Repository: shadowsocks/shadowsocks-rust Branch: master Commit: ae80b84e2262 Files: 282 Total size: 3.3 MB Directory structure: gitextract_1sakp8po/ ├── .circleci/ │ └── config.yml ├── .dockerignore ├── .github/ │ ├── dependabot.yml │ └── workflows/ │ ├── build-and-test.yml │ ├── build-docker-image.yml │ ├── build-msrv.yml │ ├── build-nightly-release.yml │ ├── build-release.yml │ ├── clippy-check.yml │ └── deny-check.yml ├── .gitignore ├── .travis.yml ├── Cargo.toml ├── Cross-centos.toml ├── Cross.toml ├── Dockerfile ├── LICENSE ├── Makefile ├── README.md ├── acl/ │ └── genacl_proxy_gfw_bypass_china_ip.py ├── appveyor.yml ├── bin/ │ ├── sslocal.rs │ ├── ssmanager.rs │ ├── ssserver.rs │ ├── ssservice.rs │ ├── ssurl.rs │ └── sswinservice.rs ├── build/ │ ├── README.md │ ├── build-host-release │ ├── build-host-release.ps1 │ └── build-release ├── cargo-publish.sh ├── clippy.toml ├── configs/ │ ├── genipset.py │ ├── iptables_mixed.sh │ ├── iptables_tproxy.sh │ ├── log4rs.yaml │ ├── org.shadowsocks.shadowsocks-rust.plist │ └── shadowsocks.procd.sh ├── crates/ │ ├── shadowsocks/ │ │ ├── Cargo.toml │ │ ├── LICENSE │ │ ├── README.md │ │ ├── src/ │ │ │ ├── config.rs │ │ │ ├── context.rs │ │ │ ├── dns_resolver/ │ │ │ │ ├── hickory_dns_resolver.rs │ │ │ │ ├── mod.rs │ │ │ │ └── resolver.rs │ │ │ ├── lib.rs │ │ │ ├── manager/ │ │ │ │ ├── client.rs │ │ │ │ ├── datagram.rs │ │ │ │ ├── error.rs │ │ │ │ ├── listener.rs │ │ │ │ ├── mod.rs │ │ │ │ └── protocol.rs │ │ │ ├── net/ │ │ │ │ ├── mod.rs │ │ │ │ ├── option.rs │ │ │ │ ├── sys/ │ │ │ │ │ ├── mod.rs │ │ │ │ │ ├── unix/ │ │ │ │ │ │ ├── bsd/ │ │ │ │ │ │ │ ├── freebsd.rs │ │ │ │ │ │ │ ├── macos.rs │ │ │ │ │ │ │ ├── mod.rs │ │ │ │ │ │ │ └── others.rs │ │ │ │ │ │ ├── linux/ │ │ │ │ │ │ │ └── mod.rs │ │ │ │ │ │ ├── mod.rs │ │ │ │ │ │ ├── others.rs │ │ │ │ │ │ └── uds.rs │ │ │ │ │ └── windows/ │ │ │ │ │ └── mod.rs │ │ │ │ ├── tcp.rs │ │ │ │ └── udp.rs │ │ │ ├── plugin/ │ │ │ │ ├── mod.rs │ │ │ │ ├── obfs_proxy.rs │ │ │ │ └── ss_plugin.rs │ │ │ ├── relay/ │ │ │ │ ├── mod.rs │ │ │ │ ├── socks5.rs │ │ │ │ ├── tcprelay/ │ │ │ │ │ ├── aead.rs │ │ │ │ │ ├── aead_2022.rs │ │ │ │ │ ├── crypto_io.rs │ │ │ │ │ ├── mod.rs │ │ │ │ │ ├── proxy_listener.rs │ │ │ │ │ ├── proxy_stream/ │ │ │ │ │ │ ├── client.rs │ │ │ │ │ │ ├── mod.rs │ │ │ │ │ │ ├── protocol/ │ │ │ │ │ │ │ ├── mod.rs │ │ │ │ │ │ │ ├── v1.rs │ │ │ │ │ │ │ └── v2.rs │ │ │ │ │ │ └── server.rs │ │ │ │ │ ├── stream.rs │ │ │ │ │ └── utils.rs │ │ │ │ └── udprelay/ │ │ │ │ ├── aead.rs │ │ │ │ ├── aead_2022.rs │ │ │ │ ├── compat.rs │ │ │ │ ├── crypto_io.rs │ │ │ │ ├── mod.rs │ │ │ │ ├── options.rs │ │ │ │ ├── proxy_socket.rs │ │ │ │ └── stream.rs │ │ │ └── security/ │ │ │ ├── mod.rs │ │ │ └── replay/ │ │ │ ├── mod.rs │ │ │ └── ppbloom.rs │ │ └── tests/ │ │ ├── tcp.rs │ │ ├── tcp_tfo.rs │ │ └── udp.rs │ └── shadowsocks-service/ │ ├── Cargo.toml │ ├── README.md │ └── src/ │ ├── acl/ │ │ ├── mod.rs │ │ └── sub_domains_tree.rs │ ├── config.rs │ ├── dns/ │ │ └── mod.rs │ ├── lib.rs │ ├── local/ │ │ ├── context.rs │ │ ├── dns/ │ │ │ ├── client_cache.rs │ │ │ ├── config.rs │ │ │ ├── dns_resolver.rs │ │ │ ├── mod.rs │ │ │ ├── server.rs │ │ │ └── upstream.rs │ │ ├── fake_dns/ │ │ │ ├── manager.rs │ │ │ ├── mod.rs │ │ │ ├── processor.rs │ │ │ ├── proto.rs │ │ │ ├── server.rs │ │ │ ├── tcp_server.rs │ │ │ └── udp_server.rs │ │ ├── http/ │ │ │ ├── config.rs │ │ │ ├── http_client.rs │ │ │ ├── http_service.rs │ │ │ ├── http_stream.rs │ │ │ ├── mod.rs │ │ │ ├── server.rs │ │ │ ├── tokio_rt.rs │ │ │ └── utils.rs │ │ ├── loadbalancing/ │ │ │ ├── mod.rs │ │ │ ├── ping_balancer.rs │ │ │ ├── server_data.rs │ │ │ └── server_stat.rs │ │ ├── mod.rs │ │ ├── net/ │ │ │ ├── mod.rs │ │ │ ├── tcp/ │ │ │ │ ├── auto_proxy_io.rs │ │ │ │ ├── auto_proxy_stream.rs │ │ │ │ ├── listener.rs │ │ │ │ └── mod.rs │ │ │ └── udp/ │ │ │ ├── association.rs │ │ │ ├── listener.rs │ │ │ └── mod.rs │ │ ├── online_config/ │ │ │ ├── content_encoding.rs │ │ │ └── mod.rs │ │ ├── redir/ │ │ │ ├── mod.rs │ │ │ ├── redir_ext.rs │ │ │ ├── server.rs │ │ │ ├── sys/ │ │ │ │ ├── mod.rs │ │ │ │ └── unix/ │ │ │ │ ├── bsd_pf.rs │ │ │ │ ├── mod.rs │ │ │ │ ├── pfvar_bindgen_freebsd.rs │ │ │ │ ├── pfvar_bindgen_macos.rs │ │ │ │ └── pfvar_bindgen_openbsd.rs │ │ │ ├── tcprelay/ │ │ │ │ ├── mod.rs │ │ │ │ └── sys/ │ │ │ │ ├── mod.rs │ │ │ │ ├── unix/ │ │ │ │ │ ├── bsd.rs │ │ │ │ │ ├── linux.rs │ │ │ │ │ ├── mod.rs │ │ │ │ │ └── not_supported.rs │ │ │ │ └── windows/ │ │ │ │ └── mod.rs │ │ │ └── udprelay/ │ │ │ ├── mod.rs │ │ │ └── sys/ │ │ │ ├── mod.rs │ │ │ ├── unix/ │ │ │ │ ├── freebsd.rs │ │ │ │ ├── linux.rs │ │ │ │ ├── macos.rs │ │ │ │ ├── mod.rs │ │ │ │ ├── not_supported.rs │ │ │ │ └── openbsd.rs │ │ │ └── windows/ │ │ │ └── mod.rs │ │ ├── socks/ │ │ │ ├── client/ │ │ │ │ ├── mod.rs │ │ │ │ ├── socks4/ │ │ │ │ │ ├── mod.rs │ │ │ │ │ └── tcp_client.rs │ │ │ │ └── socks5/ │ │ │ │ ├── mod.rs │ │ │ │ ├── tcp_client.rs │ │ │ │ └── udp_client.rs │ │ │ ├── config.rs │ │ │ ├── mod.rs │ │ │ ├── server/ │ │ │ │ ├── mod.rs │ │ │ │ ├── server.rs │ │ │ │ ├── socks4/ │ │ │ │ │ ├── mod.rs │ │ │ │ │ └── tcprelay.rs │ │ │ │ └── socks5/ │ │ │ │ ├── mod.rs │ │ │ │ ├── tcprelay.rs │ │ │ │ └── udprelay.rs │ │ │ └── socks4.rs │ │ ├── tun/ │ │ │ ├── fake_tun.rs │ │ │ ├── ip_packet.rs │ │ │ ├── mod.rs │ │ │ ├── tcp.rs │ │ │ ├── udp.rs │ │ │ └── virt_device.rs │ │ ├── tunnel/ │ │ │ ├── mod.rs │ │ │ ├── server.rs │ │ │ ├── tcprelay.rs │ │ │ └── udprelay.rs │ │ └── utils.rs │ ├── manager/ │ │ ├── mod.rs │ │ └── server.rs │ ├── net/ │ │ ├── flow.rs │ │ ├── launch_activate_socket.rs │ │ ├── mod.rs │ │ ├── mon_socket.rs │ │ ├── mon_stream.rs │ │ ├── packet_window.rs │ │ └── utils.rs │ ├── server/ │ │ ├── context.rs │ │ ├── mod.rs │ │ ├── server.rs │ │ ├── tcprelay.rs │ │ └── udprelay.rs │ ├── sys/ │ │ ├── mod.rs │ │ └── unix/ │ │ ├── macos.rs │ │ └── mod.rs │ └── utils.rs ├── debian/ │ ├── .gitignore │ ├── changelog │ ├── compat │ ├── config.json │ ├── control │ ├── copyright │ ├── install │ ├── rules │ ├── shadowsocks-rust-local@.service │ ├── shadowsocks-rust-server@.service │ ├── shadowsocks-rust.default │ ├── shadowsocks-rust.init │ ├── shadowsocks-rust.postinst │ ├── shadowsocks-rust.service │ └── source/ │ └── format ├── deny.toml ├── docker/ │ ├── Dockerfile.v2ray │ ├── docker-entrypoint.sh │ └── linux-cross/ │ └── Dockerfile ├── examples/ │ ├── config.json │ └── config_ext.json ├── homebrew/ │ └── shadowsocks-rust.rb ├── k8s/ │ ├── chart/ │ │ ├── .helmignore │ │ ├── Chart.yaml │ │ ├── templates/ │ │ │ ├── NOTES.txt │ │ │ ├── _helpers.tpl │ │ │ ├── config.yaml │ │ │ ├── deployment.yaml │ │ │ ├── hpa.yaml │ │ │ ├── service.yaml │ │ │ ├── serviceaccount.yaml │ │ │ └── tests/ │ │ │ └── test-connection.yaml │ │ └── values.yaml │ └── shadowsocks-rust.yaml ├── rustfmt.toml ├── selinux/ │ ├── README.md │ ├── shadowsocks.fc │ └── shadowsocks.te ├── snap/ │ └── snapcraft.yaml ├── src/ │ ├── allocator/ │ │ └── mod.rs │ ├── config.rs │ ├── daemonize/ │ │ ├── daemonize/ │ │ │ ├── error.rs │ │ │ └── mod.rs │ │ ├── mod.rs │ │ └── unix.rs │ ├── error.rs │ ├── lib.rs │ ├── logging/ │ │ ├── log4rs.rs │ │ ├── mod.rs │ │ └── tracing.rs │ ├── monitor/ │ │ ├── mod.rs │ │ ├── other.rs │ │ ├── unix.rs │ │ └── windows.rs │ ├── password.rs │ ├── service/ │ │ ├── genkey.rs │ │ ├── local.rs │ │ ├── manager.rs │ │ ├── mod.rs │ │ └── server.rs │ ├── sys.rs │ └── vparser/ │ └── mod.rs └── tests/ ├── dns.rs ├── http.rs ├── socks4.rs ├── socks5.rs ├── tunnel.rs └── udp.rs ================================================ FILE CONTENTS ================================================ ================================================ FILE: .circleci/config.yml ================================================ version: 2.1 orbs: windows: circleci/windows@5.1.1 jobs: build-linux: docker: - image: circleci/rust:stretch environment: OPENSSL_STATIC: "1" OPENSSL_LIB_DIR: "/usr/lib/x86_64-linux-gnu/" OPENSSL_INCLUDE_DIR: "/usr/include/x86_64-linux-gnu/" RUSTFLAGS: "-Ctarget-feature=+aes,+ssse3" steps: - checkout - run: name: "APT Install Dependencies" command: | sudo apt-get update sudo apt-get install -y build-essential - run: name: "Generate Cargo.lock" command: | rustc --version >rust-version test -e Cargo.lock || cargo generate-lockfile - restore_cache: key: cargo-cache-{{ arch }}-{{ checksum "rust-version" }}-{{ checksum "Cargo.lock" }} - run: name: "Build Release" command: BUILD_EXTRA_FEATURES="openssl-vendored local-redir" ./build-host-release no_output_timeout: 1h - save_cache: paths: - /usr/local/cargo/registry - ./target key: cargo-cache-{{ arch }}-{{ checksum "rust-version" }}-{{ checksum "Cargo.lock" }} build-windows: executor: windows/default environment: OPENSSL_STATIC: "1" OPENSSL_DIR: "C:\\OpenSSL" RUSTFLAGS: "-Ctarget-feature=+aes,+ssse3" CARGO_NET_GIT_FETCH_WITH_CLI: "true" steps: - checkout - run: name: "Install Rust" command: | $ProgressPreference = "SilentlyContinue" Invoke-WebRequest -Uri "https://win.rustup.rs/" -OutFile "C:\rustup-init.exe" & C:\rustup-init.exe -y --default-toolchain "stable-x86_64-pc-windows-msvc" --no-modify-path --profile minimal $env:Path += ";C:\Users\circleci\.cargo\bin" rustc -Vv cargo --version rustc --version | Out-File -FilePath "rust-version" if (!(Test-Path "Cargo.lock" -PathType Leaf)) { cargo generate-lockfile } - run: name: "Install OpenSSL" command: | $env:Path += ";C:\Users\circleci\.cargo\bin" $TargetTriple = (rustc -Vv | Select-String -Pattern "host: (.*)" | foreach {$_.Matches.Value}).split()[-1] if ($TargetTriple.StartsWith("x86_64-")) { $OpenSSLBits = "64" } else { $OpenSSLBits = "32" } $OpenSSLVersion = "1_1_0L" $OpenSSLFileName = "Win${OpenSSLBits}OpenSSL-${OpenSSLVersion}.exe" $ProgressPreference = "SilentlyContinue" Invoke-WebRequest -Uri "http://slproweb.com/download/${OpenSSLFileName}" -OutFile "${OpenSSLFileName}" Write-Host "* Done downloading ${OpenSSLFileName}" dir Start-Process "${OpenSSLFileName}" -ArgumentList "/SILENT /VERYSILENT /SP- /SUPPRESSMSGBOXES /DIR=C:\OpenSSL" -Wait Write-Host "* Done installing ${OpenSSLFileName}" - restore_cache: key: cargo-cache-{{ arch }}-{{ checksum "rust-version" }}-{{ checksum "Cargo.lock" }} # - run: ./build-host-release - run: name: "Package Release" command: | $ProgressPreference = "SilentlyContinue" $env:Path += ";C:\Users\circleci\.cargo\bin;." $PackageReleasePath = "${PWD}\build\release" Pushd target\release $Version = (sslocal -V).split()[-1] $TargetTriple = (rustc -Vv | Select-String -Pattern "host: (.*)" | foreach {$_.Matches.Value}).split()[-1] $PackageName = "shadowsocks-v${Version}.${TargetTriple}.zip" $PackagePath = "${PackageReleasePath}\${PackageName}" Write-Host "${Version}" Write-Host "${TargetTriple}" Write-Host "${PackagePath}" New-Item "${PackageReleasePath}" -ItemType Directory -ErrorAction SilentlyContinue $CompressParam = @{ LiteralPath = "sslocal.exe", "ssserver.exe", "ssurl.exe", "ssmanager.exe" DestinationPath = "${PackagePath}" } Compress-Archive @CompressParam Popd $PackageChecksumPath = "${PackagePath}.sha256" $PackageHash = (Get-FileHash -Path "${PackagePath}" -Algorithm SHA256).Hash "${PackageHash} ${PackageName}" | Out-File -FilePath "${PackageChecksumPath}" - save_cache: paths: - C:\Users\circleci\.cargo\registry - target key: cargo-cache-{{ arch }}-{{ checksum "rust-version" }}-{{ checksum "Cargo.lock" }} - store_artifacts: path: build\\release destination: releases - persist_to_workspace: root: build paths: - release build-docker: machine: image: ubuntu-1604:201903-01 docker_layer_caching: true steps: - checkout - run: name: "APT Install Dependencies" command: | sudo apt-get update sudo apt-get install curl - run: name: "Build docker images" command: | cd build docker build -t shadowsocks-rust:x86_64-pc-windows-gnu -f Dockerfile.x86_64-pc-windows-gnu . docker build -t shadowsocks-rust:x86_64-unknown-linux-musl -f Dockerfile.x86_64-unknown-linux-musl . docker build -t shadowsocks-rust:x86_64-unknown-linux-gnu -f Dockerfile.x86_64-unknown-linux-gnu . docker build -t shadowsocks-rust:arm-unknown-linux-gnueabihf -f Dockerfile.arm-unknown-linux-gnueabihf . docker build -t shadowsocks-rust:arm-unknown-linux-musleabi -f Dockerfile.arm-unknown-linux-musleabi . docker build -t shadowsocks-rust:aarch64-unknown-linux-gnu -f Dockerfile.aarch64-unknown-linux-gnu . - run: name: "Install Rust" command: | curl "https://sh.rustup.rs" -o "rust-init.sh" chmod +x "rust-init.sh" ./rust-init.sh -y --default-toolchain stable --no-modify-path --profile minimal export PATH="$HOME/.cargo/bin:$PATH" echo 'export PATH="$HOME/.cargo/bin:$PATH"' >> $BASH_ENV rustup --version cargo --version rustc --version - restore_cache: key: cargo-cache-{{ arch }} - run: cargo install cross - run: name: "Build Releases" command: | cd build ./build-release no_output_timeout: 2h - save_cache: paths: - /usr/local/cargo/registry - ./target key: cargo-cache-{{ arch }} - store_artifacts: path: ./build/release destination: releases - persist_to_workspace: root: build paths: - release publish-github-releases: docker: - image: circleci/golang:1.17 steps: - attach_workspace: at: /tmp/workspace - run: name: "Publish Release on GitHub" command: | ls -alh /tmp/workspace/release if [[ ! -z "${CIRCLE_TAG}" ]]; then go get github.com/tcnksm/ghr EXTRA_FLAGS="-replace" if [[ "${CIRCLE_TAG}" == *"-alpha."* ]]; then EXTRA_FLAGS="${EXTRA_FLAGS} -prerelease" fi ghr -t "${GITHUB_TOKEN}" \ -u "${CIRCLE_PROJECT_USERNAME}" -r "${CIRCLE_PROJECT_REPONAME}" \ -c "${CIRCLE_SHA1}" \ ${EXTRA_FLAGS} \ "${CIRCLE_TAG}" /tmp/workspace/release else echo "Current build is not tagged." fi workflows: version: 2 build-releases: jobs: - build-linux: filters: tags: only: /^v\d+\.\d+\.\d+(-alpha\.\d+)?$/ - build-windows: filters: tags: only: /^v\d+\.\d+\.\d+(-alpha\.\d+)?$/ - build-docker: filters: branches: ignore: /.*/ tags: only: /^v\d+\.\d+\.\d+(-alpha\.\d+)?$/ - publish-github-releases: requires: - build-windows - build-docker filters: branches: ignore: /.*/ tags: only: /^v\d+\.\d+\.\d+(-alpha\.\d+)?$/ ================================================ FILE: .dockerignore ================================================ **/.git .circleci .devcontainer .github .ssh .vscode **/target dev ================================================ FILE: .github/dependabot.yml ================================================ version: 2 updates: - package-ecosystem: cargo directory: "/" schedule: interval: weekly open-pull-requests-limit: 0 ================================================ FILE: .github/workflows/build-and-test.yml ================================================ name: Build & Test on: [push, pull_request] env: CARGO_TERM_COLOR: always RUST_LOG: "trace" jobs: build-and-test: strategy: matrix: platform: - ubuntu-latest - windows-latest - macos-latest runs-on: ${{ matrix.platform }} steps: - if: ${{ matrix.platform == 'ubuntu-latest' }} name: Free Disk Space (Ubuntu) uses: jlumbroso/free-disk-space@main - uses: actions/checkout@v6 - uses: Swatinem/rust-cache@v2 - if: ${{ runner.os == 'Windows' }} uses: ilammy/setup-nasm@v1 - if: ${{ matrix.platform == 'ubuntu-latest' }} name: Install LLVM and Clang run: sudo apt update && sudo apt install -y clang - name: Install Rust run: | rustup set profile minimal rustup toolchain install stable rustup default stable rustup override set stable - name: Build & Test (Default) run: cargo test --verbose --no-fail-fast - name: Build & Test (full) run: cargo test --features "full" --verbose --no-fail-fast - name: Build & Test (full-extra) run: cargo test --features "full-extra" --verbose --no-fail-fast - name: Build & Test (Default) - shadowsocks run: cargo test --manifest-path ./crates/shadowsocks/Cargo.toml --verbose --no-fail-fast - name: Build & Test (Default) - shadowsocks-service run: cargo test --manifest-path ./crates/shadowsocks-service/Cargo.toml --verbose --no-fail-fast - name: Build & Test (--no-default-features) run: cargo test --verbose --no-default-features --no-fail-fast - name: Build & Test (--no-default-features) - shadowsocks run: cargo test --manifest-path ./crates/shadowsocks/Cargo.toml --verbose --no-default-features --no-fail-fast - name: Build & Test (--no-default-features) - shadowsocks-service run: cargo test --manifest-path ./crates/shadowsocks-service/Cargo.toml --verbose --no-default-features --no-fail-fast - name: Build with All Features Enabled (Unix) if: ${{ runner.os == 'Linux' || runner.os == 'macOS' }} run: cargo build --verbose --features "full-extra local-flow-stat utility-url-outline" - name: Build with All Features Enabled (Windows) if: ${{ runner.os == 'Windows' }} run: cargo build --verbose --features "full-extra local-flow-stat utility-url-outline winservice" - name: Build with All Features Enabled - shadowsocks run: cargo build --manifest-path ./crates/shadowsocks/Cargo.toml --verbose --features "stream-cipher aead-cipher-extra aead-cipher-2022 aead-cipher-2022-extra security-replay-attack-detect" ================================================ FILE: .github/workflows/build-docker-image.yml ================================================ name: Build Docker Images on: push: tags: - v* workflow_dispatch: jobs: build-docker-image: runs-on: ubuntu-latest strategy: matrix: bin: - ssserver - sslocal steps: - name: Checkout uses: actions/checkout@v6 - name: Setup Docker Buildx uses: docker/setup-buildx-action@v4 - name: Login to GitHub Container Registry uses: docker/login-action@v4 with: registry: ghcr.io username: ${{ github.repository_owner }} password: ${{ secrets.GITHUB_TOKEN }} - name: Docker metadata id: metadata uses: docker/metadata-action@v6 with: images: ghcr.io/${{ github.repository_owner }}/${{ matrix.bin }}-rust - name: Build and release Docker images uses: docker/build-push-action@v7 with: platforms: linux/386,linux/amd64,linux/arm64/v8 target: ${{ matrix.bin }} tags: ${{ steps.metadata.outputs.tags }} push: true ================================================ FILE: .github/workflows/build-msrv.yml ================================================ name: Build MSRV on: [push, pull_request] env: CARGO_TERM_COLOR: always RUST_LOG: "trace" jobs: build-msrv-shadowsocks-rust: strategy: matrix: platform: - ubuntu-latest - windows-latest - macos-latest runs-on: ${{ matrix.platform }} steps: - if: ${{ matrix.platform == 'ubuntu-latest' }} name: Free Disk Space (Ubuntu) uses: jlumbroso/free-disk-space@main - if: ${{ matrix.platform == 'ubuntu-latest' }} name: Install LLVM and Clang run: sudo apt update && sudo apt install -y clang - uses: actions/checkout@v6 - uses: Swatinem/rust-cache@v2 - if: ${{ runner.os == 'Windows' }} uses: ilammy/setup-nasm@v1 - name: Install Rust run: | rustup set profile minimal rustup toolchain install 1.88 rustup default 1.88 rustup override set 1.88 - name: Build with All Features Enabled (Unix) if: ${{ runner.os == 'Linux' || runner.os == 'macOS' }} run: cargo build --verbose --features "full-extra local-flow-stat utility-url-outline" - name: Build with All Features Enabled (Windows) if: ${{ runner.os == 'Windows' }} run: cargo build --verbose --features "full-extra local-flow-stat utility-url-outline winservice" build-msrv-shadowsocks-service: strategy: matrix: platform: - ubuntu-latest - windows-latest - macos-latest runs-on: ${{ matrix.platform }} steps: - if: ${{ matrix.platform == 'ubuntu-latest' }} name: Free Disk Space (Ubuntu) uses: jlumbroso/free-disk-space@main - if: ${{ matrix.platform == 'ubuntu-latest' }} name: Install LLVM and Clang run: sudo apt update && sudo apt install -y clang - uses: actions/checkout@v6 - uses: Swatinem/rust-cache@v2 - if: ${{ runner.os == 'Windows' }} uses: ilammy/setup-nasm@v1 - name: Install Rust run: | rustup set profile minimal rustup toolchain install 1.88 rustup default 1.88 rustup override set 1.88 - name: Build with All Features Enabled run: cargo build --manifest-path crates/shadowsocks-service/Cargo.toml --verbose --features "full dns-over-tls dns-over-https dns-over-h3 local-dns local-flow-stat local-http-rustls local-tun local-fake-dns local-online-config stream-cipher aead-cipher-extra aead-cipher-2022 aead-cipher-2022-extra security-replay-attack-detect" build-msrv-shadowsocks: strategy: matrix: platform: - ubuntu-latest - windows-latest - macos-latest runs-on: ${{ matrix.platform }} steps: - if: ${{ matrix.platform == 'ubuntu-latest' }} name: Free Disk Space (Ubuntu) uses: jlumbroso/free-disk-space@main - if: ${{ matrix.platform == 'ubuntu-latest' }} name: Install LLVM and Clang run: sudo apt update && sudo apt install -y clang - uses: actions/checkout@v6 - uses: Swatinem/rust-cache@v2 - if: ${{ runner.os == 'Windows' }} uses: ilammy/setup-nasm@v1 - name: Install Rust run: | rustup set profile minimal rustup toolchain install 1.88 rustup default 1.88 rustup override set 1.88 - name: Build with All Features Enabled run: cargo build --manifest-path crates/shadowsocks/Cargo.toml --verbose --features "stream-cipher aead-cipher-extra aead-cipher-2022 aead-cipher-2022-extra security-replay-attack-detect" ================================================ FILE: .github/workflows/build-nightly-release.yml ================================================ name: Build Nightly Releases on: push: branches: [master] workflow_dispatch: env: CARGO_TERM_COLOR: always jobs: build-nightly-cross: runs-on: ubuntu-latest env: RUST_BACKTRACE: full strategy: fail-fast: false matrix: platform: - target: x86_64-unknown-linux-gnu toolchain: stable - target: x86_64-unknown-linux-musl toolchain: stable - target: aarch64-unknown-linux-gnu toolchain: stable - target: aarch64-unknown-linux-musl toolchain: stable - target: mips-unknown-linux-gnu toolchain: nightly - target: mipsel-unknown-linux-gnu toolchain: nightly - target: mips64el-unknown-linux-gnuabi64 toolchain: nightly - target: x86_64-unknown-freebsd toolchain: stable - target: x86_64-unknown-netbsd toolchain: stable - target: loongarch64-unknown-linux-gnu toolchain: stable - target: loongarch64-unknown-linux-musl toolchain: stable - target: powerpc-unknown-linux-gnu toolchain: stable - target: powerpc64-unknown-linux-gnu toolchain: stable - target: powerpc64le-unknown-linux-gnu toolchain: stable - target: riscv64gc-unknown-linux-gnu toolchain: stable - target: riscv64gc-unknown-linux-musl toolchain: stable - target: aarch64-linux-android toolchain: stable - target: x86_64-linux-android toolchain: stable steps: - name: Free Disk Space (Ubuntu) uses: jlumbroso/free-disk-space@main - name: Install LLVM and Clang run: sudo apt update && sudo apt install -y clang - uses: actions/checkout@v6 - name: Install Rust run: | rustup set profile minimal rustup toolchain install ${{ matrix.platform.toolchain }} rustup default ${{ matrix.platform.toolchain }} rustup override set ${{ matrix.platform.toolchain }} - name: Install cross run: cargo install cross --git https://github.com/cross-rs/cross - name: Build ${{ matrix.platform.target }} timeout-minutes: 120 run: | compile_target=${{ matrix.platform.target }} compile_features="-f full" if [[ "$compile_target" == *"-windows-"* ]]; then compile_features="$compile_features -f winservice" fi if [[ "$compile_target" == "mips-"* || "$compile_target" == "mipsel-"* || "$compile_target" == "mips64-"* || "$compile_target" == "mips64el-"* ]]; then sudo apt-get update -y && sudo apt-get install -y upx; if [[ "$?" == "0" ]]; then compile_compress="-u" fi compile_nightly="-n" #compile_cargo_flags="-Z build-std=std,panic_abort,proc_macro" fi cd build ./build-release -t ${{ matrix.platform.target }} $compile_features $compile_compress $compile_nightly $compile_cargo_flags - name: Upload Artifacts uses: actions/upload-artifact@v7 with: name: ${{ matrix.platform.target }} path: build/release/* build-nightly-unix: runs-on: ${{ matrix.os }} env: BUILD_EXTRA_FEATURES: "full" RUST_BACKTRACE: full strategy: fail-fast: false matrix: os: [macos-latest] target: - x86_64-apple-darwin - aarch64-apple-darwin steps: - uses: actions/checkout@v6 - name: Install GNU tar if: runner.os == 'macOS' run: | brew install gnu-tar # echo "::add-path::/usr/local/opt/gnu-tar/libexec/gnubin" echo "/usr/local/opt/gnu-tar/libexec/gnubin" >> $GITHUB_PATH - name: Install Rust run: | rustup set profile minimal rustup toolchain install stable rustup default stable rustup override set stable rustup target add --toolchain stable ${{ matrix.target }} - name: Build release shell: bash run: | ./build/build-host-release -t ${{ matrix.target }} - name: Upload Artifacts uses: actions/upload-artifact@v7 with: name: ${{ matrix.target }} path: build/release/* build-nightly-windows: runs-on: windows-latest env: RUSTFLAGS: "-C target-feature=+crt-static" RUST_BACKTRACE: full steps: - uses: actions/checkout@v6 - uses: ilammy/setup-nasm@v1 - name: Install Rust run: | rustup set profile minimal rustup toolchain install stable rustup default stable rustup override set stable - name: Build release run: | pwsh ./build/build-host-release.ps1 "full winservice" - name: Upload Artifacts uses: actions/upload-artifact@v7 with: name: windows-native path: build/release/* ================================================ FILE: .github/workflows/build-release.yml ================================================ name: Build Releases on: push: tags: - v* workflow_dispatch: inputs: tag: description: 'Release Tag' required: true type: string env: CARGO_TERM_COLOR: always jobs: build-release-cross: runs-on: ubuntu-latest env: RUST_BACKTRACE: full strategy: fail-fast: false matrix: platform: - target: i686-unknown-linux-musl toolchain: stable - target: x86_64-pc-windows-gnu toolchain: stable - target: x86_64-unknown-linux-gnu toolchain: stable - target: x86_64-unknown-linux-musl toolchain: stable - target: armv7-unknown-linux-musleabihf toolchain: stable - target: armv7-unknown-linux-gnueabihf toolchain: stable - target: arm-unknown-linux-gnueabi toolchain: stable - target: arm-unknown-linux-gnueabihf toolchain: stable - target: arm-unknown-linux-musleabi toolchain: stable - target: arm-unknown-linux-musleabihf toolchain: stable - target: aarch64-unknown-linux-gnu toolchain: stable - target: aarch64-unknown-linux-musl toolchain: stable - target: mips-unknown-linux-gnu toolchain: nightly # cross mips-*-musl images are disabled # - target: mips-unknown-linux-musl # toolchain: nightly - target: mipsel-unknown-linux-gnu toolchain: nightly # - target: mipsel-unknown-linux-musl # toolchain: nightly # FIXME: ring doesn't support mips64 CPU # - target: mips64-unknown-linux-gnuabi64 # toolchain: nightly # - target: mips64-unknown-linux-muslabi64 # toolchain: nightly - target: mips64el-unknown-linux-gnuabi64 toolchain: nightly # FIXME: Link Error. # = note: mips64el-linux-muslsf-gcc: error: crt1.o: No such file or directory # mips64el-linux-muslsf-gcc: error: crti.o: No such file or directory # mips64el-linux-muslsf-gcc: error: crtbegin.o: No such file or directory # mips64el-linux-muslsf-gcc: error: crtend.o: No such file or directory # mips64el-linux-muslsf-gcc: error: crtn.o: No such file or directory # - target: mips64el-unknown-linux-muslabi64 # toolchain: nightly - target: x86_64-unknown-freebsd toolchain: stable - target: x86_64-unknown-netbsd toolchain: stable - target: loongarch64-unknown-linux-gnu toolchain: stable - target: loongarch64-unknown-linux-musl toolchain: stable - target: riscv64gc-unknown-linux-gnu toolchain: stable - target: riscv64gc-unknown-linux-musl toolchain: stable - target: aarch64-linux-android toolchain: stable - target: x86_64-linux-android toolchain: stable steps: - name: Free Disk Space (Ubuntu) uses: jlumbroso/free-disk-space@main - name: Install LLVM and Clang run: sudo apt update && sudo apt install -y clang - uses: actions/checkout@v6 - name: Install Rust run: | rustup set profile minimal rustup toolchain install ${{ matrix.platform.toolchain }} rustup default ${{ matrix.platform.toolchain }} rustup override set ${{ matrix.platform.toolchain }} - name: Install cross run: cargo install cross --git https://github.com/cross-rs/cross - name: Build ${{ matrix.platform.target }} timeout-minutes: 120 run: | compile_target=${{ matrix.platform.target }} compile_features="-f full" if [[ "$compile_target" == *"-windows-"* ]]; then compile_features="$compile_features -f winservice" fi if [[ "$compile_target" == "mips-"* || "$compile_target" == "mipsel-"* || "$compile_target" == "mips64-"* || "$compile_target" == "mips64el-"* ]]; then sudo apt-get update -y && sudo apt-get install -y upx; if [[ "$?" == "0" ]]; then compile_compress="-u" fi compile_nightly="-n" #compile_cargo_flags="-Z build-std=std,panic_abort,proc_macro" fi cd build ./build-release -t ${{ matrix.platform.target }} $compile_features $compile_compress $compile_nightly $compile_cargo_flags - name: Upload Github Assets uses: softprops/action-gh-release@v2 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: files: build/release/* prerelease: ${{ contains(github.ref_name, '-') }} tag_name: ${{ inputs.tag || github.ref_name }} build-release-unix: runs-on: ${{ matrix.os }} env: BUILD_EXTRA_FEATURES: "full" RUST_BACKTRACE: full strategy: fail-fast: false matrix: # os: [ubuntu-latest, macos-latest] os: [macos-latest] target: - x86_64-apple-darwin - aarch64-apple-darwin steps: - uses: actions/checkout@v6 - name: Install GNU tar if: runner.os == 'macOS' run: | brew install gnu-tar # echo "::add-path::/usr/local/opt/gnu-tar/libexec/gnubin" echo "/usr/local/opt/gnu-tar/libexec/gnubin" >> $GITHUB_PATH - name: Install Rust run: | rustup set profile minimal rustup toolchain install stable rustup default stable rustup override set stable rustup target add --toolchain stable ${{ matrix.target }} - name: Build release shell: bash run: | ./build/build-host-release -t ${{ matrix.target }} - name: Upload Github Assets uses: softprops/action-gh-release@v2 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: files: build/release/* prerelease: ${{ contains(github.ref_name, '-') }} tag_name: ${{ inputs.tag || github.ref_name }} build-release-windows: runs-on: windows-latest env: RUSTFLAGS: "-C target-feature=+crt-static" RUST_BACKTRACE: full steps: - uses: actions/checkout@v6 - uses: ilammy/setup-nasm@v1 - name: Install Rust run: | rustup set profile minimal rustup toolchain install stable rustup default stable rustup override set stable - name: Build release run: | pwsh ./build/build-host-release.ps1 "full winservice" - name: Upload Github Assets uses: softprops/action-gh-release@v2 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: files: build/release/* prerelease: ${{ contains(github.ref_name, '-') }} tag_name: ${{ inputs.tag || github.ref_name }} ================================================ FILE: .github/workflows/clippy-check.yml ================================================ name: Clippy Check on: [push, pull_request] env: CARGO_TERM_COLOR: always RUST_LOG: "trace" jobs: clippy-check: strategy: matrix: platform: - ubuntu-latest - windows-latest - macos-latest runs-on: ${{ matrix.platform }} steps: - uses: actions/checkout@v6 - uses: Swatinem/rust-cache@v2 - if: ${{ runner.os == 'Windows' }} uses: ilammy/setup-nasm@v1 - name: Install Rust run: | rustup set profile minimal rustup toolchain install stable --component clippy - name: Clippy Check uses: actions-rs/clippy-check@v1 with: token: ${{ secrets.GITHUB_TOKEN }} args: | --features "full-extra local-flow-stat utility-url-outline" -- -A clippy::absurd_extreme_comparisons name: clippy ${{ matrix.platform }} ================================================ FILE: .github/workflows/deny-check.yml ================================================ name: Cargo Deny Check on: [push, pull_request] jobs: deny-check: runs-on: ubuntu-latest strategy: matrix: checks: - advisories - bans licenses sources # Prevent sudden announcement of a new advisory from failing ci: continue-on-error: ${{ matrix.checks == 'advisories' }} steps: - uses: actions/checkout@v6 - uses: EmbarkStudios/cargo-deny-action@v2 with: command: check ${{ matrix.checks }} ================================================ FILE: .gitignore ================================================ target /build/release /build/target /build/install /build/*.sha256 /dev /*.log /debian/*.log /.vscode /*.json /restart.sh /udp_echo_server.py /.idea /.devcontainer .DS_Store ================================================ FILE: .travis.yml ================================================ sudo: false language: rust jobs: include: - os: windows rust: stable - os: osx rust: stable osx_image: xcode11.3 env: SODIUM_USE_PKG_CONFIG=1 - os: linux rust: stable dist: bionic env: SODIUM_USE_PKG_CONFIG=1 - os: linux rust: beta dist: bionic env: SODIUM_USE_PKG_CONFIG=1 - os: linux rust: nightly dist: bionic env: SODIUM_USE_PKG_CONFIG=1 allow_failures: # FIXME: Travis build success but tests crash - os: osx - os: windows env: - RUSTFLAGS="-Ctarget-feature=+aes,+ssse3" RUSTDOCFLAGS="-Ctarget-feature=+aes,+ssse3" RUST_BACKTRACE=1 addons: apt: packages: - libssl-dev - libsodium-dev homebrew: packages: - libsodium install: # Install OpenSSL on Windows - if [ "${TRAVIS_OS_NAME}" = "windows" ]; then curl -Lo "openssl-1.0.2c-win64-mingw.zip" "https://dl.bintray.com/vszakats/generic/openssl-1.0.2c-win64-mingw.zip"; unzip "openssl-1.0.2c-win64-mingw.zip" -d "/c/OpenSSL"; export OPENSSL_LIB_DIR=/c/OpenSSL/openssl-1.0.2c-win64-mingw; export OPENSSL_INCLUDE_DIR=/c/OpenSSL/openssl-1.0.2c-win64-mingw/include; export OPENSSL_DIR=/c/OpenSSL/openssl-1.0.2c-win64-mingw; fi # - if [ "${TRAVIS_OS_NAME}" = "windows" ]; then # choco install openssl; # export OPENSSL_DIR='/c/Program Files/OpenSSL-Win64/'; # export OPENSSL_STATIC=1; # fi script: - cargo test --no-fail-fast # - cargo test --no-fail-fast --no-default-features # - cargo test --no-fail-fast --features aes-pmac-siv # - cargo test --no-fail-fast --features single-threaded # - cargo test --no-fail-fast --features openssl-vendored # - cargo test --no-fail-fast --no-default-features --features "local-http local-http-rustls" - if [ "${TRAVIS_OS_NAME}" = "linux" -o "${TRAVIS_OS_NAME}" = "osx" ]; then cargo test --no-fail-fast --features local-redir; fi # cache: cargo ================================================ FILE: Cargo.toml ================================================ [package] name = "shadowsocks-rust" version = "1.24.0" authors = ["Shadowsocks Contributors"] description = "shadowsocks is a fast tunnel proxy that helps you bypass firewalls." repository = "https://github.com/shadowsocks/shadowsocks-rust" readme = "README.md" documentation = "https://docs.rs/shadowsocks-rust" keywords = ["shadowsocks", "proxy", "socks", "socks5", "firewall"] license = "MIT" edition = "2024" rust-version = "1.88" [badges] maintenance = { status = "passively-maintained" } [[bin]] name = "sslocal" path = "bin/sslocal.rs" required-features = ["local"] [[bin]] name = "ssserver" path = "bin/ssserver.rs" required-features = ["server"] [[bin]] name = "ssurl" path = "bin/ssurl.rs" required-features = ["utility"] [[bin]] name = "ssmanager" path = "bin/ssmanager.rs" required-features = ["manager"] [[bin]] name = "ssservice" path = "bin/ssservice.rs" required-features = ["service"] [[bin]] name = "sswinservice" path = "bin/sswinservice.rs" required-features = ["winservice"] [workspace] members = ["crates/shadowsocks", "crates/shadowsocks-service"] [profile.release] lto = "fat" codegen-units = 1 incremental = false panic = "abort" strip = true [features] default = ["full"] # Basic Features basic = [ "logging", "hickory-dns", "local", "server", "multi-threaded", "aead-cipher", ] # All Suggested Features full = [ "logging", "hickory-dns", "dns-over-tls", "dns-over-https", "local", "server", "manager", "utility", "service", "local-http", "local-http-rustls", "local-tunnel", "local-socks4", "local-dns", "local-redir", "local-tun", "local-online-config", "multi-threaded", "stream-cipher", "aead-cipher", "aead-cipher-2022", ] # Full features with extra (non-stable) full-extra = [ "full", "dns-over-h3", "local-fake-dns", "aead-cipher-extra", "aead-cipher-2022-extra", "security-replay-attack-detect", ] # Enable local server local = ["shadowsocks-service/local"] # Enable remote server server = ["shadowsocks-service/server"] # Enable manager server manager = ["shadowsocks-service/manager"] # Enable utility utility = ["qrcode"] # Enable service service = ["local", "server", "manager"] # Enable Windows Service winservice = ["service", "windows-service"] # Enables Hickory-DNS for replacing tokio's builtin DNS resolver hickory-dns = ["shadowsocks-service/hickory-dns"] # Hickory-DNS was renamed from Trust-DNS, keep compatibility. trust-dns = ["hickory-dns"] dns-over-tls = ["shadowsocks-service/dns-over-tls"] dns-over-https = ["shadowsocks-service/dns-over-https"] dns-over-h3 = ["shadowsocks-service/dns-over-h3"] # Enable logging output logging = [ "log4rs", "tracing", "tracing-subscriber", "time", "tracing-appender", "tracing-syslog", ] # Enable DNS-relay local-dns = ["local", "shadowsocks-service/local-dns"] # Enable client flow statistic report # Currently is only used in Android local-flow-stat = ["local", "shadowsocks-service/local-flow-stat"] # Enable HTTP protocol for sslocal local-http = ["local", "shadowsocks-service/local-http"] local-http-native-tls = [ "local-http", "shadowsocks-service/local-http-native-tls", ] local-http-native-tls-vendored = [ "local-http", "shadowsocks-service/local-http-native-tls-vendored", ] local-http-rustls = ["local-http", "shadowsocks-service/local-http-rustls"] # Enable REDIR protocol for sslocal # (transparent proxy) local-redir = ["local", "shadowsocks-service/local-redir"] # Enable tunnel protocol for sslocal local-tunnel = ["local", "shadowsocks-service/local-tunnel"] # Enable socks4 protocol for sslocal local-socks4 = ["local", "shadowsocks-service/local-socks4"] # Enable Tun interface protocol for sslocal local-tun = ["local", "shadowsocks-service/local-tun", "ipnet"] # Enable Fake DNS for sslocal local-fake-dns = ["local", "shadowsocks-service/local-fake-dns", "ipnet"] # sslocal support online URL (SIP008 Online Configuration Delivery) # https://shadowsocks.org/doc/sip008.html local-online-config = ["local", "shadowsocks-service/local-online-config"] # ssurl support outline (ssconf) URL utility-url-outline = ["reqwest"] # Enable jemalloc for binaries jemalloc = ["jemallocator"] # Enable bundled tcmalloc tcmalloc-vendored = ["tcmalloc/bundled"] # Enable snmalloc for binaries snmalloc = ["snmalloc-rs"] # Enable tokio's multi-threaded runtime multi-threaded = ["tokio/rt-multi-thread"] # Enable Stream Cipher Protocol # WARN: Stream Cipher Protocol is proved to be insecure # https://github.com/shadowsocks/shadowsocks-rust/issues/373 # Users should always avoid using these ciphers in practice stream-cipher = ["shadowsocks-service/stream-cipher"] # Enable AEAD ciphers aead-cipher = ["shadowsocks-service/aead-cipher"] # Enable extra AEAD ciphers # WARN: These non-standard AEAD ciphers are not officially supported by shadowsocks community aead-cipher-extra = ["aead-cipher", "shadowsocks-service/aead-cipher-extra"] # Enable AEAD 2022 aead-cipher-2022 = ["shadowsocks-service/aead-cipher-2022"] # Enable AEAD 2022 with extra ciphers aead-cipher-2022-extra = ["shadowsocks-service/aead-cipher-2022-extra"] # Enable detection against replay attack (Stream / AEAD) security-replay-attack-detect = [ "shadowsocks-service/security-replay-attack-detect", ] replay-attack-detect = [ "security-replay-attack-detect", ] # Backward compatibility. DO NOT USE. # Logging to syslog (Unix only) tracing-syslog = ["dep:syslog-tracing"] [dependencies] log = "0.4" log4rs = { version = "1.2", optional = true } tracing = { version = "0.1", optional = true } tracing-subscriber = { version = "0.3", optional = true, features = [ "std", "fmt", "env-filter", "time", "local-time", ] } tracing-appender = { version = "0.2.3", optional = true, default-features = false } syslog-tracing = { version = "0.3", optional = true } time = { version = "0.3", optional = true } serde = { version = "1.0", features = ["derive"] } json5 = "1.3" thiserror = "2.0" base64 = "0.22" clap = { version = "4.5", features = ["wrap_help", "suggestions"] } cfg-if = "1" qrcode = { version = "0.14", default-features = false, optional = true } sysexits = "0.13" build-time = "0.1" directories = "6.0" rpassword = "7.3" libc = { version = "0.2", features = ["extra_traits"] } rand = "0.10" futures = "0.3" tokio = { version = "1", features = ["rt", "signal"] } ipnet = { version = "2.10", optional = true } reqwest = { version = "0.13", features = ["blocking"], optional = true } mimalloc = { version = "0.1", default-features = false, optional = true } tcmalloc = { version = "0.3", optional = true } jemallocator = { version = "0.5", optional = true } snmalloc-rs = { version = "0.3", optional = true } rpmalloc = { version = "0.2", optional = true } shadowsocks-service = { version = "1.24.0", path = "./crates/shadowsocks-service", default-features = false } windows-service = { version = "0.8", optional = true } [target.'cfg(unix)'.dependencies] xdg = "3.0" [dev-dependencies] byteorder = "1.5" env_logger = "0.11" byte_string = "1.0" tokio = { version = "1", features = ["net", "time", "macros", "io-util"] } [lints.clippy] uninlined_format_args = "allow" ================================================ FILE: Cross-centos.toml ================================================ [build.env] passthrough = ["RUSTFLAGS"] # WARN: GCC 4.8.2 doesn't support [target.x86_64-unknown-linux-gnu] image = "ghcr.io/cross-rs/x86_64-unknown-linux-gnu:main-centos" # GCC 4.8.2 doesn't support ACLE # https://github.com/briansmith/ring/issues/1728 # [target.aarch64-unknown-linux-gnu] # image = "ghcr.io/cross-rs/aarch64-unknown-linux-gnu:main-centos" ================================================ FILE: Cross.toml ================================================ [build] # dockerfile = "./docker/linux-cross/Dockerfile" # pre-build = [ # "curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --profile minimal --default-toolchain stable", # ". $HOME/.cargo/env", # "cargo install --force --locked bindgen-cli && mv $HOME/.cargo/bin/bindgen /usr/bin", # "rm -rf $HOME/.cargo" # ] # pre-build = [ # "apt update", # "apt install --assume-yes --no-install-recommends build-essential llvm-8-dev libclang-8-dev clang-8", # ] [build.env] passthrough = ["RUSTFLAGS"] # MIPS targets are dropped to Tier 3 # https://github.com/rust-lang/compiler-team/issues/648 # FIXME: build-std with sequence is supported only on git [target.mips-unknown-linux-gnu] build-std = ["std", "panic_abort", "proc_macro"] [target.mips-unknown-linux-musl] build-std = ["std", "panic_abort", "proc_macro"] [target.mips64-unknown-linux-gnuabi64] build-std = ["std", "panic_abort", "proc_macro"] [target.mips64-unknown-linux-muslabi64] build-std = ["std", "panic_abort", "proc_macro"] [target.mips64el-unknown-linux-gnuabi64] build-std = ["std", "panic_abort", "proc_macro"] [target.mips64el-unknown-linux-muslabi64] build-std = ["std", "panic_abort", "proc_macro"] [target.mipsel-unknown-linux-gnu] build-std = ["std", "panic_abort", "proc_macro"] [target.mipsel-unknown-linux-musl] build-std = ["std", "panic_abort", "proc_macro"] ================================================ FILE: Dockerfile ================================================ FROM --platform=$BUILDPLATFORM rust:1.94.0-alpine3.22 AS builder ARG TARGETARCH RUN set -x \ && apk add --no-cache musl-dev WORKDIR /root/shadowsocks-rust ADD . . RUN case "$TARGETARCH" in \ "386") \ RUST_TARGET="i686-unknown-linux-musl" \ MUSL="i686-linux-musl" \ SHA512="5047afc68170a2910895db2dfa448227e71a984bfa2130a1bc946fd1015d722b80b15e4abf90c64300815aa84fe781cc8b8a72f10174f9dce96169e035911880" \ ;; \ "amd64") \ RUST_TARGET="x86_64-unknown-linux-musl" \ MUSL="x86_64-linux-musl" \ SHA512="52abd1a56e670952116e35d1a62e048a9b6160471d988e16fa0e1611923dd108a581d2e00874af5eb04e4968b1ba32e0eb449a1f15c3e4d5240ebe09caf5a9f3" \ ;; \ "arm64") \ RUST_TARGET="aarch64-unknown-linux-musl" \ MUSL="aarch64-linux-musl" \ SHA512="8695ff86979cdf30fbbcd33061711f5b1ebc3c48a87822b9ca56cde6d3a22abd4dab30fdcd1789ac27c6febbaeb9e5bde59d79d66552fae53d54cc1377a19272" \ ;; \ *) \ echo "Doesn't support $TARGETARCH architecture" \ exit 1 \ ;; \ esac \ && wget "https://github.com/AaronChen0/musl-cc-mirror/releases/download/2021-09-23/$MUSL-cross.tgz" \ && ( echo "$SHA512" "$MUSL-cross.tgz" | sha512sum -c ) \ && tar -xzf "$MUSL-cross.tgz" -C /root/ \ && PATH="/root/$MUSL-cross/bin:$PATH" \ && CC=/root/$MUSL-cross/bin/$MUSL-gcc \ && echo "CC=$CC" \ && rustup target add "$RUST_TARGET" \ && RUSTFLAGS="-C linker=$CC" CC=$CC cargo build --target "$RUST_TARGET" --release --features "full" \ && mv target/$RUST_TARGET/release/ss* target/release/ FROM alpine:3.23 AS sslocal # NOTE: Please be careful to change the path of these binaries, refer to #1149 for more information. COPY --from=builder /root/shadowsocks-rust/target/release/sslocal /usr/bin/ COPY --from=builder /root/shadowsocks-rust/examples/config.json /etc/shadowsocks-rust/ COPY --from=builder /root/shadowsocks-rust/docker/docker-entrypoint.sh /usr/bin/ ENTRYPOINT [ "docker-entrypoint.sh" ] CMD [ "sslocal", "--log-without-time", "-c", "/etc/shadowsocks-rust/config.json" ] FROM alpine:3.23 AS ssserver COPY --from=builder /root/shadowsocks-rust/target/release/ssserver /usr/bin/ COPY --from=builder /root/shadowsocks-rust/examples/config.json /etc/shadowsocks-rust/ COPY --from=builder /root/shadowsocks-rust/docker/docker-entrypoint.sh /usr/bin/ ENTRYPOINT [ "docker-entrypoint.sh" ] CMD [ "ssserver", "--log-without-time", "-a", "nobody", "-c", "/etc/shadowsocks-rust/config.json" ] ================================================ FILE: LICENSE ================================================ The MIT License (MIT) Copyright (c) 2017 Y. T. CHUNG 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. ================================================ FILE: Makefile ================================================ PREFIX ?= /usr/local/bin TARGET ?= debug .PHONY: all build install uninstall clean all: build build: ifeq (${TARGET}, release) cargo build --release --features "full" else cargo build --features "full" endif install: install -d ${DESTDIR}${PREFIX} install -m 755 target/${TARGET}/sslocal ${DESTDIR}${PREFIX}/sslocal install -m 755 target/${TARGET}/ssserver ${DESTDIR}${PREFIX}/ssserver install -m 755 target/${TARGET}/ssurl ${DESTDIR}${PREFIX}/ssurl install -m 755 target/${TARGET}/ssmanager ${DESTDIR}${PREFIX}/ssmanager install -m 755 target/${TARGET}/ssservice ${DESTDIR}${PREFIX}/ssservice uninstall: rm ${DESTDIR}${PREFIX}/sslocal rm ${DESTDIR}${PREFIX}/ssserver rm ${DESTDIR}${PREFIX}/ssurl rm ${DESTDIR}${PREFIX}/ssmanager rm ${DESTDIR}${PREFIX}/ssservice clean: cargo clean ================================================ FILE: README.md ================================================ # shadowsocks [![License](https://img.shields.io/github/license/zonyitoo/shadowsocks-rust.svg)](https://github.com/zonyitoo/shadowsocks-rust) [![Build & Test](https://github.com/shadowsocks/shadowsocks-rust/actions/workflows/build-and-test.yml/badge.svg)](https://github.com/shadowsocks/shadowsocks-rust/actions/workflows/build-and-test.yml) [![Build MSRV](https://github.com/shadowsocks/shadowsocks-rust/actions/workflows/build-msrv.yml/badge.svg)](https://github.com/shadowsocks/shadowsocks-rust/actions/workflows/build-msrv.yml) [![Build Releases](https://github.com/shadowsocks/shadowsocks-rust/actions/workflows/build-release.yml/badge.svg?event=push)](https://github.com/shadowsocks/shadowsocks-rust/actions/workflows/build-release.yml) [![Build Nightly Releases](https://github.com/shadowsocks/shadowsocks-rust/actions/workflows/build-nightly-release.yml/badge.svg)](https://github.com/shadowsocks/shadowsocks-rust/actions/workflows/build-nightly-release.yml) [![Gurubase](https://img.shields.io/badge/Gurubase-Ask%20shadowsocks%20Guru-006BFF)](https://gurubase.io/g/shadowsocks) [![crates.io](https://img.shields.io/crates/v/shadowsocks-rust.svg)](https://crates.io/crates/shadowsocks-rust) [![Release](https://img.shields.io/github/release/shadowsocks/shadowsocks-rust.svg)](https://github.com/shadowsocks/shadowsocks-rust/releases) [![shadowsocks-rust](https://img.shields.io/archlinux/v/extra/x86_64/shadowsocks-rust)](https://archlinux.org/packages/extra/x86_64/shadowsocks-rust/) [![aur shadowsocks-rust-git](https://img.shields.io/aur/version/shadowsocks-rust-git)](https://aur.archlinux.org/packages/shadowsocks-rust-git) [![NixOS](https://img.shields.io/badge/NixOS-shadowsocks--rust-blue?logo=nixos)](https://github.com/NixOS/nixpkgs/blob/master/pkgs/by-name/sh/shadowsocks-rust/package.nix) [![snap shadowsocks-rust](https://snapcraft.io/shadowsocks-rust/badge.svg)](https://snapcraft.io/shadowsocks-rust) [![homebrew shadowsocks-rust](https://img.shields.io/homebrew/v/shadowsocks-rust)](https://formulae.brew.sh/formula/shadowsocks-rust#default) [![MacPorts shadowsocks-rust](https://img.shields.io/badge/dynamic/json?url=https%3A%2F%2Fports.macports.org%2Fapi%2Fv1%2Fports%2Fshadowsocks-rust%2F&query=%24.version&label=macports)](https://ports.macports.org/port/shadowsocks-rust/) This is a port of [shadowsocks](https://github.com/shadowsocks/shadowsocks). shadowsocks is a fast tunnel proxy that helps you bypass firewalls. | Library | Description | | ----------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | [**shadowsocks**](https://crates.io/crates/shadowsocks) | [![crates.io](https://img.shields.io/crates/v/shadowsocks.svg)](https://crates.io/crates/shadowsocks) [![docs.rs](https://img.shields.io/docsrs/shadowsocks)](https://docs.rs/shadowsocks) shadowsocks core protocol | | [**shadowsocks-service**](https://crates.io/crates/shadowsocks-service) | [![crates.io](https://img.shields.io/crates/v/shadowsocks-service.svg)](https://crates.io/crates/shadowsocks-service) [![docs.rs](https://img.shields.io/docsrs/shadowsocks-service)](https://docs.rs/shadowsocks-service) Services for serving shadowsocks | | [**shadowsocks-rust**](https://crates.io/crates/shadowsocks-rust) | [![crates.io](https://img.shields.io/crates/v/shadowsocks-rust.svg)](https://crates.io/crates/shadowsocks-rust) Binaries running common shadowsocks services | Related Projects: - [spyophobia/shadowsocks-gtk-rs](https://github.com/spyophobia/shadowsocks-gtk-rs) A GUI on Linux for `sslocal` using GTK, [discussion](https://github.com/shadowsocks/shadowsocks-rust/issues/664) - [honwen/openwrt-shadowsocks-rust](https://github.com/honwen/openwrt-shadowsocks-rust) OpenWRT solution for `sslocal`, [discussion](https://github.com/honwen/openwrt-shadowsocks-rust) - [cg31/shadowsocks-windows-gui-rust](https://github.com/cg31/shadowsocks-windows-gui-rust) Windows GUI client, [discussion](https://github.com/shadowsocks/shadowsocks-rust/issues/375) ## Build & Install ### Optional Features - `hickory-dns` - Uses [`hickory-resolver`](https://crates.io/crates/hickory-resolver) as DNS resolver instead of `tokio`'s builtin. - `local-http` - Allow using HTTP protocol for `sslocal` - `local-http-native-tls` - Support HTTPS with [`native-tls`](https://crates.io/crates/native-tls) - `local-http-rustls` - Support HTTPS with [`rustls`](https://crates.io/crates/rustls) - `local-tunnel` - Allow using tunnel protocol for `sslocal` - `local-socks4` - Allow using SOCKS4/4a protocol for `sslocal` - `local-redir` - Allow using redir (transparent proxy) protocol for `sslocal` - `local-dns` - Allow using dns protocol for `sslocal`, serves as a DNS server proxying queries to local or remote DNS servers by ACL rules - `local-fake-dns` - FakeDNS, allocating an IP address for each individual Query from a specific IP pool - `local-tun` - [TUN](https://en.wikipedia.org/wiki/TUN/TAP) interface support for `sslocal` - `local-online-config` - [SIP008](https://shadowsocks.org/doc/sip008.html) Online Configuration Delivery - `stream-cipher` - Enable deprecated stream ciphers. WARN: stream ciphers are UNSAFE! - `aead-cipher-extra` - Enable non-standard AEAD ciphers - `aead-cipher-2022` - Enable AEAD-2022 ciphers ([SIP022](https://github.com/shadowsocks/shadowsocks-org/issues/196)) - `aead-cipher-2022-extra` - Enable AEAD-2022 extra ciphers (non-standard ciphers) #### Memory Allocators This project uses system (libc) memory allocator (Rust's default). But it also allows you to use other famous allocators by features: - `jemalloc` - Uses [jemalloc](http://jemalloc.net/) as global memory allocator - `mimalloc` - Uses [mi-malloc](https://microsoft.github.io/mimalloc/) as global memory allocator - `tcmalloc` - Uses [TCMalloc](https://google.github.io/tcmalloc/overview.html) as global memory allocator. It tries to link system-wide tcmalloc by default, use vendored from source with `tcmalloc-vendored`. - `snmalloc` - Uses [snmalloc](https://github.com/microsoft/snmalloc) as global memory allocator - `rpmalloc` - Uses [rpmalloc](https://github.com/mjansson/rpmalloc) as global memory allocator ### **crates.io** Install from [crates.io](https://crates.io/crates/shadowsocks-rust): ```bash # Install from crates.io cargo install shadowsocks-rust ``` then you can find `sslocal` and `ssserver` in `$CARGO_HOME/bin`. ### **Install using Homebrew** For macOS and Linux, you can install it using [Homebrew](https://brew.sh/): ```bash brew install shadowsocks-rust ``` ### **Install using snap** ```bash # Install from snapstore snap install shadowsocks-rust # List services snap services shadowsocks-rust # Enable and start shadowsocks-rust.sslocal-daemon snap service snap start --enable shadowsocks-rust.sslocal-daemon # Show generated systemd service status systemctl status snap.shadowsocks-rust.sslocal-daemon.service # Override generated systemd service (configure startup options) systemctl edit snap.shadowsocks-rust.sslocal-daemon.service ## NOTE: you can pass args to sslocal: ## [Service] ## ExecStart= ## ExecStart=/usr/bin/snap run shadowsocks-rust.sslocal-daemon -b "127.0.0.1:1080" --server-url "ss://...." # Restart generated systemd service to apply changes systemctl restart snap.shadowsocks-rust.sslocal-daemon.service # ... and show service status systemctl status snap.shadowsocks-rust.sslocal-daemon.service ``` Default configuration file path probably is `/var/snap/shadowsocks-rust/common/etc/shadowsocks-rust/config.json`. ### **Download release** Download static-linked build [here](https://github.com/shadowsocks/shadowsocks-rust/releases). - Most of them are built with [cross](https://github.com/cross-rs/cross). Build environment details could be found in its README, such as glibc's version. - `x86_64-apple-darwin`, `aarch64-apple-darwin` are built in github's `macos-latest` image. Information could be found in [here](https://docs.github.com/en/actions/using-github-hosted-runners/using-github-hosted-runners/about-github-hosted-runners). - `x86_64-pc-windows-msvc` is built in github's `windows-latest` image. Information could be found in [here](https://docs.github.com/en/actions/using-github-hosted-runners/using-github-hosted-runners/about-github-hosted-runners). ### **Docker** This project provided Docker images for the `linux/i386` and `linux/amd64` and `linux/arm64/v8` architectures. > :warning: **Docker containers do not have access to IPv6 by default**: Make sure to disable IPv6 Route in the client or [enable IPv6 access to docker containers](https://docs.docker.com/config/daemon/ipv6/#use-ipv6-for-the-default-bridge-network). #### Pull from GitHub Container Registry Docker will pull the image of the appropriate architecture from our [GitHub Packages](https://github.com/orgs/shadowsocks/packages?repo_name=shadowsocks-rust). ```bash docker pull ghcr.io/shadowsocks/sslocal-rust:latest docker pull ghcr.io/shadowsocks/ssserver-rust:latest ``` #### Build on the local machine(Optional) If you want to build the Docker image yourself, you need to use the [BuildX](https://docs.docker.com/buildx/working-with-buildx/). ```bash docker buildx build -t shadowsocks/ssserver-rust:latest -t shadowsocks/ssserver-rust:v1.15.2 --target ssserver . docker buildx build -t shadowsocks/sslocal-rust:latest -t shadowsocks/sslocal-rust:v1.15.2 --target sslocal . ``` #### Run the container You need to mount the configuration file into the container and create an external port map for the container to connect to it. ```bash docker run --name sslocal-rust \ --restart always \ -p 1080:1080/tcp \ -v /path/to/config.json:/etc/shadowsocks-rust/config.json \ -dit ghcr.io/shadowsocks/sslocal-rust:latest docker run --name ssserver-rust \ --restart always \ -p 8388:8388/tcp \ -p 8388:8388/udp \ -v /path/to/config.json:/etc/shadowsocks-rust/config.json \ -dit ghcr.io/shadowsocks/ssserver-rust:latest ``` ### **Deploy to Kubernetes** This project provided yaml manifests for deploying to Kubernetes. You can leverage k8s Service to expose traffic outside, like LoadBalancer or NodePort which gains more fine-grained compared with fixed host or port. For a more interesting use case, you can use a Ingress(Istio, nginx, etc.) which routes the matched traffic to shadowsocks along with the real web service. #### Using `kubectl` `kubectl apply -f https://github.com/shadowsocks/shadowsocks-rust/raw/master/k8s/shadowsocks-rust.yaml` You can change the config via editing the ConfigMap named `shadowsocks-rust`. For more fine-grained control, use `helm`. #### Using `helm` `helm install my-release k8s/chart -f my-values.yaml` Below is the common default values you can change: ```yaml # This is the shadowsocks config which will be mount to /etc/shadowocks-rust. # You can put arbitrary yaml here, and it will be translated to json before mounting. servers: - server: "::" server_port: 8388 service_port: 80 # the k8s service port, default to server_port password: mypassword method: aes-256-gcm fast_open: true mode: tcp_and_udp # plugin: v2ray-plugin # plugin_opts: server;tls;host=github.com # Whether to download v2ray and xray plugin. downloadPlugins: false # Name of the ConfigMap with config.json configuration for shadowsocks-rust. configMapName: "" service: # Change to LoadBalancer if you are behind a cloud provider like aws, gce, or tke. type: ClusterIP # Bind shadowsocks port port to host, i.e., we can use host:port to access shawdowsocks server. hostPort: false replicaCount: 1 image: repository: ghcr.io/shadowsocks/ssserver-rust pullPolicy: IfNotPresent # Overrides the image tag whose default is the chart appVersion. tag: "latest" ``` ### **Build from source** Use cargo to build. NOTE: **RAM >= 2GiB** ```bash cargo build --release ``` Then `sslocal` and `ssserver` will appear in `./target/(debug|release)/`, it works similarly as the two binaries in the official ShadowSocks' implementation. ```bash make install TARGET=release ``` Then `sslocal`, `ssserver`, `ssmanager` and `ssurl` will be installed to `/usr/local/bin` (variable PREFIX). For Windows users, if you have encountered any problem in building, check and discuss in [#102](https://github.com/shadowsocks/shadowsocks-rust/issues/102). ### **target-cpu optimization** If you are building for your current CPU platform (for example, build and run on your personal computer), it is recommended to set `target-cpu=native` feature to let `rustc` generate and optimize code for the CPU running the compiler. ```bash export RUSTFLAGS="-C target-cpu=native" ``` ### **Build standalone binaries** Requirements: - Docker ```bash ./build/build-release ``` Then `sslocal`, `ssserver`, `ssmanager`, `ssservice` and `ssurl` will be packaged in - `./build/shadowsocks-${VERSION}-stable.x86_64-unknown-linux-musl.tar.xz` - `./build/shadowsocks-${VERSION}-stable.x86_64-pc-windows-gnu.zip` Read `Cargo.toml` for more details. For Linux with low GLIBC versions, set `CROSS_CONFIG` to CentOS based image: ```bash export CROSS_CONFIG=Cross-centos.toml ``` ## Getting Started Generate a safe and secured password for a specific encryption method (`aes-128-gcm` in the example) with: ```bash ssservice genkey -m "aes-128-gcm" ``` Create a ShadowSocks' configuration file. Example ```jsonc { "server": "my_server_ip", "server_port": 8388, "password": "rwQc8qPXVsRpGx3uW+Y3Lj4Y42yF9Bs0xg1pmx8/+bo=", "method": "aes-256-gcm", // ONLY FOR `sslocal` // Delete these lines if you are running `ssserver` or `ssmanager` "local_address": "127.0.0.1", "local_port": 1080 } ``` Detailed explanation of the configuration file could be found in [shadowsocks' documentation](https://github.com/shadowsocks/shadowsocks/wiki). (Link to original project, not maintained anymore !) > :warning: For snap installations, configuration file is most probably located in `/var/snap/shadowsocks-rust/common/etc/shadowsocks-rust/config.json` (see / ) In shadowsocks-rust, we also have an extended configuration file format, which is able to define more than one server. You can also disable individual servers. ```jsonc { "servers": [ { "server": "127.0.0.1", "server_port": 8388, "password": "rwQc8qPXVsRpGx3uW+Y3Lj4Y42yF9Bs0xg1pmx8/+bo=", "method": "aes-256-gcm", "timeout": 7200 }, { "server": "127.0.0.1", "server_port": 8389, "password": "/dliNXn5V4jg6vBW4MnC1I8Jljg9x7vSihmk6UZpRBM=", "method": "chacha20-ietf-poly1305" }, { "disabled": true, "server": "eg.disable.me", "server_port": 8390, "password": "mGvbWWay8ueP9IHnV5F1uWGN2BRToiVCAWJmWOTLU24=", "method": "chacha20-ietf-poly1305" } ], // ONLY FOR `sslocal` // Delete these lines if you are running `ssserver` or `ssmanager` "local_port": 1080, "local_address": "127.0.0.1" } ``` `sslocal` automatically selects the best server with the lowest latency and the highest availability. Start Shadowsocks client and server with: ```bash sslocal -c config.json ssserver -c config.json ``` If you Build it with Cargo: ```bash cargo run --bin sslocal -- -c config.json cargo run --bin ssserver -- -c config.json ``` List all available arguments with `-h`. ## Usage Start local client with configuration file ```bash # Read local client configuration from file sslocal -c /path/to/shadowsocks.json ``` ### Socks5 Local client ```bash # Pass all parameters via command line sslocal -b "127.0.0.1:1080" -s "[::1]:8388" -m "aes-256-gcm" -k "hello-kitty" --plugin "v2ray-plugin" --plugin-opts "server;tls;host=github.com" # Pass server with SIP002 URL sslocal -b "127.0.0.1:1080" --server-url "ss://YWVzLTI1Ni1nY206cGFzc3dvcmQ@127.0.0.1:8388/?plugin=v2ray-plugin%3Bserver%3Btls%3Bhost%3Dgithub.com" ``` ### HTTP Local client ```bash sslocal -b "127.0.0.1:3128" --protocol http -s "[::1]:8388" -m "aes-256-gcm" -k "hello-kitty" ``` All parameters are the same as Socks5 client, except `--protocol http`. ### Tunnel Local client ```bash # Set 127.0.0.1:8080 as the target for forwarding to sslocal --protocol tunnel -b "127.0.0.1:3128" -f "127.0.0.1:8080" -s "[::1]:8388" -m "aes-256-gcm" -k "hello-kitty" ``` - `--protocol tunnel` enables local client Tunnel mode - `-f "127.0.0.1:8080` sets the tunnel target address ### Transparent Proxy Local client **NOTE**: It currently only supports - Linux (with `iptables` targets `REDIRECT` and `TPROXY`) - BSDs (with `pf`), such as OS X 10.10+, FreeBSD, ... ```bash sslocal -b "127.0.0.1:60080" --protocol redir -s "[::1]:8388" -m "aes-256-gcm" -k "hello-kitty" --tcp-redir "redirect" --udp-redir "tproxy" ``` Redirects connections with `iptables` configurations to the port that `sslocal` is listening on. - `--protocol redir` enables local client Redir mode - (optional) `--tcp-redir` sets TCP mode to `REDIRECT` (Linux) - (optional) `--udp-redir` sets UDP mode to `TPROXY` (Linux) ### Tun interface client **NOTE**: It currently only supports - Linux, Android - macOS, iOS - Windows #### Linux Create a Tun interface with name `tun0` ```bash ip tuntap add mode tun tun0 ifconfig tun0 inet 10.255.0.1 netmask 255.255.255.0 up ``` Start `sslocal` with `--protocol tun` and binds to `tun0` ```bash sslocal --protocol tun -s "[::1]:8388" -m "aes-256-gcm" -k "hello-kitty" --outbound-bind-interface lo0 --tun-interface-name tun0 ``` #### macOS ```bash sslocal --protocol tun -s "[::1]:8388" -m "aes-256-gcm" -k "hello-kitty" --outbound-bind-interface lo0 --tun-interface-address 10.255.0.1/24 ``` It will create a Tun interface with address `10.255.0.1` and netmask `255.255.255.0`. #### Windows Download `wintun.dll` from [Wintun](https://www.wintun.net/), and place it in the folder with shadowsocks' runnable binaries, or in the system PATH. ```powershell sslocal --protocol tun -s "[::1]:8388" -m "aes-256-gcm" -k "hello-kitty" --outbound-bind-interface "Ethernet 0" --tun-interface-name "shadowsocks" ``` ### Local client for Windows Service Compile it by enabling `--features "winservice"` (not included in the default build): ```bash cargo build --release --bin "sswinservice" --features "winservice" ``` Install it as a Windows Service (PowerShell): ```powershell New-Service -Name "shadowsocks-local-service" ` -DisplayName "Shadowsocks Local Service" ` -BinaryPathName "\sswinservice.exe local -c \local_config.json" ``` There are other ways to install `sswinservice` as a Windows Service, for example, the `sc` command. As you may have noticed that the `-BinaryPathName` contains not only just the `sswinservice.exe`, but `local -c local_config.json`. These command line parameters will be used as the default parameter when the Windows Service starts. You can also start the service with customized parameters. Learn more from [Microsoft's Document](https://learn.microsoft.com/en-us/dotnet/framework/windows-services/introduction-to-windows-service-applications). The `sswinservice`'s parameter works exactly the same as `ssservice`. It supports `local`, `server` and `manager` subcommands. ### Server ```bash # Read server configuration from file ssserver -c /path/to/shadowsocks.json # Pass all parameters via command line ssserver -s "[::]:8388" -m "aes-256-gcm" -k "hello-kitty" --plugin "v2ray-plugin" --plugin-opts "server;tls;host=github.com" ``` ### Server Manager Supported [Manage Multiple Users](https://github.com/shadowsocks/shadowsocks/wiki/Manage-Multiple-Users) API: - `add` - Starts a server instance - `remove` - Deletes an existing server instance - `list` - Lists all current running servers - `ping` - Lists all servers' statistic data NOTE: `stat` command is not supported. Because servers are running in the same process with the manager itself. ```bash # Start it just with --manager-address command line parameter ssmanager --manager-address "127.0.0.1:6100" # For *nix system, manager can bind to unix socket address ssmanager --manager-address "/tmp/shadowsocks-manager.sock" # You can also provide a configuration file # # `manager_address` key must be provided in the configuration file ssmanager -c /path/to/shadowsocks.json # Create one server by UDP echo 'add: {"server_port":8388,"password":"hello-kitty"}' | nc -u '127.0.0.1' '6100' # Close one server by unix socket echo 'remove: {"server_port":8388}' | nc -Uu '/tmp/shadowsocks-manager.sock' ``` For manager UI, check more details in the [shadowsocks-manager](https://github.com/shadowsocks/shadowsocks-manager) project. Example configuration: ```jsonc { // Required option // Address that ssmanager is listening on "manager_address": "127.0.0.1", "manager_port": 6100, // Or bind to a Unix Domain Socket "manager_address": "/tmp/shadowsocks-manager.sock", "servers": [ // These servers will be started automatically when ssmanager is started ], // Outbound socket binds to this IP address // For choosing different network interface on the same machine "local_address": "xxx.xxx.xxx.xxx", // Other options that may be passed directly to new servers } ``` ## Configuration ```jsonc { // LOCAL: Listen address. This is exactly the same as `locals[0]` // SERVER: Bind address for remote sockets, mostly used for choosing interface // Don't set it if you don't know what's this for. "local_address": "127.0.0.1", "local_port": 1080, // Extended multiple local configuration "locals": [ { // Basic configuration, a SOCKS5 local server "local_address": "127.0.0.1", "local_port": 1080, // OPTIONAL. Setting the `mode` for this specific local server instance. // If not set, it will derive from the outer `mode` "mode": "tcp_and_udp", // OPTIONAL. Authentication configuration file // Configuration file document could be found in the next section. "socks5_auth_config_path": "/path/to/auth.json", // OPTIONAL. Instance specific ACL "acl": "/path/to/acl/file.acl", // OPTIONAL. macOS launchd activate socket "launchd_tcp_socket_name": "TCPListener", "launchd_udp_socket_name": "UDPListener" }, { // SOCKS5, SOCKS4/4a local server "protocol": "socks", // Listen address "local_address": "127.0.0.1", "local_port": 1081, // OPTIONAL. Enables UDP relay "mode": "tcp_and_udp", // OPTIONAL. Customizing the UDP's binding address. Depending on `mode`, if // - TCP is enabled, then SOCKS5's UDP Association command will return this address // - UDP is enabled, then SOCKS5's UDP server will listen to this address. "local_udp_address": "127.0.0.1", "local_udp_port": 2081, // OPTIONAL. macOS launchd activate socket "launchd_tcp_socket_name": "TCPListener", "launchd_udp_socket_name": "UDPListener" }, { // Tunnel local server (feature = "local-tunnel") "protocol": "tunnel", // Listen address "local_address": "127.0.0.1", "local_port": 5353, // Forward address, the target of this tunnel // In this example, this will build a `127.0.0.1:5353` -> `8.8.8.8:53` tunnel "forward_address": "8.8.8.8", "forward_port": 53, // OPTIONAL. Customizing whether to start TCP and UDP tunnel "mode": "tcp_only", // OPTIONAL. macOS launchd activate socket "launchd_tcp_socket_name": "TCPListener", "launchd_udp_socket_name": "UDPListener" }, { // HTTP local server (feature = "local-http") "protocol": "http", // Listen address "local_address": "127.0.0.1", "local_port": 3128, // OPTIONAL. macOS launchd activate socket "launchd_tcp_socket_name": "TCPListener", // OPTIONAL. Authentication configuration file // Configuration file document could be found in the next section. "http_auth_config_path": "/path/to/auth.json", }, { // DNS local server (feature = "local-dns") // This DNS works like China-DNS, it will send requests to `local_dns` and `remote_dns` and choose by ACL rules "protocol": "dns", // Listen address "local_address": "127.0.0.1", "local_port": 53, // OPTIONAL. DNS local server uses `tcp_and_udp` mode by default "mode": "udp_only", // Local DNS address, DNS queries will be sent directly to this address "local_dns_address": "114.114.114.114", // OPTIONAL. Local DNS's port, 53 by default "local_dns_port": 53, // Remote DNS address, DNS queries will be sent through ssserver to this address "remote_dns_address": "8.8.8.8", // OPTIONAL. Remote DNS's port, 53 by default "remote_dns_port": 53, // OPTIONAL. dns client cache size for fetching dns queries. "client_cache_size": 5, // OPTIONAL. macOS launchd activate socket "launchd_tcp_socket_name": "TCPListener", "launchd_udp_socket_name": "UDPListener" }, { // Tun local server (feature = "local-tun") "protocol": "tun", // Tun interface name "tun_interface_name": "tun0", // Tun interface address // // It has to be a host address in CIDR form "tun_interface_address": "10.255.0.1/24" }, { // Transparent Proxy (redir) local server (feature = "local-redir") "protocol": "redir", // OPTIONAL: TCP type, may be different between platforms // Linux/Android: redirect (default), tproxy // FreeBSD/OpenBSD: pf (default), ipfw // NetBSD/macOS/Solaris: pf (default), ipfw "tcp_redir": "tproxy", // OPTIONAL: UDP type, may be different between platforms // Linux/Android: tproxy (default) // FreeBSD/OpenBSD: pf (default) "udp_redir": "tproxy" }, { // FakeDNS local server (feature = "local-fake-dns") // FakeDNS is a DNS server that allocates an IPv4 / IPv6 address in a specific pool for each queries. // Subsequence requests from the other local interfaces that the target addresses includes those allocated IP addresses, // will be substituted back to their original domain name addresses. // This feature is useful mostly for transparent proxy, which will allow the proxied domain names to be resolved remotely. "protocol": "fake-dns", // Listen address "local_address": "127.0.0.1", "local_port": 10053, // IPv4 address pool (for A records) "fake_dns_ipv4_network": "10.255.0.0/16", // IPv6 address pool (for AAAA records) "fake_dns_ipv6_network": "fdf2:e786:ab40:9d2f::/64", // Persistent storage for all allocated DNS records "fake_dns_database_path": "/var/shadowsocks/fakedns.db", // OPTIONAL: Record expire duration in seconds, 10s by default "fake_dns_record_expire_duration": 10 } ], // Server configuration // listen on :: for dual stack support, no need add [] around. "server": "::", // Change to use your custom port number "server_port": 8388, "method": "aes-256-gcm", "password": "your-password", "plugin": "v2ray-plugin", "plugin_opts": "mode=quic;host=github.com", "plugin_args": [ // Each line is an argument passed to "plugin" "--verbose" ], "plugin_mode": "tcp_and_udp", // SIP003u, default is "tcp_only" // Server: TCP socket timeout in seconds. // Client: TCP connection timeout in seconds. // Omit this field if you don't have specific needs. "timeout": 7200, // Extended multiple server configuration // LOCAL: Choosing the best server to connect dynamically // SERVER: Creating multiple servers in one process "servers": [ { // Fields are the same as the single server's configuration // Individual servers can be disabled // "disabled": true, "address": "0.0.0.0", "port": 8389, "method": "aes-256-gcm", "password": "your-password", "plugin": "...", "plugin_opts": "...", "plugin_args": [], "plugin_mode": "...", "timeout": 7200, // Customized weight for local server's balancer // // Weight must be in [0, 1], default is 1.0. // The higher weight, the server may rank higher. "tcp_weight": 1.0, "udp_weight": 1.0, // OPTIONAL. Instance specific ACL "acl": "/path/to/acl/file.acl", }, { // Same key as basic format "server" and "server_port" "server": "0.0.0.0", "server_port": 8388, "method": "chacha20-ietf-poly1305", // Read the actual password from environment variable PASSWORD_FROM_ENV "password": "${PASSWORD_FROM_ENV}" }, { // AEAD-2022 "server": "::", "server_port": 8390, "method": "2022-blake3-aes-256-gcm", "password": "3SYJ/f8nmVuzKvKglykRQDSgg10e/ADilkdRWrrY9HU=", // For Server (OPTIONAL) // Support multiple users with Extensible Identity Header // https://github.com/Shadowsocks-NET/shadowsocks-specs/blob/main/2022-2-shadowsocks-2022-extensible-identity-headers.md "users": [ { "name": "username", // User's password must have the same length as server's password "password": "4w0GKJ9U3Ox7CIXGU4A3LDQAqP6qrp/tUi/ilpOR9p4=" } ], // For Client (OPTIONAL) // If EIH enabled, then "password" should have the following format: iPSK:iPSK:iPSK:uPSK // - iPSK is one of the middle relay servers' PSK, for the last `ssserver`, it must be server's PSK ("password") // - uPSK is the user's PSK ("password") // Example: // "password": "3SYJ/f8nmVuzKvKglykRQDSgg10e/ADilkdRWrrY9HU=:4w0GKJ9U3Ox7CIXGU4A3LDQAqP6qrp/tUi/ilpOR9p4=" }, { "...": "Any other fields", // Some optional fields for this specific server // Outbound socket options // Linux Only (SO_MARK) "outbound_fwmark": 255, // FreeBSD only (SO_USER_COOKIE) "outbound_user_cookie": 255, // `SO_BINDTODEVICE` (Linux), `IP_BOUND_IF` (BSD), `IP_UNICAST_IF` (Windows) socket option for outbound sockets "outbound_bind_interface": "eth1", // Outbound socket bind() to this IP (choose a specific interface) "outbound_bind_addr": "11.22.33.44", // Outbound UDP socket allows IP fragmentation (default false) "outbound_udp_allow_fragmentation": false, } ], // Global configurations for UDP associations "udp_timeout": 300, // Timeout for UDP associations (in seconds), 5 minutes by default "udp_max_associations": 512, // Maximum UDP associations to be kept in one server, unlimited by default // Options for Manager "manager_address": "127.0.0.1", // Could be a path to UNIX socket, /tmp/shadowsocks-manager.sock "manager_port": 5300, // Not needed for UNIX socket // DNS server's address for resolving domain names // For *NIX and Windows, it uses system's configuration by default // // Value could be IP address of DNS server, for example, "8.8.8.8". // DNS client will automatically request port 53 with both TCP and UDP protocol. // // - system, uses system provided API (`getaddrinfo` on *NIX) // // It also allows some pre-defined well-known public DNS servers: // - google (TCP, UDP) // - cloudflare (TCP, UDP) // - cloudflare_tls (TLS), enable by feature "dns-over-tls" // - cloudflare_https (HTTPS), enable by feature "dns-over-https" // - quad9 (TCP, UDP) // - quad9_tls (TLS), enable by feature "dns-over-tls" // // The field is only effective if feature "hickory-dns" is enabled. "dns": "google", // Configure `cache_size` for "hickory-dns" ResolverOpts. Set to "0" to disable DNS cache. "dns_cache_size": 0, // Mode, could be one of the // - tcp_only // - tcp_and_udp // - udp_only "mode": "tcp_only", // TCP_NODELAY "no_delay": false, // Enables `SO_KEEPALIVE` and set `TCP_KEEPIDLE`, `TCP_KEEPINTVL` to the specified seconds "keep_alive": 15, // Soft and Hard limit of file descriptors on *NIX systems "nofile": 10240, // Try to resolve domain name to IPv6 (AAAA) addresses first "ipv6_first": false, // Set IPV6_V6ONLY for all IPv6 listener sockets // Only valid for locals and servers listening on `::` "ipv6_only": false, // Outbound socket options // Linux Only (SO_MARK) "outbound_fwmark": 255, // FreeBSD only (SO_USER_COOKIE) "outbound_user_cookie": 255, // `SO_BINDTODEVICE` (Linux), `IP_BOUND_IF` (BSD), `IP_UNICAST_IF` (Windows) socket option for outbound sockets "outbound_bind_interface": "eth1", // Outbound socket bind() to this IP (choose a specific interface) "outbound_bind_addr": "11.22.33.44", // Outbound UDP socket allows IP fragmentation (default false) "outbound_udp_allow_fragmentation": false, // Balancer customization "balancer": { // MAX Round-Trip-Time (RTT) of servers // The timeout seconds of each individual checks "max_server_rtt": 5, // Interval seconds between each check "check_interval": 10, // Interval seconds between each check for the best server // Optional. Specify to enable shorter checking interval for the best server only. "check_best_interval": 5 }, // SIP008 Online Configuration Delivery // https://shadowsocks.org/doc/sip008.html "online_config": { "config_url": "https://path-to-online-sip008-configuration", // Optional. Seconds between each update to config_url. Default to 3600s "update_interval": 3600, // Optional. Whitelist of plugins (RECOMMENDED for all users) // SECURITY: To avoid executing untrusted commands loaded from config_url "allowed_plugins": [ "v2ray-plugin" ] }, // Service configurations // Logger configuration "log": { // Default log level to use, if not overridden by `writers`, default is `0` // Equivalent to `-v` command line option "level": 1, // Default log format to use, if not overridden by `writers` "format": { // Euiqvalent to `--log-without-time`, default is `false` "without_time": false, }, // Advanced logging configuration for configuring multiple writers // A console writer will be configured by default. // Set this to empty array `[]` to disable logging completely "writers": [ { // Configure a console writer // The inner fields are optional, if not set, it will use the default values // To minimally configure a console writer, simply write `"console": {}`. "console": { "level": 2, "format": { "without_time": false, } } }, { // Configure a file writer, useful when running as a Windows Service "file": { // `level` and `format` can also be set here, if not set, it will use the default values // Required. Directory to store log files "directory": "/var/log/shadowsocks-rust", // Optional. Log rotation frequency, must be one of the following: // - never (default): This will result in log file located at `directory/prefix.suffix` // - daily: A new log file in the format of `directory/prefix.yyyy-MM-dd.suffix` will be created daily // - hourly: A new log file in the format of `directory/prefix.yyyy-MM-dd-HH.suffix` will be created hourly "rotation": "never", // Optional. Prefix of log file, default is one of `sslocal`, `ssserver`, `ssmanager` depending on the service being run. "prefix": "shadowsocks-rust", // Optional. Suffix of log file, default is `log` "suffix": "log", // Optional. If set, keeps the last N log files "max_files": 5 } }, { // Configure a syslog writer, only supported on *nix system "syslog": { // `level` and `format` can also be set here, if not set, it will use the default values // Optional. Set the "identity" when calling openlog(). Use current service name by default. "identity": "identity_name", // Optional. Set the "facility" when calling openlog(). 1 (user-level messages) by default. See RFC5424. "facility": 1 } } ] }, // Runtime configuration "runtime": { // `single_thread` or `multi_thread` "mode": "multi_thread", // Worker threads that are used in multi-thread runtime "worker_count": 10 } } ``` ### SOCKS5 Authentication Configuration The configuration file is set by `socks5_auth_config_path` in `locals`. ```jsonc { // Password/Username Authentication (RFC1929) "password": { "users": [ { "user_name": "USERNAME in UTF-8", "password": "PASSWORD in UTF-8" } ] } } ``` ### HTTP Authentication Configuration The configuration file is set by `http_auth_config_path` in `locals`. ```jsonc { // Basic Authentication (RFC9110) "basic": { "users": [ { "user_name": "USERNAME in UTF-8", "password": "PASSWORD in UTF-8" } ] } } ``` ### Environment Variables - `SS_SERVER_PASSWORD`: A default password for servers that created from command line argument (`--server-addr`) - `SS_SYSTEM_DNS_RESOLVER_FORCE_BUILTIN`: `"system"` DNS resolver force use system's builtin (`getaddrinfo` in *NIX) ## Supported Ciphers ### AEAD 2022 Ciphers - `2022-blake3-aes-128-gcm`, `2022-blake3-aes-256-gcm` - `2022-blake3-chacha20-poly1305`, `2022-blake3-chacha8-poly1305` These Ciphers require `"password"` to be a Base64 string of key that have **exactly the same length** of Cipher's Key Size. It is recommended to use `ssservice genkey -m "METHOD_NAME"` to generate a secured and safe key. ### AEAD Ciphers - `chacha20-ietf-poly1305` - `aes-128-gcm`, `aes-256-gcm` ### Stream Ciphers - `plain` or `none` (No encryption, only used for debugging or with plugins that ensure transport security)
Deprecated

- `table` - `aes-128-cfb`, `aes-128-cfb1`, `aes-128-cfb8`, `aes-128-cfb128` - `aes-192-cfb`, `aes-192-cfb1`, `aes-192-cfb8`, `aes-192-cfb128` - `aes-256-cfb`, `aes-256-cfb1`, `aes-256-cfb8`, `aes-256-cfb128` - `aes-128-ctr` - `aes-192-ctr` - `aes-256-ctr` - `camellia-128-cfb`, `camellia-128-cfb1`, `camellia-128-cfb8`, `camellia-128-cfb128` - `camellia-192-cfb`, `camellia-192-cfb1`, `camellia-192-cfb8`, `camellia-192-cfb128` - `camellia-256-cfb`, `camellia-256-cfb1`, `camellia-256-cfb8`, `camellia-256-cfb128` - `rc4-md5` - `chacha20-ietf`

## ACL `sslocal`, `ssserver`, and `ssmanager` support ACL file with syntax like [shadowsocks-libev](https://github.com/shadowsocks/shadowsocks-libev). Some examples could be found in [here](https://github.com/shadowsocks/shadowsocks-libev/tree/master/acl). ### Available sections - For local servers (`sslocal`, `ssredir`, ...) - Modes: - `[bypass_all]` - ACL runs in `WhiteList` mode. Bypasses all addresses except those matching any rules. - `[proxy_all]` - ACL runs in `BlackList` mode. Proxies all addresses except those matching any rules. (default) - Rules: - `[bypass_list]` - Rules for connecting directly - `[proxy_list]` - Rules for connecting through proxies - For remote servers (`ssserver`) - Modes: - `[reject_all]` - ACL runs in `WhiteList` mode. Rejects all clients except those matching any rules. - `[accept_all]` - ACL runs in `BlackList` mode. Accepts all clients except those matching any rules. (default) - `[outbound_block_all]` - Outbound ACL runs in `WhiteList` mode. Blocks all outbound addresses except those matching any rules. - `[outbound_allow_all]` - Outbound ACL runs in `BlackList` mode. Allows all outbound addresses except those matching any rules. (default) - Rules: - `[white_list]` - Rules for accepted clients - `[black_list]` - Rules for rejected clients - `[outbound_block_list]` - Rules for blocking outbound addresses. - `[outbound_allow_list]` - Rules for allowing outbound addresses. ### Example ```ini # SERVERS # For ssserver, accepts requests from all clients by default [accept_all] # Blocks these clients [black_list] 1.2.3.4 127.0.0.1/8 # Disallow these outbound addresses [outbound_block_list] 127.0.0.1/8 ::1 # Using regular expression ^[a-z]{5}\.baidu\.com # Match exactly |baidu.com # Match with subdomains ||google.com # An internationalized domain name should be converted to punycode # |☃-⌘.com - WRONG |xn----dqo34k.com # ||джpумлатест.bрфa - WRONG ||xn--p-8sbkgc5ag7bhce.xn--ba-lmcq # CLIENTS # For sslocal, ..., bypasses all targets by default [bypass_all] # Proxy these addresses [proxy_list] ||google.com 8.8.8.8 ``` ## Useful Tools 1. `ssurl` is for encoding and decoding ShadowSocks URLs (SIP002). Example: ```plain ss://YWVzLTI1Ni1jZmI6cGFzc3dvcmQ@127.0.0.1:8388/?plugin=obfs-local%3Bobfs%3Dhttp%3Bobfs-host%3Dwww.baidu.com ``` ## Notes It supports the following features: - [x] SOCKS5 CONNECT command - [x] SOCKS5 UDP ASSOCIATE command (partial) - [x] SOCKS4/4a CONNECT command - [x] Various crypto algorithms - [x] Load balancing (multiple servers) and server delay checking - [x] [SIP004](https://github.com/shadowsocks/shadowsocks-org/issues/30) AEAD ciphers - [x] [SIP003](https://github.com/shadowsocks/shadowsocks-org/issues/28) Plugins - [x] [SIP003u](https://github.com/shadowsocks/shadowsocks-org/issues/180) Plugin with UDP support - [x] [SIP002](https://github.com/shadowsocks/shadowsocks-org/issues/27) Extension ss URLs - [x] [SIP022](https://github.com/shadowsocks/shadowsocks-org/issues/196) AEAD 2022 ciphers - [x] HTTP Proxy Supports ([RFC 7230](http://tools.ietf.org/html/rfc7230) and [CONNECT](https://tools.ietf.org/html/draft-luotonen-web-proxy-tunneling-01)) - [x] Defend against replay attacks, [shadowsocks/shadowsocks-org#44](https://github.com/shadowsocks/shadowsocks-org/issues/44) - [x] Manager APIs, supporting [Manage Multiple Users](https://github.com/shadowsocks/shadowsocks/wiki/Manage-Multiple-Users) - [x] ACL (Access Control List) - [x] Support HTTP/HTTPS Proxy protocol ## TODO - [x] Documentation - [x] Extend configuration format - [x] Improved logging format (waiting for the new official log crate) - [x] Support more ciphers without depending on `libcrypto` (waiting for an acceptable Rust crypto lib implementation) - [x] Windows support. - [x] Build with stable `rustc` ~~(blocking by `crypto2`)~~. - [x] Support HTTP Proxy protocol - [x] AEAD ciphers. (proposed in [SIP004](https://github.com/shadowsocks/shadowsocks-org/issues/30), still under discussion) - [x] Choose server based on delay #152 ## License [The MIT License (MIT)](https://opensource.org/licenses/MIT) Copyright (c) 2014 Y. T. CHUNG 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. ## Stargazers over time [![Stargazers over time](https://starchart.cc/shadowsocks/shadowsocks-rust.svg)](https://starchart.cc/shadowsocks/shadowsocks-rust) ================================================ FILE: acl/genacl_proxy_gfw_bypass_china_ip.py ================================================ #!/usr/bin/env python3 from urllib import request, parse import logging import sys import json from datetime import datetime logging.basicConfig(level=logging.INFO) logger = logging.getLogger(__name__) GFW_TRANSLATED_URL = "https://raw.githubusercontent.com/NateScarlet/gfwlist.acl/master/gfwlist.acl.json" CHINA_IP_LIST_URL = "https://raw.githubusercontent.com/17mon/china_ip_list/master/china_ip_list.txt" CUSTOM_BYPASS = [ "127.0.0.1", "10.0.0.0/8", "172.16.0.0/12", "192.168.0.0/16", "fd00::/8", ] CUSTOM_PROXY = [ ] def fetch_url_content(url): logger.info("FETCHING {}".format(url)) r = request.urlopen(url) return r.read() def write_gfw_list(fp): gfw_json = fetch_url_content(GFW_TRANSLATED_URL) gfw_obj = json.loads(gfw_json) for line in gfw_obj["blacklist"]: fp.write(line.encode("utf-8")) fp.write(b"\n") def write_china_ip(fp): china_ip_list = fetch_url_content(CHINA_IP_LIST_URL) fp.write(china_ip_list) fp.write(b"\n") try: output_file_path = sys.argv[1] except: output_file_path = "shadowsocks.acl" logger.info("WRITING {}".format(output_file_path)) with open(output_file_path, 'wb') as fp: now = datetime.now() fp.write(b"# Generated by genacl.py\n") fp.write("# Time: {}\n".format(now.isoformat()).encode("utf-8")) fp.write(b"\n") fp.write(b"[proxy_all]\n") fp.write(b"\n[proxy_list]\n") write_gfw_list(fp) fp.write(b"\n[bypass_list]\n") write_china_ip(fp) if len(CUSTOM_BYPASS) > 0: logger.info("CUSTOM_BYPASS {} lines".format(len(CUSTOM_BYPASS))) fp.write(b"\n[bypass_list]\n") for a in CUSTOM_BYPASS: fp.write(a.encode("utf-8")) fp.write(b"\n") if len(CUSTOM_PROXY) > 0: logger.info("CUSTOM_PROXY {} lines".format(len(CUSTOM_PROXY))) fp.write(b"\n[proxy_list]\n") for a in CUSTOM_PROXY: fp.write(a.encode("utf-8")) fp.write(b"\n") logger.info("DONE") ================================================ FILE: appveyor.yml ================================================ environment: SSL_CERT_FILE: "C:\\OpenSSL\\cacert.pem" matrix: - TARGET: x86_64-pc-windows-msvc BITS: 64 MSYS2: 1 OPENSSL_DIR: C:\OpenSSL-Win64 RUST_BACKTRACE: 1 # - TARGET: i686-pc-windows-gnu # BITS: 32 # OPENSSL_DIR: C:\OpenSSL-Win32 # MSYS2: 1 # SODIUM_BUILD_STATIC: yes # RUST_BACKTRACE: 1 install: # Install Rust - appveyor DownloadFile https://win.rustup.rs/ -FileName rustup-init.exe - rustup-init.exe -y --default-host %TARGET% - set PATH=%PATH%;%USERPROFILE%\.cargo\bin - if defined MSYS2 set PATH=C:\msys64\mingw%BITS%\bin;%PATH% # Run tests - rustc -V - cargo -V build: false test_script: - cargo test --no-fail-fast cache: - target - C:\Users\appveyor\.cargo\registry ================================================ FILE: bin/sslocal.rs ================================================ //! This is a binary running in the local environment //! //! You have to provide all needed configuration attributes via command line parameters, //! or you could specify a configuration file. The format of configuration file is defined //! in mod `config`. use std::process::ExitCode; use clap::Command; use shadowsocks_rust::service::local; fn main() -> ExitCode { let mut app = Command::new("shadowsocks") .version(shadowsocks_rust::VERSION) .about("A fast tunnel proxy that helps you bypass firewalls. (https://shadowsocks.org)"); app = local::define_command_line_options(app); let matches = app.get_matches(); local::main(&matches) } ================================================ FILE: bin/ssmanager.rs ================================================ //! This is a binary running in the server environment //! //! You have to provide all needed configuration attributes via command line parameters, //! or you could specify a configuration file. The format of configuration file is defined //! in mod `config`. //! //! *It should be notice that the extended configuration file is not suitable for the server //! side.* use std::process::ExitCode; use clap::Command; use shadowsocks_rust::service::manager; fn main() -> ExitCode { let mut app = Command::new("shadowsocks") .version(shadowsocks_rust::VERSION) .about("A fast tunnel proxy that helps you bypass firewalls. (https://shadowsocks.org)"); app = manager::define_command_line_options(app); let matches = app.get_matches(); manager::main(&matches) } ================================================ FILE: bin/ssserver.rs ================================================ //! This is a binary running in the server environment //! //! You have to provide all needed configuration attributes via command line parameters, //! or you could specify a configuration file. The format of configuration file is defined //! in mod `config`. //! //! *It should be notice that the extended configuration file is not suitable for the server //! side.* use std::process::ExitCode; use clap::Command; use shadowsocks_rust::service::server; fn main() -> ExitCode { let mut app = Command::new("shadowsocks") .version(shadowsocks_rust::VERSION) .about("A fast tunnel proxy that helps you bypass firewalls. (https://shadowsocks.org)"); app = server::define_command_line_options(app); let matches = app.get_matches(); server::main(&matches) } ================================================ FILE: bin/ssservice.rs ================================================ //! This is a binary running in both local and server environment //! //! You have to provide all needed configuration attributes via command line parameters, //! or you could specify a configuration file. The format of configuration file is defined //! in mod `config`. //! //! *It should be notice that the extended configuration file is not suitable for the server //! side.* use std::{env, path::Path, process::ExitCode}; use clap::Command; use shadowsocks_rust::service::{genkey, local, manager, server}; fn main() -> ExitCode { let app = Command::new("shadowsocks") .version(shadowsocks_rust::VERSION) .about("A fast tunnel proxy that helps you bypass firewalls. (https://shadowsocks.org)"); // Allow running `ssservice` as symlink of `sslocal`, `ssserver` and `ssmanager` if let Some(program_path) = env::args().next() && let Some(program_name) = Path::new(&program_path).file_name() { match program_name.to_str() { Some("sslocal") => return local::main(&local::define_command_line_options(app).get_matches()), Some("ssserver") => return server::main(&server::define_command_line_options(app).get_matches()), Some("ssmanager") => return manager::main(&manager::define_command_line_options(app).get_matches()), _ => {} } } let matches = app .subcommand_required(true) .subcommand(local::define_command_line_options(Command::new("local")).about("Shadowsocks Local service")) .subcommand(server::define_command_line_options(Command::new("server")).about("Shadowsocks Server service")) .subcommand( manager::define_command_line_options(Command::new("manager")).about("Shadowsocks Server Manager service"), ) .subcommand( genkey::define_command_line_options(Command::new("genkey")) .about("Generate shadowsocks encryption key for method"), ) .get_matches(); match matches.subcommand() { Some(("local", matches)) => local::main(matches), Some(("server", matches)) => server::main(matches), Some(("manager", matches)) => manager::main(matches), Some(("genkey", matches)) => genkey::main(matches), _ => unreachable!("expecting a subcommand"), } } ================================================ FILE: bin/ssurl.rs ================================================ //! SIP002 and SIP008 URL Schemes //! //! SS-URI = "ss://" userinfo "@" hostname ":" port [ "/" ] [ "?" plugin ] [ "#" tag ] //! userinfo = websafe-base64-encode-utf8(method ":" password) use std::process::ExitCode; use clap::{Arg, ArgAction, Command, ValueHint}; use qrcode::{QrCode, types::Color}; use shadowsocks_service::{ config::{Config, ConfigType, ServerInstanceConfig}, shadowsocks::config::ServerConfig, }; /// shadowsocks version const VERSION: &str = env!("CARGO_PKG_VERSION"); const BLACK: &str = "\x1b[40m \x1b[0m"; const WHITE: &str = "\x1b[47m \x1b[0m"; fn print_qrcode(encoded: &str) { let qrcode = QrCode::new(encoded.as_bytes()).unwrap(); for _ in 0..qrcode.width() + 2 { print!("{WHITE}"); } println!(); for y in 0..qrcode.width() { print!("{WHITE}"); for x in 0..qrcode.width() { let color = match qrcode[(x, y)] { Color::Light => WHITE, Color::Dark => BLACK, }; print!("{color}"); } println!("{WHITE}"); } for _ in 0..qrcode.width() + 2 { print!("{WHITE}"); } println!(); } fn encode(filename: &str, need_qrcode: bool) { let config = Config::load_from_file(filename, ConfigType::Server).unwrap(); for svr in config.server { let encoded = svr.config.to_url(); println!("{encoded}"); if need_qrcode { let encoded = svr.config.to_qrcode_url(); print_qrcode(&encoded); } } } fn decode(encoded: &str, need_qrcode: bool) { let svrconfig = ServerConfig::from_url(encoded).unwrap(); let mut config = Config::new(ConfigType::Server); config.server.push(ServerInstanceConfig::with_server_config(svrconfig)); println!("{config}"); if need_qrcode { print_qrcode(encoded); } } #[cfg(feature = "utility-url-outline")] fn decode_outline(remote: &str, need_qrcode: bool) { // Protect from using http and other non-ssconf links in reqwest call if !remote.starts_with("ssconf") { println!("Incorrect link format"); return; } let url = remote.replace("ssconf", "https"); let svrconfig = ServerConfig::from_url(reqwest::blocking::get(url).unwrap().text().unwrap().as_str()).unwrap(); let mut config = Config::new(ConfigType::Server); config.server.push(ServerInstanceConfig::with_server_config(svrconfig)); println!("{config}"); if need_qrcode { print_qrcode(remote); } } fn main() -> ExitCode { let mut app = Command::new("ssurl") .version(VERSION) .about("Encode and decode ShadowSocks URL") .arg( Arg::new("ENCODE_CONFIG_PATH") .short('e') .long("encode") .action(ArgAction::Set) .value_hint(ValueHint::FilePath) .conflicts_with("DECODE_CONFIG_PATH") .required_unless_present_any(["DECODE_CONFIG_PATH", "OUTLINE_CONFIG_URL"]) .help("Encode the server configuration in the provided JSON file"), ) .arg( Arg::new("DECODE_CONFIG_PATH") .short('d') .long("decode") .action(ArgAction::Set) .value_hint(ValueHint::FilePath) .required_unless_present_any(["ENCODE_CONFIG_PATH", "OUTLINE_CONFIG_URL"]) .help("Decode the server configuration from the provided ShadowSocks URL"), ) .arg( Arg::new("QRCODE") .short('c') .long("qrcode") .action(ArgAction::SetTrue) .help("Generate the QRCode with the provided configuration"), ); if cfg!(feature = "utility-url-outline") { app = app.arg( Arg::new("OUTLINE_CONFIG_URL") .short('o') .long("outline") .value_hint(ValueHint::Url) .required_unless_present_any(["ENCODE_CONFIG_PATH", "DECODE_CONFIG_PATH"]) .help("Fetch and decode config from ssconf URL used by Outline"), ); } let matches = app.get_matches(); let need_qrcode = matches.get_flag("QRCODE"); if let Some(file) = matches.get_one::("ENCODE_CONFIG_PATH") { encode(file, need_qrcode); return ExitCode::SUCCESS; } if let Some(encoded) = matches.get_one::("DECODE_CONFIG_PATH") { decode(encoded, need_qrcode); return ExitCode::SUCCESS; } #[cfg(feature = "utility-url-outline")] if let Some(remote) = matches.get_one::("OUTLINE_CONFIG_URL") { decode_outline(remote, need_qrcode); return ExitCode::SUCCESS; } println!("Use -h for more detail"); ExitCode::FAILURE } ================================================ FILE: bin/sswinservice.rs ================================================ use std::{ ffi::OsString, future::Future, sync::atomic::{AtomicU32, Ordering}, time::Duration, }; use clap::Command; use log::{error, info}; use shadowsocks_rust::{ error::ShadowsocksResult, service::{local, manager, server}, }; use tokio::{runtime::Runtime, sync::oneshot}; use windows_service::{ define_windows_service, service::{ServiceControl, ServiceControlAccept, ServiceExitCode, ServiceState, ServiceStatus, ServiceType}, service_control_handler::{self, ServiceControlHandlerResult, ServiceStatusHandle}, service_dispatcher, }; const SERVICE_NAME: &str = "ssservice"; const SERVICE_EXIT_CODE_ARGUMENT_ERROR: u32 = 100; const SERVICE_EXIT_CODE_EXITED_UNEXPECTEDLY: u32 = 101; const SERVICE_EXIT_CODE_CREATE_FAILED: u32 = 102; #[inline] fn set_service_status( handle: &ServiceStatusHandle, current_state: ServiceState, exit_code: ServiceExitCode, wait_hint: Duration, ) -> Result<(), windows_service::Error> { static SERVICE_STATE_CHECKPOINT: AtomicU32 = AtomicU32::new(0); let next_status = ServiceStatus { service_type: ServiceType::OWN_PROCESS, current_state, controls_accepted: if current_state == ServiceState::StartPending { ServiceControlAccept::empty() } else { ServiceControlAccept::STOP }, exit_code, checkpoint: if matches!(current_state, ServiceState::Running | ServiceState::Stopped) { SERVICE_STATE_CHECKPOINT.fetch_add(1, Ordering::AcqRel) } else { 0 }, wait_hint, process_id: None, }; handle.set_service_status(next_status) } fn handle_create_service_result( status_handle: ServiceStatusHandle, create_service_result: ShadowsocksResult<(Runtime, F)>, stop_receiver: oneshot::Receiver<()>, ) -> Result<(), windows_service::Error> where F: Future, { match create_service_result { Ok((runtime, main_fut)) => { // Successfully create runtime and future // Report running state set_service_status( &status_handle, ServiceState::Running, ServiceExitCode::Win32(0), Duration::default(), )?; // Run it right now. let exited_by_ctrl = runtime.block_on(async move { tokio::pin!(main_fut); tokio::pin!(stop_receiver); loop { tokio::select! { _ = stop_receiver => { break true; } exit_code = main_fut => { info!("service exited unexpectedly with code: {:?}", exit_code); break false; } } } }); // Report stopped state set_service_status( &status_handle, ServiceState::Stopped, if exited_by_ctrl { ServiceExitCode::Win32(0) } else { ServiceExitCode::ServiceSpecific(SERVICE_EXIT_CODE_EXITED_UNEXPECTEDLY) }, Duration::default(), )?; } Err(err) => { error!("failed to create service, exit code: {:?}", err.exit_code()); // Report running state set_service_status( &status_handle, ServiceState::Stopped, ServiceExitCode::ServiceSpecific(SERVICE_EXIT_CODE_CREATE_FAILED), Duration::default(), )?; } } Ok(()) } fn service_main(arguments: Vec) -> Result<(), windows_service::Error> { // Create a Oneshot channel for receiving Stop event let (stop_sender, stop_receiver) = oneshot::channel(); let mut stop_sender_opt = Some(stop_sender); let event_handler = move |control_event| -> ServiceControlHandlerResult { match control_event { ServiceControl::Stop => { if let Some(stop_sender) = stop_sender_opt.take() { let _ = stop_sender.send(()); } ServiceControlHandlerResult::NoError } ServiceControl::Interrogate => ServiceControlHandlerResult::NoError, _ => ServiceControlHandlerResult::NotImplemented, } }; // Register system service event handler let status_handle = service_control_handler::register(SERVICE_NAME, event_handler)?; // Report SERVICE_START_PENDING // https://learn.microsoft.com/en-us/windows/win32/services/writing-a-servicemain-function set_service_status( &status_handle, ServiceState::StartPending, ServiceExitCode::Win32(0), Duration::from_secs(30), )?; let app = Command::new("shadowsocks service") .version(shadowsocks_rust::VERSION) .about("A fast tunnel proxy that helps you bypass firewalls. (https://shadowsocks.org)"); let app = app .subcommand_required(true) .subcommand(local::define_command_line_options(Command::new("local")).about("Shadowsocks Local service")) .subcommand(server::define_command_line_options(Command::new("server")).about("Shadowsocks Server service")) .subcommand( manager::define_command_line_options(Command::new("manager")).about("Shadowsocks Server Manager service"), ); let matches_result = if arguments.len() <= 1 { app.try_get_matches() } else { app.try_get_matches_from(arguments) }; let matches = match matches_result { Ok(m) => m, Err(err) => { error!("failed to parse command line arguments, error: {}", err); set_service_status( &status_handle, ServiceState::Stopped, ServiceExitCode::ServiceSpecific(SERVICE_EXIT_CODE_ARGUMENT_ERROR), Duration::default(), )?; return Err(windows_service::Error::LaunchArgumentsNotSupported); } }; match matches.subcommand() { Some(("local", matches)) => handle_create_service_result(status_handle, local::create(matches), stop_receiver), Some(("server", matches)) => { handle_create_service_result(status_handle, server::create(matches), stop_receiver) } Some(("manager", matches)) => { handle_create_service_result(status_handle, manager::create(matches), stop_receiver) } _ => Err(windows_service::Error::LaunchArgumentsNotSupported), } } fn service_entry(arguments: Vec) { if let Err(err) = service_main(arguments) { error!("service main exited with error: {}", err); } } define_windows_service!(ffi_service_entry, service_entry); fn main() -> Result<(), windows_service::Error> { service_dispatcher::start(SERVICE_NAME, ffi_service_entry)?; Ok(()) } ================================================ FILE: build/README.md ================================================ ## Build Standalone Binaries ### Build with `cross` - Install [`cross`](https://github.com/rust-embedded/cross) ```bash cargo install cross ``` - Build with cross ```bash cross build --target x86_64-unknown-linux-musl ``` ### Predefined build routines - `build-release`: Build binaries with `cross` and packages outputs into `release` folder - `build-host-release`: Build binaries with host's Rust toolchain. *NIX shell script - `build-host-release.ps1`: Build binaries with host's Rust toolchain. PowerShell script ================================================ FILE: build/build-host-release ================================================ #!/bin/bash BUILD_TARGET="" BUILD_FEATURES=() while getopts "t:f:" opt; do case $opt in t) BUILD_TARGET=$OPTARG ;; f) BUILD_FEATURES+=($OPTARG) ;; ?) echo "Usage: $(basename $0) [-t ] [-f ]" ;; esac done BUILD_FEATURES+=${BUILD_EXTRA_FEATURES} ROOT_DIR=$( cd $( dirname $0 ) && pwd ) VERSION=$(grep -E '^version' "${ROOT_DIR}/../Cargo.toml" | awk '{print $3}' | sed 's/"//g') HOST_TRIPLE=$(rustc -Vv | grep 'host:' | awk '{print $2}') echo "Started build release ${VERSION} for ${HOST_TRIPLE} (target: ${BUILD_TARGET}) with features \"${BUILD_FEATURES}\"..." if [[ "${BUILD_TARGET}" != "" ]]; then if [[ "${BUILD_FEATURES}" != "" ]]; then cargo build --release --features "${BUILD_FEATURES}" --target "${BUILD_TARGET}" else cargo build --release --target "${BUILD_TARGET}" fi else if [[ "${BUILD_FEATURES}" != "" ]]; then cargo build --release --features "${BUILD_FEATURES}" else cargo build --release fi fi if [[ "$?" != "0" ]]; then exit 1; fi if [[ "${BUILD_TARGET}" == "" ]]; then BUILD_TARGET=$HOST_TRIPLE fi RELEASE_FOLDER="${ROOT_DIR}/release" RELEASE_PACKAGE_NAME="shadowsocks-v${VERSION}.${BUILD_TARGET}" mkdir -p "${RELEASE_FOLDER}" # Into release folder if [[ "${BUILD_TARGET}" != "" ]]; then cd "${ROOT_DIR}/../target/${BUILD_TARGET}/release" else cd "${ROOT_DIR}/../target/release" fi TARGET_SUFFIX="" if [[ "${BUILD_TARGET}" == *"-windows-"* ]]; then TARGET_SUFFIX=".exe" fi TARGETS=("sslocal${TARGET_SUFFIX}" "ssserver${TARGET_SUFFIX}" "ssurl${TARGET_SUFFIX}" "ssmanager${TARGET_SUFFIX}" "ssservice${TARGET_SUFFIX}") if [ -e "sswinservice${TARGET_SUFFIX}" ]; then TARGETS+=("sswinservice${TARGET_SUFFIX}") fi if [[ "${BUILD_TARGET}" == *"-windows-"* ]]; then # For Windows, use zip RELEASE_PACKAGE_FILE_NAME="${RELEASE_PACKAGE_NAME}.zip" RELEASE_PACKAGE_FILE_PATH="${RELEASE_FOLDER}/${RELEASE_PACKAGE_FILE_NAME}" zip "${RELEASE_PACKAGE_FILE_PATH}" "${TARGETS[@]}" if [[ $? != "0" ]]; then exit 1 fi # Checksum cd "${RELEASE_FOLDER}" shasum -a 256 "${RELEASE_PACKAGE_FILE_NAME}" > "${RELEASE_PACKAGE_FILE_NAME}.sha256" else # For others, Linux, OS X, uses tar.xz # For Darwin, .DS_Store and other related files should be ignored if [[ "$(uname -s)" == "Darwin" ]]; then export COPYFILE_DISABLE=1 fi RELEASE_PACKAGE_FILE_NAME="${RELEASE_PACKAGE_NAME}.tar.xz" RELEASE_PACKAGE_FILE_PATH="${RELEASE_FOLDER}/${RELEASE_PACKAGE_FILE_NAME}" tar -cJf "${RELEASE_PACKAGE_FILE_PATH}" "${TARGETS[@]}" if [[ $? != "0" ]]; then exit 1 fi # Checksum cd "${RELEASE_FOLDER}" shasum -a 256 "${RELEASE_PACKAGE_FILE_NAME}" > "${RELEASE_PACKAGE_FILE_NAME}.sha256" fi echo "Finished build release ${RELEASE_PACKAGE_FILE_PATH}" ================================================ FILE: build/build-host-release.ps1 ================================================ #!pwsh <# OpenSSL is already installed on windows-latest virtual environment. If you need OpenSSL, consider install it by: choco install openssl #> param( [Parameter(HelpMessage = "extra features")] [Alias('f')] [string]$Features ) $ErrorActionPreference = "Stop" $TargetTriple = (rustc -Vv | Select-String -Pattern "host: (.*)" | ForEach-Object { $_.Matches.Value }).split()[-1] Write-Host "Started building release for ${TargetTriple} ..." if ([string]::IsNullOrEmpty($Features)) { cargo build --release } else { cargo build --release --features "${Features}" } if (!$?) { exit $LASTEXITCODE } $Version = (Select-String -Pattern '^version *= *"([^"]*)"$' -Path "${PSScriptRoot}\..\Cargo.toml" | ForEach-Object { $_.Matches.Value }).split()[-1] $Version = $Version -replace '"' $PackageReleasePath = "${PSScriptRoot}\release" $PackageName = "shadowsocks-v${Version}.${TargetTriple}.zip" $PackagePath = "${PackageReleasePath}\${PackageName}" $ReleaseBuildPath = "${PSScriptRoot}\..\target\release" Write-Host $Version Write-Host $PackageReleasePath Write-Host $PackageName Write-Host $PackagePath Write-Host $ReleaseBuildPath Push-Location $ReleaseBuildPath $ProgressPreference = "SilentlyContinue" New-Item "${PackageReleasePath}" -ItemType Directory -ErrorAction SilentlyContinue $CompressParam = @{ LiteralPath = "sslocal.exe", "ssserver.exe", "ssurl.exe", "ssmanager.exe", "ssservice.exe" DestinationPath = "${PackagePath}" } if ([System.IO.File]::Exists("$ReleaseBuildPath\sswinservice.exe")) { $CompressParam.LiteralPath += "sswinservice.exe" } Compress-Archive @CompressParam Write-Host "Created release packet ${PackagePath}" $PackageChecksumPath = "${PackagePath}.sha256" $PackageHash = (Get-FileHash -Path "${PackagePath}" -Algorithm SHA256).Hash "${PackageHash} ${PackageName}" | Out-File -FilePath "${PackageChecksumPath}" Write-Host "Created release packet checksum ${PackageChecksumPath}" Pop-Location ================================================ FILE: build/build-release ================================================ #!/bin/bash CUR_DIR=$( cd $( dirname $0 ) && pwd ) VERSION=$(grep -E '^version' ${CUR_DIR}/../Cargo.toml | awk '{print $3}' | sed 's/"//g') ## Disable macos ACL file if [[ "$(uname -s)" == "Darwin" ]]; then export COPYFILE_DISABLE=1 fi targets=() features=() use_upx=false use_nightly=false cargo_flags="" while getopts "t:f:unZ:" opt; do case $opt in t) targets+=($OPTARG) ;; f) features+=($OPTARG) ;; u) use_upx=true ;; n) use_nightly=true ;; Z) cargo_flags="-Z $OPTARG" ;; ?) echo "Usage: $(basename $0) [-t ] [-f features] [-u] [-n]" ;; esac done features+=${EXTRA_FEATURES} if [[ "${#targets[@]}" == "0" ]]; then echo "Specifying compile target with -t " exit 1 fi if [[ "${use_upx}" = true ]]; then if [[ -z "$upx" ]] && command -v upx &> /dev/null; then upx="upx -9" fi if [[ "x$upx" == "x" ]]; then echo "Couldn't find upx in PATH, consider specifying it with variable \$upx" exit 1 fi fi build_command="cross" if [[ "${use_nightly}" = true ]]; then build_command="$build_command +nightly" fi function build() { cd "$CUR_DIR/.." TARGET=$1 RELEASE_DIR="target/${TARGET}/release" TARGET_FEATURES="${features[@]}" if [[ "${TARGET_FEATURES}" != "" ]]; then echo "* Building ${TARGET} package ${VERSION} with features \"${TARGET_FEATURES}\" ..." $build_command build --target "${TARGET}" \ --features "${TARGET_FEATURES}" \ --release \ ${cargo_flags} else echo "* Building ${TARGET} package ${VERSION} ..." $build_command build --target "${TARGET}" \ --release \ ${cargo_flags} fi if [[ $? != "0" ]]; then exit 1 fi PKG_DIR="${CUR_DIR}/release" mkdir -p "${PKG_DIR}" if [[ "$TARGET" == *"-linux-"* || "$TARGET" == *"-freebsd" || "$TARGET" == *"-netbsd" ]]; then PKG_NAME="shadowsocks-v${VERSION}.${TARGET}.tar.xz" PKG_PATH="${PKG_DIR}/${PKG_NAME}" cd ${RELEASE_DIR} if [[ "${use_upx}" = true ]]; then # Enable upx for MIPS. $upx sslocal ssserver ssurl ssmanager ssservice #>/dev/null fi echo "* Packaging XZ in ${PKG_PATH} ..." tar -cJf ${PKG_PATH} \ "sslocal" \ "ssserver" \ "ssurl" \ "ssmanager" \ "ssservice" if [[ $? != "0" ]]; then exit 1 fi cd "${PKG_DIR}" shasum -a 256 "${PKG_NAME}" > "${PKG_NAME}.sha256" elif [[ "$TARGET" == *"-windows-"* ]]; then PKG_NAME="shadowsocks-v${VERSION}.${TARGET}.zip" PKG_PATH="${PKG_DIR}/${PKG_NAME}" echo "* Packaging ZIP in ${PKG_PATH} ..." cd ${RELEASE_DIR} sswinservice="" if [ -e "sswinservice.exe" ]; then sswinservice="sswinservice.exe" fi zip ${PKG_PATH} \ "sslocal.exe" \ "ssserver.exe" \ "ssurl.exe" \ "ssmanager.exe" \ "ssservice.exe" \ "${sswinservice}" if [[ $? != "0" ]]; then exit 1 fi cd "${PKG_DIR}" shasum -a 256 "${PKG_NAME}" > "${PKG_NAME}.sha256" fi echo "* Done build package ${PKG_NAME}" } for target in "${targets[@]}"; do build "$target"; done ================================================ FILE: cargo-publish.sh ================================================ #!/bin/bash -e set -x ROOT_DIR=$(dirname $0) cd ${ROOT_DIR:?} package_ordered="crates/shadowsocks crates/shadowsocks-service ." ## dry-run cargo check for p in ${package_ordered:?}; do cargo update -p shadowsocks cargo update -p shadowsocks-service #echo "====> dry-run publish $p" #cargo publish --verbose --locked --dry-run --manifest-path "${p:?}/Cargo.toml" echo "====> publishing $p" cargo publish --verbose --locked --manifest-path "${p:?}/Cargo.toml" # this seems to be enough time to let crates.io update sleep 10 done ================================================ FILE: clippy.toml ================================================ msrv = "1.88" ================================================ FILE: configs/genipset.py ================================================ #!/usr/bin/env python3 # -*- coding:utf-8 -*- import sys import time APNIC_DELEGATED_LATEST = "https://ftp.apnic.net/apnic/stats/apnic/delegated-apnic-latest" def get_apnic_delegated(): from urllib import request u = request.urlopen(APNIC_DELEGATED_LATEST) return u.read().decode('utf-8') def generate_ipset(content, name, location_set, type_set, output_file): if 'ipv4' in type_set: cidr_trans = {} for i in range(0, 32): cidr_trans[2 ** (32 - i - 1)] = i + 1 for line in content.splitlines(): if line.startswith('#'): continue splits = line.split('|') if len(splits) == 7: ''' This is a Record with 7 fields ''' registry, cc, type_, start, value, _, _ = splits if registry != 'apnic': continue if cc in location_set and type_ in type_set: if type_ == 'ipv4': ''' In the case of IPv4 address the count of hosts for this range. This count does not have to represent a CIDR range. But. It seems that it is always a CIDR range in this particular file. ''' mask = cidr_trans[int(value)] output_file.write( 'add {} {}/{} -exist\n'.format(name, start, mask)) elif type_ == 'ipv6': ''' In the case of an IPv6 address the value will be the CIDR prefix length from the ‘first address’ value of . ''' output_file.write( 'add {} {}/{} -exist\n'.format(name, start, value)) if __name__ == '__main__': import argparse parser = argparse.ArgumentParser() parser.add_argument('--name', '-n', help='Name of ipset', type=str, required=True) parser.add_argument('--location', '-l', help='Location to be filtered, like CN', nargs='+', type=str, required=True) parser.add_argument('--address-type', '-t', help='Address type, like ipv4, ipv6', nargs='+', type=str, required=True, choices=['ipv4', 'ipv6']) parser.add_argument( '--output', '-o', help='Output file, default to stdout', type=str, required=False) args = parser.parse_args() name = args.name location_set = set(args.location) type_set = set(args.address_type) start_time = time.time() data = get_apnic_delegated() if hasattr(args, 'output'): with open(args.output, 'w') as fp: generate_ipset(data, name, location_set, type_set, fp) else: generate_ipset(data, name, location_set, type_set, sys.stdout) ================================================ FILE: configs/iptables_mixed.sh ================================================ #!/bin/bash iptables-save | grep -v shadowsocks- | iptables-restore ip6tables-save | grep -v shadowsocks- | ip6tables-restore ### IPv4 RULES # Create chnip ipset ipset create chnip hash:net family inet -exist ipset restore < /usr/local/etc/chnip.ipset # Create gfwlist ipset ipset create gfwlist hash:ip family inet timeout 7200 -exist ipset create bypasslist hash:ip family inet timeout 7200 -exist SHADOWSOCKS_REDIR_IP=0.0.0.0 SHADOWSOCKS_REDIR_PORT=60080 readonly IPV4_RESERVED_IPADDRS="\ 0/8 \ 10/8 \ 100.64/10 \ 127/8 \ 169.254/16 \ 172.16/12 \ 192/24 \ 192.0.2.0/24 \ 192.88.99/24 \ 192.168/16 \ 198.18/15 \ 198.51.100/24 \ 203.0.113/24 \ 224/4 \ 240/4 \ 255.255.255.255/32 \ " ## TCP # NAT PREROUTING iptables -t nat -N shadowsocks-nat # Skip LoopBack, Reserved for addr in ${IPV4_RESERVED_IPADDRS}; do iptables -t nat -A shadowsocks-nat -d "${addr}" -j RETURN done # Bypass sslocal's outbound data iptables -t nat -A shadowsocks-nat -m mark --mark 0xff/0xff -j RETURN iptables -t nat -A shadowsocks-nat -m owner --uid-owner shadowsocks -j RETURN # Proxy gfwlist iptables -t nat -A shadowsocks-nat -m set --match-set gfwlist dst -p tcp -j REDIRECT --to-ports ${SHADOWSOCKS_REDIR_PORT} # Bypass CN IPs iptables -t nat -A shadowsocks-nat -m set --match-set chnip dst -p tcp -j RETURN iptables -t nat -A shadowsocks-nat -m set --match-set bypasslist dst -p tcp -j RETURN # Redirect TCP to 60080 iptables -t nat -A shadowsocks-nat -p tcp -j REDIRECT --to-ports ${SHADOWSOCKS_REDIR_PORT} # Local TCP -> shadowsocks-nat iptables -t nat -A OUTPUT -p tcp -j shadowsocks-nat # LAN TCP -> shadowsocks-nat iptables -t nat -A PREROUTING -p tcp -j shadowsocks-nat ## UDP # Strategy Route ip -4 rule del fwmark 0x1 table 803 ip -4 rule add fwmark 0x1 table 803 ip -4 route del local 0.0.0.0/0 dev lo table 803 ip -4 route add local 0.0.0.0/0 dev lo table 803 # TPROXY for LAN iptables -t mangle -N shadowsocks-tproxy # Skip LoopBack, Reserved for addr in ${IPV4_RESERVED_IPADDRS}; do iptables -t mangle -A shadowsocks-tproxy -d "${addr}" -j RETURN done # Bypass sslocal's outbound data iptables -t mangle -A shadowsocks-tproxy -m mark --mark 0xff/0xff -j RETURN # Proxy gfwlist iptables -t mangle -A shadowsocks-tproxy -m set --match-set gfwlist dst -p udp -j TPROXY --on-ip ${SHADOWSOCKS_REDIR_IP} --on-port ${SHADOWSOCKS_REDIR_PORT} --tproxy-mark 0x01/0x01 # Bypass CN IPs iptables -t mangle -A shadowsocks-tproxy -m set --match-set chnip dst -p udp -j RETURN iptables -t mangle -A shadowsocks-tproxy -m set --match-set bypasslist dst -p udp -j RETURN # TPROXY UDP to 60080 iptables -t mangle -A shadowsocks-tproxy -p udp -j TPROXY --on-ip ${SHADOWSOCKS_REDIR_IP} --on-port ${SHADOWSOCKS_REDIR_PORT} --tproxy-mark 0x01/0x01 # TPROXY for Local iptables -t mangle -N shadowsocks-tproxy-mark # Skip LoopBack, Reserved for addr in ${IPV4_RESERVED_IPADDRS}; do iptables -t mangle -A shadowsocks-tproxy-mark -d "${addr}" -j RETURN done # Bypass sslocal's outbound data iptables -t mangle -A shadowsocks-tproxy-mark -m mark --mark 0xff/0xff -j RETURN iptables -t mangle -A shadowsocks-tproxy-mark -m owner --uid-owner shadowsocks -j RETURN # Proxy gfwlist iptables -t mangle -A shadowsocks-tproxy-mark -m set --match-set gfwlist dst -j MARK --set-xmark 0x01/0xffffffff # Bypass CN IPs iptables -t mangle -A shadowsocks-tproxy-mark -m set --match-set chnip dst -j RETURN # Set MARK and reroute iptables -t mangle -A shadowsocks-tproxy-mark -p udp -j MARK --set-xmark 0x01/0xffffffff #iptables -t mangle -A shadowsocks-tproxy-mark -p tcp -j MARK --set-xmark 1 # Apply TPROXY to LAN iptables -t mangle -A PREROUTING -p udp -j shadowsocks-tproxy #iptables -t mangle -A PREROUTING -p udp -m addrtype ! --src-type LOCAL ! --dst-type LOCAL -j shadowsocks-tproxy # Apply TPROXY for Local iptables -t mangle -A OUTPUT -p udp -j shadowsocks-tproxy-mark #iptables -t mangle -A OUTPUT -p udp -m addrtype --src-type LOCAL ! --dst-type LOCAL -j shadowsocks-tproxy-mark # DIVERT rules # For optimizing TCP # iptables -t mangle -N shadowsocks-divert # iptables -t mangle -A shadowsocks-divert -j MARK --set-mark 1 # iptables -t mangle -A shadowsocks-divert -j ACCEPT # iptables -t mangle -I PREROUTING -p tcp -m socket -j shadowsocks-divert ### IPv6 RULES # Create chnip6 ipset ipset create chnip6 hash:net family inet6 -exist ipset restore < /usr/local/etc/chnip6.ipset # Create gfwlist6 ipset ipset create gfwlist6 hash:ip family inet6 timeout 7200 -exist ipset create bypasslist6 hash:ip family inet6 timeout 7200 -exist SHADOWSOCKS6_REDIR_IP=:: SHADOWSOCKS6_REDIR_PORT=60081 readonly IPV6_RESERVED_IPADDRS="\ ::/128 \ ::1/128 \ ::ffff:0:0/96 \ ::ffff:0:0:0/96 \ 64:ff9b::/96 \ 100::/64 \ 2001::/32 \ 2001:20::/28 \ 2001:db8::/32 \ 2002::/16 \ fc00::/7 \ fe80::/10 \ ff00::/8 \ " ## TCP # NAT PREROUTING ip6tables -t nat -N shadowsocks-nat # Skip LoopBack, Reserved for addr in ${IPV6_RESERVED_IPADDRS}; do ip6tables -t nat -A shadowsocks-nat -d "${addr}" -j RETURN done # Bypass sslocal's outbound data ip6tables -t nat -A shadowsocks-nat -m mark --mark 0xff/0xff -j RETURN ip6tables -t nat -A shadowsocks-nat -m owner --uid-owner shadowsocks -j RETURN # Proxy gfwlist6 ip6tables -t nat -A shadowsocks-nat -m set --match-set gfwlist6 dst -p tcp -j REDIRECT --to-ports ${SHADOWSOCKS6_REDIR_PORT} # Bypass CN IPs ip6tables -t nat -A shadowsocks-nat -m set --match-set chnip6 dst -p tcp -j RETURN ip6tables -t nat -A shadowsocks-nat -m set --match-set bypasslist6 dst -p tcp -j RETURN # Redirect TCP to 60081 ip6tables -t nat -A shadowsocks-nat -p tcp -j REDIRECT --to-ports ${SHADOWSOCKS6_REDIR_PORT} # Local TCP -> shadowsocks-nat ip6tables -t nat -A OUTPUT -p tcp -j shadowsocks-nat # LAN TCP -> shadowsocks-nat ip6tables -t nat -A PREROUTING -p tcp -j shadowsocks-nat ## UDP # Strategy Route ip -6 rule del fwmark 0x1 table 803 ip -6 rule add fwmark 0x1 table 803 ip -6 route del local ::/0 dev lo table 803 ip -6 route add local ::/0 dev lo table 803 # TPROXY for LAN ip6tables -t mangle -N shadowsocks-tproxy # Skip LoopBack, Reserved for addr in ${IPV6_RESERVED_IPADDRS}; do ip6tables -t mangle -A shadowsocks-tproxy -d "${addr}" -j RETURN done # Bypass sslocal's outbound data ip6tables -t mangle -A shadowsocks-tproxy -m mark --mark 0xff/0xff -j RETURN # Proxy gfwlist6 ip6tables -t mangle -A shadowsocks-tproxy -m set --match-set gfwlist6 dst -p udp -j TPROXY --on-ip ${SHADOWSOCKS6_REDIR_IP} --on-port ${SHADOWSOCKS6_REDIR_PORT} --tproxy-mark 0x01/0x01 # Bypass CN IPs ip6tables -t mangle -A shadowsocks-tproxy -m set --match-set chnip6 dst -p udp -j RETURN ip6tables -t mangle -A shadowsocks-tproxy -m set --match-set bypasslist6 dst -p udp -j RETURN # TPROXY UDP to 60081 ip6tables -t mangle -A shadowsocks-tproxy -p udp -j TPROXY --on-ip ${SHADOWSOCKS6_REDIR_IP} --on-port ${SHADOWSOCKS6_REDIR_PORT} --tproxy-mark 0x01/0x01 # TPROXY for Local ip6tables -t mangle -N shadowsocks-tproxy-mark # Skip LoopBack, Reserved for addr in ${IPV6_RESERVED_IPADDRS}; do ip6tables -t mangle -A shadowsocks-tproxy-mark -d "${addr}" -j RETURN done # Bypass sslocal's outbound data ip6tables -t mangle -A shadowsocks-tproxy-mark -m mark --mark 0xff/0xff -j RETURN ip6tables -t mangle -A shadowsocks-tproxy-mark -m owner --uid-owner shadowsocks -j RETURN # Proxy gfwlist6 ip6tables -t mangle -A shadowsocks-tproxy-mark -m set --match-set gfwlist6 dst -j MARK --set-xmark 0x01/0xffffffff # Bypass CN IPs ip6tables -t mangle -A shadowsocks-tproxy-mark -m set --match-set chnip6 dst -j RETURN # Set MARK and reroute ip6tables -t mangle -A shadowsocks-tproxy-mark -p udp -j MARK --set-xmark 0x01/0xffffffff #ip6tables -t mangle -A shadowsocks-tproxy-mark -p tcp -j MARK --set-xmark 1 # Apply TPROXY to LAN ip6tables -t mangle -A PREROUTING -p udp -j shadowsocks-tproxy #ip6tables -t mangle -A PREROUTING -p udp -m addrtype ! --src-type LOCAL ! --dst-type LOCAL -j shadowsocks-tproxy # Apply TPROXY for Local ip6tables -t mangle -A OUTPUT -p udp -j shadowsocks-tproxy-mark #ip6tables -t mangle -A OUTPUT -p udp -m addrtype --src-type LOCAL ! --dst-type LOCAL -j shadowsocks-tproxy-mark # DIVERT rules # For optimizing TCP # ip6tables -t mangle -N shadowsocks-divert # ip6tables -t mangle -A shadowsocks-divert -j MARK --set-mark 1 # ip6tables -t mangle -A shadowsocks-divert -j ACCEPT # ip6tables -t mangle -I PREROUTING -p tcp -m socket -j shadowsocks-divert ================================================ FILE: configs/iptables_tproxy.sh ================================================ #!/bin/bash iptables-save | grep -v shadowsocks- | iptables-restore ip6tables-save | grep -v shadowsocks- | ip6tables-restore ### IPv4 RULES # Create chnip ipset ipset create chnip hash:net family inet -exist ipset restore < /usr/local/etc/chnip.ipset # Create gfwlist ipset ipset create gfwlist hash:ip family inet timeout 7200 -exist ipset create bypasslist hash:ip family inet timeout 7200 -exist SHADOWSOCKS_REDIR_IP=0.0.0.0 SHADOWSOCKS_REDIR_PORT=60080 readonly IPV4_RESERVED_IPADDRS="\ 0/8 \ 10/8 \ 100.64/10 \ 127/8 \ 169.254/16 \ 172.16/12 \ 192/24 \ 192.0.2.0/24 \ 192.88.99/24 \ 192.168/16 \ 198.18/15 \ 198.51.100/24 \ 203.0.113/24 \ 224/4 \ 240/4 \ 255.255.255.255/32 \ " ## TCP+UDP # Strategy Route ip -4 rule del fwmark 0x1 table 803 ip -4 rule add fwmark 0x1 table 803 ip -4 route del local 0.0.0.0/0 dev lo table 803 ip -4 route add local 0.0.0.0/0 dev lo table 803 # TPROXY for LAN iptables -t mangle -N shadowsocks-tproxy # Skip LoopBack, Reserved for addr in ${IPV4_RESERVED_IPADDRS}; do iptables -t mangle -A shadowsocks-tproxy -d "${addr}" -j RETURN done # Bypass LAN data iptables -t mangle -A shadowsocks-tproxy -m addrtype --dst-type LOCAL -j RETURN # Bypass sslocal's outbound data iptables -t mangle -A shadowsocks-tproxy -m mark --mark 0xff/0xff -j RETURN # UDP: Proxy gfwlist iptables -t mangle -A shadowsocks-tproxy -m set --match-set gfwlist dst -p udp -j TPROXY --on-ip ${SHADOWSOCKS_REDIR_IP} --on-port ${SHADOWSOCKS_REDIR_PORT} --tproxy-mark 0x01/0x01 # UDP: Bypass CN IPs iptables -t mangle -A shadowsocks-tproxy -m set --match-set chnip dst -p udp -j RETURN iptables -t mangle -A shadowsocks-tproxy -m set --match-set bypasslist dst -p udp -j RETURN # UDP: TPROXY UDP to 60080 iptables -t mangle -A shadowsocks-tproxy -p udp -j TPROXY --on-ip ${SHADOWSOCKS_REDIR_IP} --on-port ${SHADOWSOCKS_REDIR_PORT} --tproxy-mark 0x01/0x01 # TCP: Proxy gfwlist iptables -t mangle -A shadowsocks-tproxy -m set --match-set gfwlist dst -p tcp -j TPROXY --on-ip ${SHADOWSOCKS_REDIR_IP} --on-port ${SHADOWSOCKS_REDIR_PORT} --tproxy-mark 0x01/0x01 # TCP: Bypass CN IPs iptables -t mangle -A shadowsocks-tproxy -m set --match-set chnip dst -p tcp -j RETURN iptables -t mangle -A shadowsocks-tproxy -m set --match-set bypasslist dst -p tcp -j RETURN # TCP: TPROXY TCP to 60080 iptables -t mangle -A shadowsocks-tproxy -p tcp -j TPROXY --on-ip ${SHADOWSOCKS_REDIR_IP} --on-port ${SHADOWSOCKS_REDIR_PORT} --tproxy-mark 0x01/0x01 # TPROXY for Local iptables -t mangle -N shadowsocks-tproxy-mark # Skip LoopBack, Reserved for addr in ${IPV4_RESERVED_IPADDRS}; do iptables -t mangle -A shadowsocks-tproxy-mark -d "${addr}" -j RETURN done # TCP: conntrack iptables -t mangle -A shadowsocks-tproxy-mark -p tcp -m conntrack --ctdir REPLY -j RETURN # Bypass sslocal's outbound data iptables -t mangle -A shadowsocks-tproxy-mark -m mark --mark 0xff/0xff -j RETURN iptables -t mangle -A shadowsocks-tproxy-mark -m owner --uid-owner shadowsocks -j RETURN # Proxy gfwlist iptables -t mangle -A shadowsocks-tproxy-mark -m set --match-set gfwlist dst -j MARK --set-xmark 0x01/0xffffffff # Bypass CN IPs iptables -t mangle -A shadowsocks-tproxy-mark -m set --match-set chnip dst -j RETURN # UDP: Set MARK and reroute iptables -t mangle -A shadowsocks-tproxy-mark -p udp -j MARK --set-xmark 0x01/0xffffffff # TCP: Set MARK and reroute iptables -t mangle -A shadowsocks-tproxy-mark -p tcp -j MARK --set-xmark 0x01/0xffffffff # Apply TPROXY to LAN iptables -t mangle -A PREROUTING -p udp -j shadowsocks-tproxy iptables -t mangle -A PREROUTING -p tcp -j shadowsocks-tproxy #iptables -t mangle -A PREROUTING -p udp -m addrtype ! --src-type LOCAL ! --dst-type LOCAL -j shadowsocks-tproxy # Apply TPROXY for Local iptables -t mangle -A OUTPUT -p udp -j shadowsocks-tproxy-mark iptables -t mangle -A OUTPUT -p tcp -j shadowsocks-tproxy-mark #iptables -t mangle -A OUTPUT -p udp -m addrtype --src-type LOCAL ! --dst-type LOCAL -j shadowsocks-tproxy-mark # DIVERT rules # For optimizing TCP # iptables -t mangle -N shadowsocks-divert # iptables -t mangle -A shadowsocks-divert -j MARK --set-mark 1 # iptables -t mangle -A shadowsocks-divert -j ACCEPT # iptables -t mangle -I PREROUTING -p tcp -m socket -j shadowsocks-divert ### IPv6 RULES # Create chnip6 ipset ipset create chnip6 hash:net family inet6 -exist ipset restore < /usr/local/etc/chnip6.ipset # Create gfwlist6 ipset ipset create gfwlist6 hash:ip family inet6 timeout 7200 -exist ipset create bypasslist6 hash:ip family inet6 timeout 7200 -exist SHADOWSOCKS6_REDIR_IP=:: SHADOWSOCKS6_REDIR_PORT=60081 readonly IPV6_RESERVED_IPADDRS="\ ::/128 \ ::1/128 \ ::ffff:0:0/96 \ ::ffff:0:0:0/96 \ 64:ff9b::/96 \ 100::/64 \ 2001::/32 \ 2001:20::/28 \ 2001:db8::/32 \ 2002::/16 \ fc00::/7 \ fe80::/10 \ ff00::/8 \ " ## TCP+UDP # Strategy Route ip -6 rule del fwmark 0x1 table 803 ip -6 rule add fwmark 0x1 table 803 ip -6 route del local ::/0 dev lo table 803 ip -6 route add local ::/0 dev lo table 803 # TPROXY for LAN ip6tables -t mangle -N shadowsocks-tproxy # Skip LoopBack, Reserved for addr in ${IPV6_RESERVED_IPADDRS}; do ip6tables -t mangle -A shadowsocks-tproxy -d "${addr}" -j RETURN done # Bypass LAN data ip6tables -t mangle -A shadowsocks-tproxy -m addrtype --dst-type LOCAL -j RETURN # Bypass sslocal's outbound data ip6tables -t mangle -A shadowsocks-tproxy -m mark --mark 0xff/0xff -j RETURN # UDP: Proxy gfwlist6 ip6tables -t mangle -A shadowsocks-tproxy -m set --match-set gfwlist6 dst -p udp -j TPROXY --on-ip ${SHADOWSOCKS6_REDIR_IP} --on-port ${SHADOWSOCKS6_REDIR_PORT} --tproxy-mark 0x01/0x01 # UDP: Bypass CN IPs ip6tables -t mangle -A shadowsocks-tproxy -m set --match-set chnip6 dst -p udp -j RETURN ip6tables -t mangle -A shadowsocks-tproxy -m set --match-set bypasslist6 dst -p udp -j RETURN # UDP: TPROXY UDP to 60081 ip6tables -t mangle -A shadowsocks-tproxy -p udp -j TPROXY --on-ip ${SHADOWSOCKS6_REDIR_IP} --on-port ${SHADOWSOCKS6_REDIR_PORT} --tproxy-mark 0x01/0x01 # TCP: Proxy gfwlist6 ip6tables -t mangle -A shadowsocks-tproxy -m set --match-set gfwlist6 dst -p tcp -j TPROXY --on-ip ${SHADOWSOCKS6_REDIR_IP} --on-port ${SHADOWSOCKS6_REDIR_PORT} --tproxy-mark 0x01/0x01 # TCP: Bypass CN IPs ip6tables -t mangle -A shadowsocks-tproxy -m set --match-set chnip6 dst -p tcp -j RETURN ip6tables -t mangle -A shadowsocks-tproxy -m set --match-set bypasslist6 dst -p tcp -j RETURN # TCP: TPROXY UDP to 60081 ip6tables -t mangle -A shadowsocks-tproxy -p tcp -j TPROXY --on-ip ${SHADOWSOCKS6_REDIR_IP} --on-port ${SHADOWSOCKS6_REDIR_PORT} --tproxy-mark 0x01/0x01 # TPROXY for Local ip6tables -t mangle -N shadowsocks-tproxy-mark # Skip LoopBack, Reserved for addr in ${IPV6_RESERVED_IPADDRS}; do ip6tables -t mangle -A shadowsocks-tproxy-mark -d "${addr}" -j RETURN done # TCP: conntrack ip6tables -t mangle -A shadowsocks-tproxy-mark -p tcp -m conntrack --ctdir REPLY -j RETURN # Bypass sslocal's outbound data ip6tables -t mangle -A shadowsocks-tproxy-mark -m mark --mark 0xff/0xff -j RETURN ip6tables -t mangle -A shadowsocks-tproxy-mark -m owner --uid-owner shadowsocks -j RETURN # Proxy gfwlist6 ip6tables -t mangle -A shadowsocks-tproxy-mark -m set --match-set gfwlist6 dst -j MARK --set-xmark 0x01/0xffffffff # Bypass CN IPs ip6tables -t mangle -A shadowsocks-tproxy-mark -m set --match-set chnip6 dst -j RETURN # Set MARK and reroute ip6tables -t mangle -A shadowsocks-tproxy-mark -p udp -j MARK --set-xmark 0x01/0xffffffff ip6tables -t mangle -A shadowsocks-tproxy-mark -p tcp -j MARK --set-xmark 0x01/0xffffffff # Apply TPROXY to LAN ip6tables -t mangle -A PREROUTING -p udp -j shadowsocks-tproxy ip6tables -t mangle -A PREROUTING -p tcp -j shadowsocks-tproxy #ip6tables -t mangle -A PREROUTING -p udp -m addrtype ! --src-type LOCAL ! --dst-type LOCAL -j shadowsocks-tproxy # Apply TPROXY for Local ip6tables -t mangle -A OUTPUT -p udp -j shadowsocks-tproxy-mark ip6tables -t mangle -A OUTPUT -p tcp -j shadowsocks-tproxy-mark #ip6tables -t mangle -A OUTPUT -p udp -m addrtype --src-type LOCAL ! --dst-type LOCAL -j shadowsocks-tproxy-mark # DIVERT rules # For optimizing TCP # ip6tables -t mangle -N shadowsocks-divert # ip6tables -t mangle -A shadowsocks-divert -j MARK --set-mark 1 # ip6tables -t mangle -A shadowsocks-divert -j ACCEPT ================================================ FILE: configs/log4rs.yaml ================================================ refresh_rate: 30 seconds appenders: stdout: kind: console encoder: pattern: "{d} {h({l}):<5} {m}{n}" file: kind: rolling_file path: shadowsocks.log encoder: kind: pattern pattern: "{d} {h({l}):<5} {m}{n}" policy: trigger: kind: size limit: 10 mb roller: kind: fixed_window pattern: shadowsocks.{}.log count: 5 root: level: info appenders: - stdout - file ================================================ FILE: configs/org.shadowsocks.shadowsocks-rust.plist ================================================ Disabled Label org.shadowsocks.shadowsocks-rust ProgramArguments /usr/local/bin/sslocal -c /usr/local/etc/shadowsocks.json RunAtLoad KeepAlive NetworkState WorkingDirectory / StandardErrorPath /tmp/shadowsocks-rust.stderr.log StandardOutPath /tmp/shadowsocks-rust.stdout.log SoftResourceLimits NumberOfFiles 10240 ================================================ FILE: configs/shadowsocks.procd.sh ================================================ #!/bin/sh /etc/rc.common START=30 USE_PROCD=1 EXTRA_COMMANDS="set_firewall destroy" EXTRA_HELP=</dev/null; then chown shadowsocks:shadowsocks -R ${SHADOWSOCKS_LOG_FILE_PATH} fi SHADOWSOCKS_CONFIG_PATH="/usr/local/etc/shadowsocks.json" SHADOWSOCKS_EXECUTABLE="/usr/local/bin/sslocal" SHADOWSOCKS_PARAMETERS="-c ${SHADOWSOCKS_CONFIG_PATH} --log-without-time --udp-max-associations 4192 --outbound-fwmark 255" SHADOWSOCKS_COMMAND="${SHADOWSOCKS_EXECUTABLE} ${SHADOWSOCKS_PARAMETERS}" procd_open_instance shadowsocks procd_set_param env RUST_BACKTRACE=1 procd_set_param env NO_COLOR=1 procd_set_param file ${SHADOWSOCKS_CONFIG_PATH} procd_set_param respawn procd_set_param reload_signal USR1 procd_set_param limits nofile="10240 10240" procd_set_param limits core="unlimited" procd_set_param stdout 1 procd_set_param stderr 1 if id "shadowsocks" &>/dev/null; then if [ -x /sbin/ujail -a -e ${SHADOWSOCKS_CAPABILITIES_CONFIG_PATH} ]; then procd_add_jail shadowsocks requirejail procd_add_jail_mount ${SHADOWSOCKS_CONFIG_PATH} procd_set_param user shadowsocks procd_set_param group shadowsocks procd_set_param capabilities ${SHADOWSOCKS_CAPABILITIES_CONFIG_PATH} procd_set_param no_new_privs 1 procd_set_param command ${SHADOWSOCKS_COMMAND} else procd_set_param user root procd_set_param command /usr/sbin/capsh --caps="cap_setpcap,cap_setuid,cap_setgid+ep cap_net_admin,cap_net_raw,cap_net_bind_service+eip" --keep=1 \ --user="shadowsocks" --addamb="cap_net_admin,cap_net_raw,cap_net_bind_service" \ --shell="${SHADOWSOCKS_EXECUTABLE}" -- ${SHADOWSOCKS_PARAMETERS} fi else procd_set_param user root procd_set_param command ${SHADOWSOCKS_COMMAND} fi SHADOWSOCKS6_CONFIG_PATH="/usr/local/etc/shadowsocks6.json" SHADOWSOCKS6_EXECUTABLE="/usr/local/bin/sslocal" SHADOWSOCKS6_PARAMETERS="-c ${SHADOWSOCKS6_CONFIG_PATH} --log-without-time --udp-max-associations 4192 --outbound-fwmark 255" SHADOWSOCKS6_COMMAND="${SHADOWSOCKS6_EXECUTABLE} ${SHADOWSOCKS6_PARAMETERS}" procd_set_param pidfile /var/run/shadowsocks.pid procd_close_instance procd_open_instance shadowsocks6 procd_set_param env RUST_BACKTRACE=1 procd_set_param env NO_COLOR=1 procd_set_param file ${SHADOWSOCKS6_CONFIG_PATH} procd_set_param respawn procd_set_param reload_signal USR1 procd_set_param limits nofile="10240 10240" procd_set_param limits core="unlimited" procd_set_param stdout 1 procd_set_param stderr 1 if id "shadowsocks" &>/dev/null; then if [ -x /sbin/ujail -a -e ${SHADOWSOCKS_CAPABILITIES_CONFIG_PATH} ]; then procd_add_jail shadowsocks6 requirejail procd_add_jail_mount ${SHADOWSOCKS6_CONFIG_PATH} procd_set_param user shadowsocks procd_set_param group shadowsocks procd_set_param capabilities ${SHADOWSOCKS_CAPABILITIES_CONFIG_PATH} procd_set_param no_new_privs 1 procd_set_param command ${SHADOWSOCKS6_COMMAND} else procd_set_param user root procd_set_param command /usr/sbin/capsh --caps="cap_setpcap,cap_setuid,cap_setgid+ep cap_net_admin,cap_net_raw,cap_net_bind_service+eip" --keep=1 \ --user="shadowsocks" --addamb="cap_net_admin,cap_net_raw,cap_net_bind_service" \ --shell="${SHADOWSOCKS6_EXECUTABLE}" -- ${SHADOWSOCKS6_PARAMETERS} fi else procd_set_param user root procd_set_param command ${SHADOWSOCKS6_COMMAND} fi procd_set_param pidfile /var/run/shadowsocks6.pid procd_close_instance echo 'Started shadowsocks service' } service_stopped() { echo 'Stopped shadowsocks service' } service_triggers() { #procd_add_reload_interface_trigger "pppoe-wan" procd_add_interface_trigger "interface.*" "pppoe-wan" /etc/init.d/shadowsocks restart } ================================================ FILE: crates/shadowsocks/Cargo.toml ================================================ [package] name = "shadowsocks" version = "1.24.0" authors = ["Shadowsocks Contributors"] description = "shadowsocks is a fast tunnel proxy that helps you bypass firewalls." repository = "https://github.com/shadowsocks/shadowsocks-rust" readme = "README.md" documentation = "https://docs.rs/shadowsocks-core" keywords = ["shadowsocks", "proxy", "socks", "socks5", "firewall"] license = "MIT" edition = "2024" rust-version = "1.88" [badges] maintenance = { status = "passively-maintained" } [features] default = ["hickory-dns", "aead-cipher"] # Uses Hickory-DNS instead of tokio's builtin DNS resolver hickory-dns = ["hickory-resolver", "arc-swap", "notify"] # Hickory-DNS was renamed from Trust-DNS, keep compatibility. trust-dns = ["hickory-dns"] # Enable Stream Cipher Protocol # WARN: Stream Cipher Protocol is proved to be insecure # https://github.com/shadowsocks/shadowsocks-rust/issues/373 # Users should always avoid using these ciphers in practice stream-cipher = ["shadowsocks-crypto/v1-stream", "shadowsocks-crypto/ring"] # Enable AEAD ciphers aead-cipher = ["shadowsocks-crypto/v1-aead", "shadowsocks-crypto/ring"] # Enable extra AEAD ciphers # WARN: These non-standard AEAD ciphers are not officially supported by shadowsocks community aead-cipher-extra = ["aead-cipher", "shadowsocks-crypto/v1-aead-extra"] aead-cipher-2022 = [ "shadowsocks-crypto/v2", "shadowsocks-crypto/ring", "rand", "aes", "lru_time_cache", ] # Enable AEAD 2022 # Enable AEAD 2022 with extra ciphers aead-cipher-2022-extra = ["aead-cipher-2022", "shadowsocks-crypto/v2-extra"] # Enable detection against replay attack security-replay-attack-detect = ["bloomfilter"] [dependencies] log = "0.4" libc = "~0.2.141" bytes = "1.7" cfg-if = "1" byte_string = "1.0" base64 = "0.22" url = "2.5" spin = { version = "0.10", features = ["std"] } pin-project = "1.1" bloomfilter = { version = "3.0.0", optional = true } thiserror = "2.0" rand = { version = "0.10", optional = true } lru_time_cache = { version = "0.11", optional = true } serde = { version = "1.0", features = ["derive"] } serde_urlencoded = "0.7" serde_json = "1.0" percent-encoding = "2.1" futures = "0.3" trait-variant = "0.1" dynosaur = "0.3.0" sealed = "0.6" socket2 = { version = "0.6", features = ["all"] } tokio = { version = "1.9.0", features = [ "io-util", "macros", "net", "parking_lot", "process", "rt", "sync", "time", ] } hickory-resolver = { version = "0.25", optional = true } arc-swap = { version = "1.7", optional = true } notify = { version = "8.0", optional = true } aes = { version = "0.8", optional = true } blake3 = "1.5" shadowsocks-crypto = { version = "0.6.0", default-features = false } [target.'cfg(any(windows, target_os = "linux", target_os = "android", target_os = "freebsd", target_os = "macos", target_os = "ios", target_os = "watchos", target_os = "tvos"))'.dependencies] tokio-tfo = "0.4.3" [target.'cfg(windows)'.dependencies] windows-sys = { version = "0.61", features = [ "Win32_Foundation", "Win32_NetworkManagement_IpHelper", "Win32_NetworkManagement_Ndis", "Win32_Networking_WinSock", "Win32_System_IO", ] } [target.'cfg(unix)'.dependencies] sendfd = { version = "0.4", features = ["tokio"] } [dev-dependencies] env_logger = "0.11" [lints.clippy] uninlined_format_args = "allow" ================================================ FILE: crates/shadowsocks/LICENSE ================================================ The MIT License (MIT) Copyright (c) 2017 Y. T. CHUNG 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. ================================================ FILE: crates/shadowsocks/README.md ================================================ # shadowsocks [![License](https://img.shields.io/github/license/zonyitoo/shadowsocks-rust.svg)](https://github.com/zonyitoo/shadowsocks-rust) [![crates.io](https://img.shields.io/crates/v/shadowsocks.svg)](https://crates.io/crates/shadowsocks) [![docs.rs](https://img.shields.io/docsrs/shadowsocks)](https://docs.rs/shadowsocks) This is a port of [shadowsocks](https://github.com/shadowsocks/shadowsocks). shadowsocks is a fast tunnel proxy that helps you bypass firewalls. ================================================ FILE: crates/shadowsocks/src/config.rs ================================================ //! Configuration #[cfg(unix)] use std::path::PathBuf; use std::{ collections::HashMap, fmt::{self, Debug, Display}, net::SocketAddr, str::{self, FromStr}, sync::Arc, time::Duration, }; use base64::Engine as _; use byte_string::ByteStr; use bytes::Bytes; use cfg_if::cfg_if; use log::{error, warn}; use thiserror::Error; use url::{self, Url}; #[cfg(any(feature = "stream-cipher", feature = "aead-cipher"))] use crate::crypto::v1::openssl_bytes_to_key; use crate::{crypto::CipherKind, plugin::PluginConfig, relay::socks5::Address}; const USER_KEY_BASE64_ENGINE: base64::engine::GeneralPurpose = base64::engine::GeneralPurpose::new( &base64::alphabet::STANDARD, base64::engine::GeneralPurposeConfig::new() .with_encode_padding(true) .with_decode_padding_mode(base64::engine::DecodePaddingMode::Indifferent), ); #[cfg(feature = "aead-cipher-2022")] const AEAD2022_PASSWORD_BASE64_ENGINE: base64::engine::GeneralPurpose = base64::engine::GeneralPurpose::new( &base64::alphabet::STANDARD, base64::engine::GeneralPurposeConfig::new() .with_encode_padding(true) .with_decode_padding_mode(base64::engine::DecodePaddingMode::Indifferent), ); const URL_PASSWORD_BASE64_ENGINE: base64::engine::GeneralPurpose = base64::engine::GeneralPurpose::new( &base64::alphabet::URL_SAFE, base64::engine::GeneralPurposeConfig::new() .with_encode_padding(false) .with_decode_padding_mode(base64::engine::DecodePaddingMode::Indifferent), ); /// Shadowsocks server type #[derive(Debug, Copy, Clone, Eq, PartialEq)] pub enum ServerType { /// Running as a local service Local, /// Running as a shadowsocks server Server, } impl ServerType { /// Check if it is `Local` pub fn is_local(self) -> bool { self == Self::Local } /// Check if it is `Server` pub fn is_server(self) -> bool { self == Self::Server } } /// Server mode #[derive(Clone, Copy, Debug)] pub enum Mode { TcpOnly = 0x01, TcpAndUdp = 0x03, UdpOnly = 0x02, } impl Mode { /// Check if UDP is enabled pub fn enable_udp(self) -> bool { matches!(self, Self::UdpOnly | Self::TcpAndUdp) } /// Check if TCP is enabled pub fn enable_tcp(self) -> bool { matches!(self, Self::TcpOnly | Self::TcpAndUdp) } /// Merge with another Mode pub fn merge(&self, mode: Self) -> Self { let me = *self as u8; let fm = mode as u8; match me | fm { 0x01 => Self::TcpOnly, 0x02 => Self::UdpOnly, 0x03 => Self::TcpAndUdp, _ => unreachable!(), } } /// String representation of Mode pub fn as_str(&self) -> &'static str { match *self { Self::TcpOnly => "tcp_only", Self::TcpAndUdp => "tcp_and_udp", Self::UdpOnly => "udp_only", } } } impl fmt::Display for Mode { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.write_str(self.as_str()) } } impl FromStr for Mode { type Err = (); fn from_str(s: &str) -> Result { match s { "tcp_only" => Ok(Self::TcpOnly), "tcp_and_udp" => Ok(Self::TcpAndUdp), "udp_only" => Ok(Self::UdpOnly), _ => Err(()), } } } struct ModeVisitor; impl serde::de::Visitor<'_> for ModeVisitor { type Value = Mode; fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Mode") } fn visit_str(self, v: &str) -> Result where E: serde::de::Error, { match v.parse::() { Ok(m) => Ok(m), Err(_) => Err(serde::de::Error::invalid_value(serde::de::Unexpected::Str(v), &self)), } } fn visit_string(self, v: String) -> Result where E: serde::de::Error, { self.visit_str::(v.as_str()) } fn visit_bytes(self, v: &[u8]) -> Result where E: serde::de::Error, { match str::from_utf8(v) { Ok(v) => self.visit_str(v), Err(_) => Err(serde::de::Error::invalid_value(serde::de::Unexpected::Bytes(v), &self)), } } fn visit_byte_buf(self, v: Vec) -> Result where E: serde::de::Error, { match String::from_utf8(v) { Ok(v) => self.visit_string(v), Err(e) => Err(serde::de::Error::invalid_value( serde::de::Unexpected::Bytes(&e.into_bytes()), &self, )), } } } impl<'de> serde::Deserialize<'de> for Mode { fn deserialize(deserializer: D) -> Result where D: serde::Deserializer<'de>, { deserializer.deserialize_string(ModeVisitor) } } impl serde::Serialize for Mode { fn serialize(&self, serializer: S) -> Result where S: serde::Serializer, { serializer.serialize_str(self.as_str()) } } /// Server's weight /// /// Commonly for using in balancer #[derive(Debug, Clone)] pub struct ServerWeight { tcp_weight: f32, udp_weight: f32, } impl Default for ServerWeight { fn default() -> Self { Self::new() } } impl ServerWeight { /// Creates a default weight for server, which will have 1.0 for both TCP and UDP pub fn new() -> Self { Self { tcp_weight: 1.0, udp_weight: 1.0, } } /// Weight for TCP balancer pub fn tcp_weight(&self) -> f32 { self.tcp_weight } /// Set weight for TCP balancer in `[0, 1]` pub fn set_tcp_weight(&mut self, weight: f32) { assert!((0.0..=1.0).contains(&weight)); self.tcp_weight = weight; } /// Weight for UDP balancer pub fn udp_weight(&self) -> f32 { self.udp_weight } /// Set weight for UDP balancer in `[0, 1]` pub fn set_udp_weight(&mut self, weight: f32) { assert!((0.0..=1.0).contains(&weight)); self.udp_weight = weight; } } /// Server's user #[derive(Clone)] pub struct ServerUser { name: String, key: Bytes, identity_hash: Bytes, } impl Debug for ServerUser { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("ServerUser") .field("name", &self.name) .field("key", &USER_KEY_BASE64_ENGINE.encode(&self.key)) .field("identity_hash", &ByteStr::new(&self.identity_hash)) .finish() } } impl ServerUser { /// Create a user pub fn new(name: N, key: K) -> Self where N: Into, K: Into, { let name = name.into(); let key = key.into(); let hash = blake3::hash(&key); let identity_hash = Bytes::from(hash.as_bytes()[0..16].to_owned()); Self { name, key, identity_hash, } } /// Create a user from encoded key pub fn with_encoded_key(name: N, key: &str) -> Result where N: Into, { let key = USER_KEY_BASE64_ENGINE.decode(key)?; Ok(Self::new(name, key)) } /// Name of the user pub fn name(&self) -> &str { self.name.as_str() } /// Encryption key of user pub fn key(&self) -> &[u8] { self.key.as_ref() } /// Get Base64 encoded key of user pub fn encoded_key(&self) -> String { USER_KEY_BASE64_ENGINE.encode(&self.key) } /// User's identity hash /// /// https://github.com/Shadowsocks-NET/shadowsocks-specs/blob/main/2022-2-shadowsocks-2022-extensible-identity-headers.md pub fn identity_hash(&self) -> &[u8] { self.identity_hash.as_ref() } /// User's identity hash /// /// https://github.com/Shadowsocks-NET/shadowsocks-specs/blob/main/2022-2-shadowsocks-2022-extensible-identity-headers.md pub fn clone_identity_hash(&self) -> Bytes { self.identity_hash.clone() } } /// ServerUser related errors #[derive(Debug, Clone, Error)] pub enum ServerUserError { /// Invalid User key encoding #[error("{0}")] InvalidKeyEncoding(#[from] base64::DecodeError), } /// Server multi-users manager #[derive(Clone, Debug)] pub struct ServerUserManager { users: HashMap>, } impl ServerUserManager { /// Create a new manager pub fn new() -> Self { Self { users: HashMap::new() } } /// Add a new user pub fn add_user(&mut self, user: ServerUser) { self.users.insert(user.clone_identity_hash(), Arc::new(user)); } /// Get user by hash key pub fn get_user_by_hash(&self, user_hash: &[u8]) -> Option<&ServerUser> { self.users.get(user_hash).map(AsRef::as_ref) } /// Get user by hash key cloned pub fn clone_user_by_hash(&self, user_hash: &[u8]) -> Option> { self.users.get(user_hash).cloned() } /// Number of users pub fn user_count(&self) -> usize { self.users.len() } /// Iterate users pub fn users_iter(&self) -> impl Iterator { self.users.values().map(|v| v.as_ref()) } } impl Default for ServerUserManager { fn default() -> Self { Self::new() } } /// The source of the ServerConfig #[derive(Debug, Clone, Copy, Eq, PartialEq)] pub enum ServerSource { Default, //< Default source, created in code Configuration, //< Created from configuration CommandLine, //< Created from command line OnlineConfig, //< Created from online configuration (SIP008) } /// Errors when creating a new ServerConfig #[derive(Debug, Clone, Error)] pub enum ServerConfigError { /// Invalid base64 encoding of password #[error("invalid key encoding for {0}, {1}")] InvalidKeyEncoding(CipherKind, base64::DecodeError), /// Invalid user key encoding #[error("invalid iPSK encoding for {0}, {1}")] InvalidUserKeyEncoding(CipherKind, base64::DecodeError), /// Key length mismatch #[error("invalid key length for {0}, expecting {1} bytes, but found {2} bytes")] InvalidKeyLength(CipherKind, usize, usize), /// User Key (ipsk) length mismatch #[error("invalid user key length for {0}, expecting {1} bytes, but found {2} bytes")] InvalidUserKeyLength(CipherKind, usize, usize), } /// Configuration for a server #[derive(Clone, Debug)] pub struct ServerConfig { /// Server address addr: ServerAddr, /// Encryption password (key) password: String, /// Encryption type (method) method: CipherKind, /// Encryption key enc_key: Box<[u8]>, /// Handshake timeout (connect) timeout: Option, /// Extensible Identity Headers (AEAD-2022) /// /// For client, assemble EIH headers identity_keys: Arc>, /// Extensible Identity Headers (AEAD-2022) /// /// For server, support multi-users with EIH user_manager: Option>, /// Plugin config plugin: Option, /// Plugin address plugin_addr: Option, /// Remark (Profile Name), normally used as an identifier of this erver remarks: Option, /// ID (SIP008) is a random generated UUID id: Option, /// Mode mode: Mode, /// Weight weight: ServerWeight, /// Source source: ServerSource, } #[inline] fn make_derived_key(method: CipherKind, password: &str, enc_key: &mut [u8]) -> Result<(), ServerConfigError> { #[cfg(feature = "aead-cipher-2022")] if method.is_aead_2022() { // AEAD 2022 password is a base64 form of enc_key match AEAD2022_PASSWORD_BASE64_ENGINE.decode(password) { Ok(v) => { if v.len() != enc_key.len() { return Err(ServerConfigError::InvalidKeyLength(method, enc_key.len(), v.len())); } enc_key.copy_from_slice(&v); } Err(err) => { return Err(ServerConfigError::InvalidKeyEncoding(method, err)); } } return Ok(()); } cfg_if! { if #[cfg(any(feature = "stream-cipher", feature = "aead-cipher"))] { let _ = method; openssl_bytes_to_key(password.as_bytes(), enc_key); Ok(()) } else { // No default implementation. let _ = password; let _ = enc_key; unreachable!("{method} don't know how to make a derived key"); } } } /// Check if method supports Extended Identity Header /// /// https://github.com/Shadowsocks-NET/shadowsocks-specs/blob/main/2022-2-shadowsocks-2022-extensible-identity-headers.md #[cfg(feature = "aead-cipher-2022")] #[inline] pub fn method_support_eih(method: CipherKind) -> bool { matches!( method, CipherKind::AEAD2022_BLAKE3_AES_128_GCM | CipherKind::AEAD2022_BLAKE3_AES_256_GCM ) } #[allow(clippy::type_complexity)] fn password_to_keys

(method: CipherKind, password: P) -> Result<(String, Box<[u8]>, Vec), ServerConfigError> where P: Into, { let password = password.into(); match method { CipherKind::NONE => { // NONE method's key length is 0 debug_assert_eq!(method.key_len(), 0); if !password.is_empty() { warn!( "method \"none\" doesn't need a password, which should be set as an empty String, but password.len() = {}", password.len() ); } return Ok((password, Vec::new().into_boxed_slice(), Vec::new())); } #[cfg(feature = "stream-cipher")] CipherKind::SS_TABLE => { // TABLE cipher doesn't need key derivation. // Reference implementation: shadowsocks-libev, shadowsocks (Python) let enc_key = password.clone().into_bytes().into_boxed_slice(); return Ok((password, enc_key, Vec::new())); } #[allow(unreachable_patterns)] _ => {} } #[cfg(feature = "aead-cipher-2022")] if method_support_eih(method) { // Extensible Identity Headers // iPSK1:iPSK2:iPSK3:...:uPSK let mut identity_keys = Vec::new(); let mut split_iter = password.rsplit(':'); let upsk = split_iter.next().expect("uPSK"); let mut enc_key = vec![0u8; method.key_len()].into_boxed_slice(); make_derived_key(method, upsk, &mut enc_key)?; for ipsk in split_iter { match USER_KEY_BASE64_ENGINE.decode(ipsk) { Ok(v) => { // Double check identity key's length match method { CipherKind::AEAD2022_BLAKE3_AES_128_GCM => { // AES-128 if v.len() != 16 { return Err(ServerConfigError::InvalidUserKeyLength(method, 16, v.len())); } } CipherKind::AEAD2022_BLAKE3_AES_256_GCM => { // AES-256 if v.len() != 32 { return Err(ServerConfigError::InvalidUserKeyLength(method, 32, v.len())); } } _ => unreachable!("{} doesn't support EIH", method), } identity_keys.push(Bytes::from(v)); } Err(err) => { return Err(ServerConfigError::InvalidUserKeyEncoding(method, err)); } } } identity_keys.reverse(); return Ok((upsk.to_owned(), enc_key, identity_keys)); } let mut enc_key = vec![0u8; method.key_len()].into_boxed_slice(); make_derived_key(method, &password, &mut enc_key)?; Ok((password, enc_key, Vec::new())) } impl ServerConfig { /// Create a new `ServerConfig` pub fn new(addr: A, password: P, method: CipherKind) -> Result where A: Into, P: Into, { let (password, enc_key, identity_keys) = password_to_keys(method, password)?; Ok(Self { addr: addr.into(), password, method, enc_key, identity_keys: Arc::new(identity_keys), user_manager: None, timeout: None, plugin: None, plugin_addr: None, remarks: None, id: None, mode: Mode::TcpAndUdp, // Server serves TCP & UDP by default weight: ServerWeight::new(), source: ServerSource::Default, }) } /// Set encryption method pub fn set_method

(&mut self, method: CipherKind, password: P) -> Result<(), ServerConfigError> where P: Into, { self.method = method; let (password, enc_key, identity_keys) = password_to_keys(method, password)?; self.password = password; self.enc_key = enc_key; self.identity_keys = Arc::new(identity_keys); Ok(()) } /// Set plugin pub fn set_plugin(&mut self, p: PluginConfig) { self.plugin = Some(p); } /// Set server addr pub fn set_addr(&mut self, a: A) where A: Into, { self.addr = a.into(); } /// Get server address pub fn addr(&self) -> &ServerAddr { &self.addr } /// Get encryption key pub fn key(&self) -> &[u8] { self.enc_key.as_ref() } /// Get password pub fn password(&self) -> &str { self.password.as_str() } /// Get identity keys (Client) pub fn identity_keys(&self) -> &[Bytes] { &self.identity_keys } /// Clone identity keys (Client) pub fn clone_identity_keys(&self) -> Arc> { self.identity_keys.clone() } /// Set user manager, enable Server's multi-user support with EIH pub fn set_user_manager(&mut self, user_manager: ServerUserManager) { self.user_manager = Some(Arc::new(user_manager)); } /// Get user manager (Server) pub fn user_manager(&self) -> Option<&ServerUserManager> { self.user_manager.as_deref() } /// Clone user manager (Server) pub fn clone_user_manager(&self) -> Option> { self.user_manager.clone() } /// Get method pub fn method(&self) -> CipherKind { self.method } /// Get plugin pub fn plugin(&self) -> Option<&PluginConfig> { self.plugin.as_ref() } /// Set plugin address pub fn set_plugin_addr(&mut self, a: ServerAddr) { self.plugin_addr = Some(a); } /// Get plugin address pub fn plugin_addr(&self) -> Option<&ServerAddr> { self.plugin_addr.as_ref() } /// Get server's TCP external address pub fn tcp_external_addr(&self) -> &ServerAddr { if let Some(plugin) = self.plugin() && plugin.plugin_mode.enable_tcp() { return self.plugin_addr.as_ref().unwrap_or(&self.addr); } &self.addr } /// Get server's UDP external address pub fn udp_external_addr(&self) -> &ServerAddr { if let Some(plugin) = self.plugin() && plugin.plugin_mode.enable_udp() { return self.plugin_addr.as_ref().unwrap_or(&self.addr); } &self.addr } /// Set timeout pub fn set_timeout(&mut self, timeout: Duration) { self.timeout = Some(timeout); } /// Timeout pub fn timeout(&self) -> Option { self.timeout } /// Get server's remark pub fn remarks(&self) -> Option<&str> { self.remarks.as_ref().map(AsRef::as_ref) } /// Set server's remark pub fn set_remarks(&mut self, remarks: S) where S: Into, { self.remarks = Some(remarks.into()); } /// Get server's ID (SIP008) pub fn id(&self) -> Option<&str> { self.id.as_ref().map(AsRef::as_ref) } /// Set server's ID (SIP008) pub fn set_id(&mut self, id: S) where S: Into, { self.id = Some(id.into()) } /// Get server's `Mode` pub fn mode(&self) -> Mode { self.mode } /// Set server's `Mode` pub fn set_mode(&mut self, mode: Mode) { self.mode = mode; } /// Get server's balancer weight pub fn weight(&self) -> &ServerWeight { &self.weight } /// Set server's balancer weight pub fn set_weight(&mut self, weight: ServerWeight) { self.weight = weight; } /// Get server's source pub fn source(&self) -> ServerSource { self.source } /// Set server's source pub fn set_source(&mut self, source: ServerSource) { self.source = source; } /// Get URL for QRCode /// ```plain /// ss:// + base64(method:password@host:port) /// ``` pub fn to_qrcode_url(&self) -> String { let param = format!("{}:{}@{}", self.method(), self.password(), self.addr()); format!("ss://{}", URL_PASSWORD_BASE64_ENGINE.encode(param)) } /// Get [SIP002](https://github.com/shadowsocks/shadowsocks-org/issues/27) URL pub fn to_url(&self) -> String { cfg_if! { if #[cfg(feature = "aead-cipher-2022")] { let user_info = if !self.method().is_aead_2022() { let user_info = format!("{}:{}", self.method(), self.password()); URL_PASSWORD_BASE64_ENGINE.encode(user_info) } else { format!("{}:{}", self.method(), percent_encoding::utf8_percent_encode(self.password(), percent_encoding::NON_ALPHANUMERIC)) }; } else { let mut user_info = format!("{}:{}", self.method(), self.password()); user_info = URL_PASSWORD_BASE64_ENGINE.encode(&user_info) } } let mut url = format!("ss://{}@{}", user_info, self.addr()); if let Some(c) = self.plugin() { let mut plugin = c.plugin.clone(); if let Some(ref opt) = c.plugin_opts { plugin += ";"; plugin += opt; } url += "/?plugin="; for c in percent_encoding::utf8_percent_encode(&plugin, percent_encoding::NON_ALPHANUMERIC) { url.push_str(c); } } if let Some(remark) = self.remarks() { url += "#"; for c in percent_encoding::utf8_percent_encode(remark, percent_encoding::NON_ALPHANUMERIC) { url.push_str(c); } } url } /// Parse from [SIP002](https://github.com/shadowsocks/shadowsocks-org/issues/27) URL /// /// Extended formats: /// /// 1. QRCode URL supported by shadowsocks-android, https://github.com/shadowsocks/shadowsocks-android/issues/51 /// 2. Plain userinfo:password format supported by go2-shadowsocks2 pub fn from_url(encoded: &str) -> Result { let parsed = Url::parse(encoded).map_err(UrlParseError::from)?; if parsed.scheme() != "ss" { return Err(UrlParseError::InvalidScheme); } let user_info = parsed.username(); if user_info.is_empty() { // This maybe a QRCode URL, which is ss://BASE64-URL-ENCODE(pass:encrypt@hostname:port) let encoded = match parsed.host_str() { Some(e) => e, None => return Err(UrlParseError::MissingHost), }; let mut decoded_body = match URL_PASSWORD_BASE64_ENGINE.decode(encoded) { Ok(b) => match String::from_utf8(b) { Ok(b) => b, Err(..) => return Err(UrlParseError::InvalidServerAddr), }, Err(err) => { error!("failed to parse legacy ss://ENCODED with Base64, err: {}", err); return Err(UrlParseError::InvalidServerAddr); } }; decoded_body.insert_str(0, "ss://"); // Parse it like ss://method:password@host:port return Self::from_url(&decoded_body); } let (method, pwd) = match parsed.password() { Some(password) => { // Plain method:password without base64 encoded let m = match percent_encoding::percent_decode_str(user_info).decode_utf8() { Ok(m) => m, Err(err) => { error!("failed to parse percent-encoded method in userinfo, err: {}", err); return Err(UrlParseError::InvalidAuthInfo); } }; let p = match percent_encoding::percent_decode_str(password).decode_utf8() { Ok(m) => m, Err(err) => { error!("failed to parse percent-encoded password in userinfo, err: {}", err); return Err(UrlParseError::InvalidAuthInfo); } }; (m, p) } None => { // userinfo is not required to be percent encoded, but some implementation did. // If the base64 library have padding = added to the encoded string, then it will become %3D. let decoded_user_info = match percent_encoding::percent_decode_str(user_info).decode_utf8() { Ok(m) => m, Err(err) => { error!("failed to parse percent-encoded userinfo, err: {}", err); return Err(UrlParseError::InvalidAuthInfo); } }; // reborrow to fit AsRef<[u8]> let decoded_user_info: &str = &decoded_user_info; // Some implementation, like outline, // or those with Python (base64 in Python will still have '=' padding for URL safe encode) let account = match URL_PASSWORD_BASE64_ENGINE.decode(decoded_user_info) { Ok(account) => match String::from_utf8(account) { Ok(ac) => ac, Err(..) => return Err(UrlParseError::InvalidAuthInfo), }, Err(err) => { error!("failed to parse UserInfo with Base64, err: {}", err); return Err(UrlParseError::InvalidUserInfo); } }; let mut sp2 = account.splitn(2, ':'); let (m, p) = match (sp2.next(), sp2.next()) { (Some(m), Some(p)) => (m, p), _ => return Err(UrlParseError::InvalidUserInfo), }; (m.to_owned().into(), p.to_owned().into()) } }; let host = match parsed.host_str() { Some(host) => host, None => return Err(UrlParseError::MissingHost), }; let port = parsed.port().unwrap_or(8388); let addr = format!("{host}:{port}"); let addr = match addr.parse::() { Ok(a) => a, Err(err) => { error!("failed to parse \"{}\" to ServerAddr, err: {:?}", addr, err); return Err(UrlParseError::InvalidServerAddr); } }; let method = match method.parse::() { Ok(m) => m, Err(err) => { error!("failed to parse \"{}\" to CipherKind, err: {:?}", method, err); return Err(UrlParseError::InvalidMethod); } }; let mut svrconfig = Self::new(addr, pwd, method)?; if let Some(q) = parsed.query() { let query = match serde_urlencoded::from_bytes::>(q.as_bytes()) { Ok(q) => q, Err(err) => { error!("failed to parse QueryString, err: {}", err); return Err(UrlParseError::InvalidQueryString); } }; for (key, value) in query { if key != "plugin" { continue; } let mut vsp = value.splitn(2, ';'); match vsp.next() { None => {} Some(p) => { let plugin = PluginConfig { plugin: p.to_owned(), plugin_opts: vsp.next().map(ToOwned::to_owned), plugin_args: Vec::new(), // SIP002 doesn't have arguments for plugins plugin_mode: Mode::TcpOnly, // SIP002 doesn't support SIP003u }; svrconfig.set_plugin(plugin); } } } } if let Some(frag) = parsed.fragment() { match percent_encoding::percent_decode_str(frag).decode_utf8() { Ok(m) => svrconfig.set_remarks(m), Err(..) => svrconfig.set_remarks(frag), } } Ok(svrconfig) } /// Check if it is a basic format server pub fn is_basic(&self) -> bool { self.remarks.is_none() && self.id.is_none() } } /// Shadowsocks URL parsing Error #[derive(Debug, Clone, Error)] pub enum UrlParseError { #[error("{0}")] ParseError(#[from] url::ParseError), #[error("URL must have \"ss://\" scheme")] InvalidScheme, #[error("unknown encryption method")] InvalidMethod, #[error("invalid user info")] InvalidUserInfo, #[error("missing host")] MissingHost, #[error("invalid authentication info")] InvalidAuthInfo, #[error("invalid server address")] InvalidServerAddr, #[error("invalid query string")] InvalidQueryString, #[error("{0}")] ServerConfigError(#[from] ServerConfigError), } impl FromStr for ServerConfig { type Err = UrlParseError; fn from_str(s: &str) -> Result { Self::from_url(s) } } /// Server address #[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] pub enum ServerAddr { /// IP Address SocketAddr(SocketAddr), /// Domain name address, eg. example.com:8080 DomainName(String, u16), } impl ServerAddr { /// Get string representation of domain pub fn host(&self) -> String { match *self { Self::SocketAddr(ref s) => s.ip().to_string(), Self::DomainName(ref dm, _) => dm.clone(), } } /// Get port pub fn port(&self) -> u16 { match *self { Self::SocketAddr(ref s) => s.port(), Self::DomainName(_, p) => p, } } } /// Parse `ServerAddr` error #[derive(Debug)] pub struct ServerAddrError; impl Display for ServerAddrError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.write_str("invalid ServerAddr") } } impl FromStr for ServerAddr { type Err = ServerAddrError; fn from_str(s: &str) -> Result { match s.parse::() { Ok(addr) => Ok(Self::SocketAddr(addr)), Err(..) => { let mut sp = s.split(':'); match (sp.next(), sp.next()) { (Some(dn), Some(port)) => { if dn.is_empty() { return Err(ServerAddrError); } match port.parse::() { Ok(port) => Ok(Self::DomainName(dn.to_owned(), port)), Err(..) => Err(ServerAddrError), } } _ => Err(ServerAddrError), } } } } } impl Display for ServerAddr { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { Self::SocketAddr(ref a) => write!(f, "{a}"), Self::DomainName(ref d, port) => write!(f, "{d}:{port}"), } } } struct ServerAddrVisitor; impl serde::de::Visitor<'_> for ServerAddrVisitor { type Value = ServerAddr; fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("ServerAddr") } fn visit_str(self, v: &str) -> Result where E: serde::de::Error, { match v.parse::() { Ok(m) => Ok(m), Err(_) => Err(serde::de::Error::invalid_value(serde::de::Unexpected::Str(v), &self)), } } fn visit_string(self, v: String) -> Result where E: serde::de::Error, { self.visit_str::(v.as_str()) } fn visit_bytes(self, v: &[u8]) -> Result where E: serde::de::Error, { match str::from_utf8(v) { Ok(v) => self.visit_str(v), Err(_) => Err(serde::de::Error::invalid_value(serde::de::Unexpected::Bytes(v), &self)), } } fn visit_byte_buf(self, v: Vec) -> Result where E: serde::de::Error, { match String::from_utf8(v) { Ok(v) => self.visit_string(v), Err(e) => Err(serde::de::Error::invalid_value( serde::de::Unexpected::Bytes(&e.into_bytes()), &self, )), } } } impl<'de> serde::Deserialize<'de> for ServerAddr { fn deserialize(deserializer: D) -> Result where D: serde::Deserializer<'de>, { deserializer.deserialize_string(ServerAddrVisitor) } } impl serde::Serialize for ServerAddr { fn serialize(&self, serializer: S) -> Result where S: serde::Serializer, { serializer.serialize_str(self.to_string().as_str()) } } impl From for ServerAddr { fn from(addr: SocketAddr) -> Self { Self::SocketAddr(addr) } } impl> From<(I, u16)> for ServerAddr { fn from((dname, port): (I, u16)) -> Self { Self::DomainName(dname.into(), port) } } impl From

for ServerAddr { fn from(addr: Address) -> Self { match addr { Address::SocketAddress(sa) => Self::SocketAddr(sa), Address::DomainNameAddress(dn, port) => Self::DomainName(dn, port), } } } impl From<&Address> for ServerAddr { fn from(addr: &Address) -> Self { match *addr { Address::SocketAddress(sa) => Self::SocketAddr(sa), Address::DomainNameAddress(ref dn, port) => Self::DomainName(dn.clone(), port), } } } impl From for Address { fn from(addr: ServerAddr) -> Self { match addr { ServerAddr::SocketAddr(sa) => Self::SocketAddress(sa), ServerAddr::DomainName(dn, port) => Self::DomainNameAddress(dn, port), } } } impl From<&ServerAddr> for Address { fn from(addr: &ServerAddr) -> Self { match *addr { ServerAddr::SocketAddr(sa) => Self::SocketAddress(sa), ServerAddr::DomainName(ref dn, port) => Self::DomainNameAddress(dn.clone(), port), } } } /// Address for Manager server #[derive(Debug, Clone)] pub enum ManagerAddr { /// IP address SocketAddr(SocketAddr), /// Domain name address DomainName(String, u16), /// Unix socket path #[cfg(unix)] UnixSocketAddr(PathBuf), } /// Error for parsing `ManagerAddr` #[derive(Debug)] pub struct ManagerAddrError; impl Display for ManagerAddrError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.write_str("invalid ManagerAddr") } } impl FromStr for ManagerAddr { type Err = ManagerAddrError; fn from_str(s: &str) -> Result { match s.find(':') { Some(pos) => { // Contains a ':' in address, must be IP:Port or Domain:Port match s.parse::() { Ok(saddr) => Ok(Self::SocketAddr(saddr)), Err(..) => { // Splits into Domain and Port let (sdomain, sport) = s.split_at(pos); let (sdomain, sport) = (sdomain.trim(), sport[1..].trim()); match sport.parse::() { Ok(port) => Ok(Self::DomainName(sdomain.to_owned(), port)), Err(..) => Err(ManagerAddrError), } } } } #[cfg(unix)] None => { // Must be a unix socket path Ok(Self::UnixSocketAddr(PathBuf::from(s))) } #[cfg(not(unix))] None => Err(ManagerAddrError), } } } impl Display for ManagerAddr { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { Self::SocketAddr(ref saddr) => fmt::Display::fmt(saddr, f), Self::DomainName(ref dname, port) => write!(f, "{dname}:{port}"), #[cfg(unix)] Self::UnixSocketAddr(ref path) => fmt::Display::fmt(&path.display(), f), } } } struct ManagerAddrVisitor; impl serde::de::Visitor<'_> for ManagerAddrVisitor { type Value = ManagerAddr; fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("ManagerAddr") } fn visit_str(self, v: &str) -> Result where E: serde::de::Error, { match v.parse::() { Ok(m) => Ok(m), Err(_) => Err(serde::de::Error::invalid_value(serde::de::Unexpected::Str(v), &self)), } } fn visit_string(self, v: String) -> Result where E: serde::de::Error, { self.visit_str::(v.as_str()) } fn visit_bytes(self, v: &[u8]) -> Result where E: serde::de::Error, { match str::from_utf8(v) { Ok(v) => self.visit_str(v), Err(_) => Err(serde::de::Error::invalid_value(serde::de::Unexpected::Bytes(v), &self)), } } fn visit_byte_buf(self, v: Vec) -> Result where E: serde::de::Error, { match String::from_utf8(v) { Ok(v) => self.visit_string(v), Err(e) => Err(serde::de::Error::invalid_value( serde::de::Unexpected::Bytes(&e.into_bytes()), &self, )), } } } impl<'de> serde::Deserialize<'de> for ManagerAddr { fn deserialize(deserializer: D) -> Result where D: serde::Deserializer<'de>, { deserializer.deserialize_string(ManagerAddrVisitor) } } impl serde::Serialize for ManagerAddr { fn serialize(&self, serializer: S) -> Result where S: serde::Serializer, { serializer.serialize_str(self.to_string().as_str()) } } impl From for ManagerAddr { fn from(addr: SocketAddr) -> Self { Self::SocketAddr(addr) } } impl<'a> From<(&'a str, u16)> for ManagerAddr { fn from((dname, port): (&'a str, u16)) -> Self { Self::DomainName(dname.to_owned(), port) } } impl From<(String, u16)> for ManagerAddr { fn from((dname, port): (String, u16)) -> Self { Self::DomainName(dname, port) } } #[cfg(unix)] impl From for ManagerAddr { fn from(p: PathBuf) -> Self { Self::UnixSocketAddr(p) } } /// Policy for handling replay attack requests #[derive(Debug, Clone, Copy, Eq, PartialEq, Default)] pub enum ReplayAttackPolicy { /// Default strategy based on protocol /// /// SIP022 (AEAD-2022): Reject /// SIP004 (AEAD): Ignore /// Stream: Ignore #[default] Default, /// Ignore it completely Ignore, /// Try to detect replay attack and warn about it Detect, /// Try to detect replay attack and reject the request Reject, } impl Display for ReplayAttackPolicy { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { Self::Default => f.write_str("default"), Self::Ignore => f.write_str("ignore"), Self::Detect => f.write_str("detect"), Self::Reject => f.write_str("reject"), } } } /// Error while parsing ReplayAttackPolicy from string #[derive(Debug, Clone, Copy)] pub struct ReplayAttackPolicyError; impl Display for ReplayAttackPolicyError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.write_str("invalid ReplayAttackPolicy") } } impl FromStr for ReplayAttackPolicy { type Err = ReplayAttackPolicyError; fn from_str(s: &str) -> Result { match s { "default" => Ok(Self::Default), "ignore" => Ok(Self::Ignore), "detect" => Ok(Self::Detect), "reject" => Ok(Self::Reject), _ => Err(ReplayAttackPolicyError), } } } #[cfg(test)] mod test { use super::*; #[test] fn test_server_config_from_url() { let server_config = ServerConfig::from_url("ss://foo:bar@127.0.0.1:9999"); assert!(matches!(server_config, Err(UrlParseError::InvalidMethod))); } } ================================================ FILE: crates/shadowsocks/src/context.rs ================================================ //! Shadowsocks service context use std::{io, net::SocketAddr, sync::Arc}; use byte_string::ByteStr; use log::warn; use crate::{ config::{ReplayAttackPolicy, ServerType}, crypto::CipherKind, dns_resolver::DnsResolver, security::replay::ReplayProtector, }; /// Service context #[derive(Debug)] pub struct Context { // Protector against replay attack // The actual replay detection behavior is implemented in ReplayProtector replay_protector: ReplayProtector, // Policy against replay attack replay_policy: ReplayAttackPolicy, // hickory-dns resolver, which supports REAL asynchronous resolving, and also customizable dns_resolver: Arc, // Connect IPv6 address first ipv6_first: bool, } /// `Context` for sharing between services pub type SharedContext = Arc; impl Context { /// Create a new `Context` for `Client` or `Server` pub fn new(config_type: ServerType) -> Self { Self { replay_protector: ReplayProtector::new(config_type), replay_policy: ReplayAttackPolicy::Default, dns_resolver: Arc::new(DnsResolver::system_resolver()), ipv6_first: false, } } /// Create a new `Context` shared pub fn new_shared(config_type: ServerType) -> SharedContext { SharedContext::new(Self::new(config_type)) } /// Check if nonce exist or not /// /// If not, set into the current bloom filter #[cfg(any(feature = "stream-cipher", feature = "aead-cipher", feature = "aead-cipher-2022"))] #[inline(always)] fn check_nonce_and_set(&self, method: CipherKind, nonce: &[u8]) -> bool { match self.replay_policy { ReplayAttackPolicy::Ignore => false, _ => self.replay_protector.check_nonce_and_set(method, nonce), } } /// Generate nonce (IV or SALT) pub fn generate_nonce(&self, method: CipherKind, nonce: &mut [u8], unique: bool) { if nonce.is_empty() { return; } #[cfg(any(feature = "stream-cipher", feature = "aead-cipher", feature = "aead-cipher-2022"))] loop { use crate::crypto::utils::random_iv_or_salt; random_iv_or_salt(nonce); // Salt already exists, generate a new one. if unique && self.check_nonce_and_set(method, nonce) { continue; } break; } #[cfg(not(any(feature = "stream-cipher", feature = "aead-cipher", feature = "aead-cipher-2022")))] if !nonce.is_empty() { let _ = unique; panic!("{method} don't know how to generate nonce"); } } /// Check nonce replay pub fn check_nonce_replay(&self, method: CipherKind, nonce: &[u8]) -> io::Result<()> { if nonce.is_empty() { return Ok(()); } #[allow(unused_mut)] let mut replay_policy = self.replay_policy; #[cfg(feature = "aead-cipher-2022")] if method.is_aead_2022() { // AEAD-2022 can't be ignored. replay_policy = ReplayAttackPolicy::Reject; } match replay_policy { ReplayAttackPolicy::Default | ReplayAttackPolicy::Ignore => Ok(()), ReplayAttackPolicy::Detect => { if self.replay_protector.check_nonce_and_set(method, nonce) { warn!("detected repeated nonce (iv/salt) {:?}", ByteStr::new(nonce)); } Ok(()) } ReplayAttackPolicy::Reject => { if self.replay_protector.check_nonce_and_set(method, nonce) { let err = io::Error::other("detected repeated nonce (iv/salt)"); Err(err) } else { Ok(()) } } } } /// Set a DNS resolver /// /// The resolver should be wrapped in an `Arc`, because it could be shared with the other servers pub fn set_dns_resolver(&mut self, resolver: Arc) { self.dns_resolver = resolver; } /// Get the DNS resolver pub fn dns_resolver(&self) -> &Arc { &self.dns_resolver } /// Resolves DNS address to `SocketAddr`s pub async fn dns_resolve<'a>( &self, addr: &'a str, port: u16, ) -> io::Result + 'a + use<'a>> { self.dns_resolver.resolve(addr, port).await } /// Try to connect IPv6 addresses first if hostname could be resolved to both IPv4 and IPv6 pub fn set_ipv6_first(&mut self, ipv6_first: bool) { self.ipv6_first = ipv6_first; } /// Try to connect IPv6 addresses first if hostname could be resolved to both IPv4 and IPv6 pub fn ipv6_first(&self) -> bool { self.ipv6_first } /// Set policy against replay attack pub fn set_replay_attack_policy(&mut self, replay_policy: ReplayAttackPolicy) { self.replay_policy = replay_policy; } /// Get policy against replay attack pub fn replay_attack_policy(&self) -> ReplayAttackPolicy { self.replay_policy } } ================================================ FILE: crates/shadowsocks/src/dns_resolver/hickory_dns_resolver.rs ================================================ //! Asynchronous DNS resolver use std::{ future::Future, io, net::SocketAddr, ops::Deref, pin::Pin, task::{Context, Poll}, time::Duration, }; use futures::ready; use hickory_resolver::{ ResolveError, Resolver, config::{LookupIpStrategy, ResolverConfig, ResolverOpts}, name_server::GenericConnector, proto::{ runtime::{RuntimeProvider, TokioHandle, TokioTime, iocompat::AsyncIoTokioAsStd}, udp::DnsUdpSocket, }, }; use log::{error, trace}; use tokio::{io::ReadBuf, net::UdpSocket}; use crate::net::{ConnectOpts, tcp::TcpStream as ShadowTcpStream, udp::UdpSocket as ShadowUdpSocket}; /// Shadowsocks hickory-dns Runtime Provider #[derive(Clone)] pub struct ShadowDnsRuntimeProvider { handle: TokioHandle, connect_opts: ConnectOpts, } impl ShadowDnsRuntimeProvider { fn new(connect_opts: ConnectOpts) -> Self { Self { handle: TokioHandle::default(), connect_opts, } } } impl DnsUdpSocket for ShadowUdpSocket { type Time = TokioTime; #[inline] fn poll_recv_from(&self, cx: &mut Context<'_>, buf: &mut [u8]) -> Poll> { let udp: &UdpSocket = self.deref(); let mut read_buf = ReadBuf::new(buf); let recv_addr = ready!(udp.poll_recv_from(cx, &mut read_buf))?; Ok((read_buf.filled().len(), recv_addr)).into() } #[inline] fn poll_send_to(&self, cx: &mut Context<'_>, buf: &[u8], target: SocketAddr) -> Poll> { let udp: &UdpSocket = self.deref(); udp.poll_send_to(cx, buf, target) } } impl RuntimeProvider for ShadowDnsRuntimeProvider { type Handle = TokioHandle; type Tcp = AsyncIoTokioAsStd; type Timer = TokioTime; type Udp = ShadowUdpSocket; fn create_handle(&self) -> Self::Handle { self.handle.clone() } fn connect_tcp( &self, server_addr: SocketAddr, bind_addr: Option, wait_for: Option, ) -> Pin>>> { let mut connect_opts = self.connect_opts.clone(); if let Some(bind_addr) = bind_addr { connect_opts.bind_local_addr = Some(bind_addr); } let wait_for = wait_for.unwrap_or_else(|| Duration::from_secs(5)); Box::pin(async move { trace!( "hickory-dns RuntimeProvider tcp connecting to {} with {:?}", server_addr, connect_opts ); let tcp = match tokio::time::timeout( wait_for, ShadowTcpStream::connect_with_opts(&server_addr, &connect_opts), ) .await { Ok(Ok(s)) => s, Ok(Err(err)) => return Err(err), Err(_) => return Err(io::ErrorKind::TimedOut.into()), }; trace!( "hickory-dns RuntimeProvider tcp connected to {}, {:?}", server_addr, connect_opts ); Ok(AsyncIoTokioAsStd(tcp)) }) } fn bind_udp( &self, local_addr: SocketAddr, _server_addr: SocketAddr, ) -> Pin>>> { let connect_opts = self.connect_opts.clone(); Box::pin(async move { trace!( "hickory-dns RuntimeProvider udp binding to {} with {:?}", local_addr, connect_opts ); let udp = ShadowUdpSocket::bind_with_opts(&local_addr, &connect_opts).await?; trace!( "hickory-dns RuntimeProvider udp bound to {}, {:?}", local_addr, connect_opts ); Ok(udp) }) } } /// Shadowsocks DNS ConnectionProvider pub type ShadowDnsConnectionProvider = GenericConnector; /// Shadowsocks DNS resolver /// /// A customized hickory-dns-resolver pub type DnsResolver = Resolver; /// Create a `hickory-dns` asynchronous DNS resolver pub async fn create_resolver( dns: Option, opts: Option, connect_opts: ConnectOpts, ) -> Result { // Customized dns resolution match dns { Some(conf) => { trace!("initializing DNS resolver with config {:?}", conf,); let mut builder = DnsResolver::builder_with_config( conf, ShadowDnsConnectionProvider::new(ShadowDnsRuntimeProvider::new(connect_opts)), ); if let Some(opts) = opts { *builder.options_mut() = opts; } let resolver_opts = builder.options_mut(); // Use Ipv4AndIpv6 strategy. Because Ipv4ThenIpv6 or Ipv6ThenIpv4 will return if the first query returned. // Since we want to use Happy Eyeballs to connect to both IPv4 and IPv6 addresses, we need both A and AAAA records. resolver_opts.ip_strategy = LookupIpStrategy::Ipv4AndIpv6; // Enable EDNS0 for large records resolver_opts.edns0 = true; trace!("initializing DNS resolver with opts {:?}", resolver_opts); Ok(builder.build()) } // To make this independent, if targeting macOS, BSD, Linux, or Windows, we can use the system's configuration // Android doesn't have /etc/resolv.conf. None => { match DnsResolver::builder(ShadowDnsConnectionProvider::new(ShadowDnsRuntimeProvider::new( connect_opts, ))) { Ok(mut builder) => { let opts = builder.options_mut(); // NOTE: timeout will be set by config (for example, /etc/resolv.conf on UNIX-like system) // // Only ip_strategy should be changed. Why Ipv4AndIpv6? See comments above. opts.ip_strategy = LookupIpStrategy::Ipv4AndIpv6; // Enable EDNS0 for large records opts.edns0 = true; trace!("initializing DNS resolver with system-config opts {:?}", opts); Ok(builder.build()) } Err(err) => { error!("initialize DNS resolver with system-config failed, error: {}", err); Err(ResolveError::from( "current platform doesn't support hickory-dns resolver with system configured".to_owned(), )) } } } } } ================================================ FILE: crates/shadowsocks/src/dns_resolver/mod.rs ================================================ //! Asynchronous DNS resolver #![macro_use] pub use self::resolver::{DnsResolve, DnsResolver}; #[cfg(feature = "hickory-dns")] mod hickory_dns_resolver; mod resolver; /// Helper macro for resolving host and then process each addresses #[macro_export] macro_rules! lookup_then { ($context:expr_2021, $addr:expr_2021, $port:expr_2021, |$resolved_addr:ident| $body:block) => {{ use std::net::SocketAddr; let ipv6_first = $context.ipv6_first(); let mut v4_addrs = Vec::new(); let mut v6_addrs = Vec::new(); for addr in $context.dns_resolve($addr, $port).await? { match addr { SocketAddr::V4(..) => v4_addrs.push(addr), SocketAddr::V6(..) => v6_addrs.push(addr), } } let has_v4 = !v4_addrs.is_empty(); let has_v6 = !v6_addrs.is_empty(); assert!(has_v4 || has_v6, "resolved empty address"); if !has_v4 && has_v6 { lookup_then!(RESOLVE @ v6_addrs, $resolved_addr, $body) } else if has_v4 && !has_v6 { lookup_then!(RESOLVE @ v4_addrs, $resolved_addr, $body) } else { if ipv6_first { match lookup_then!(RESOLVE @ v6_addrs, $resolved_addr, $body) { Ok(r) => Ok(r), Err(_v6_err) => lookup_then!(RESOLVE @ v4_addrs, $resolved_addr, $body), } } else { match lookup_then!(RESOLVE @ v4_addrs, $resolved_addr, $body) { Ok(r) => Ok(r), Err(_v4_err) => lookup_then!(RESOLVE @ v6_addrs, $resolved_addr, $body), } } } }}; (RESOLVE @ $addrs:expr_2021, $resolved_addr:ident, $body:block) => {{ let mut result = None; for $resolved_addr in $addrs { match $body { Ok(r) => { result = Some(Ok(($resolved_addr, r))); break; } Err(err) => { result = Some(Err(err)); } } } result.expect("resolved empty address") }}; } #[macro_export] macro_rules! lookup_then_connect { ($context:expr_2021, $addr:expr_2021, $port:expr_2021, |$resolved_addr:ident| $body:block) => {{ use futures::future::{self, Either}; use log::trace; use std::{net::SocketAddr, time::Duration}; use tokio::time; let ipv6_first = $context.ipv6_first(); let mut v4_addrs = Vec::new(); let mut v6_addrs = Vec::new(); for addr in $context.dns_resolve($addr, $port).await? { match addr { SocketAddr::V4(..) => v4_addrs.push(addr), SocketAddr::V6(..) => v6_addrs.push(addr), } } let has_v4 = !v4_addrs.is_empty(); let has_v6 = !v6_addrs.is_empty(); assert!(has_v4 || has_v6, "resolved empty address"); // Happy Eyeballs, RFC6555, RFC8305 // // RFC6555 gives an example that Chrome and Firefox uses 300ms const FIXED_DELAY: Duration = Duration::from_millis(300); // Connects every addresses synchronously. // TODO: Try another address after FIXED_DELAY if one of the IPs is unreachable. // // This would require `future::select_ok`, which will require futures to be `Unpin` // (boxed future, excessive memory allocation). let connect_v4 = async { // use futures::FutureExt; // // let mut vfut = Vec::new(); // // let mut delay = Duration::from_millis(0); // // for $resolved_addr in v4_addrs { // vfut.push( // async move { // if delay != Duration::from_millis(0) { // time::sleep(delay).await; // } // // trace!("trying connect {}:{} {}", $addr, $port, $resolved_addr); // // match $body { // Ok(r) => Ok(($resolved_addr, r)), // Err(err) => Err(err), // } // } // .boxed(), // ); // // delay += FIXED_DELAY; // } // // match future::select_ok(vfut).await { // Ok((r, _)) => Ok(r), // Err(err) => Err(err), // } let mut result = None; for $resolved_addr in v4_addrs { trace!("trying connect {}:{} {}", $addr, $port, $resolved_addr); match $body { Ok(r) => { trace!("connected {}:{} {}", $addr, $port, $resolved_addr); result = Some(Ok(($resolved_addr, r))); break; } Err(err) => { result = Some(Err(err)); } } } result.expect("impossible") }; let connect_v6 = async { let mut result = None; for $resolved_addr in v6_addrs { trace!("trying connect {}:{} {}", $addr, $port, $resolved_addr); match $body { Ok(r) => { trace!("connected {}:{} {}", $addr, $port, $resolved_addr); result = Some(Ok(($resolved_addr, r))); break; } Err(err) => { result = Some(Err(err)); } } } result.expect("impossible") }; if has_v4 && !has_v6 { connect_v4.await } else if !has_v4 && has_v6 { connect_v6.await } else { if ipv6_first { let v4_fut = async move { time::sleep(FIXED_DELAY).await; connect_v4.await }; let v6_fut = connect_v6; tokio::pin!(v4_fut); tokio::pin!(v6_fut); match future::select(v4_fut, v6_fut).await { Either::Left((v4_res, v6_fut)) => match v4_res { Ok(res) => Ok(res), Err(_v4_err) => v6_fut.await, }, Either::Right((v6_res, v4_fut)) => match v6_res { Ok(res) => Ok(res), Err(_v6_err) => v4_fut.await, }, } } else { let v6_fut = async move { time::sleep(FIXED_DELAY).await; connect_v6.await }; let v4_fut = connect_v4; tokio::pin!(v4_fut); tokio::pin!(v6_fut); match future::select(v4_fut, v6_fut).await { Either::Left((v4_res, v6_fut)) => match v4_res { Ok(res) => Ok(res), Err(_v4_err) => v6_fut.await, }, Either::Right((v6_res, v4_fut)) => match v6_res { Ok(res) => Ok(res), Err(_v6_err) => v4_fut.await, }, } } } }}; } ================================================ FILE: crates/shadowsocks/src/dns_resolver/resolver.rs ================================================ //! Resolver Alternatives #[cfg(feature = "hickory-dns")] use std::sync::Arc; use std::{ fmt::{self, Debug}, io::{self, Error}, net::SocketAddr, time::Instant, }; #[cfg(feature = "hickory-dns")] use arc_swap::ArcSwap; use cfg_if::cfg_if; #[cfg(feature = "hickory-dns")] use hickory_resolver::config::ResolverConfig; #[cfg(feature = "hickory-dns")] use hickory_resolver::config::ResolverOpts; #[cfg(all(feature = "hickory-dns", unix, not(target_os = "android")))] use log::error; use log::{Level, log_enabled, trace}; use tokio::net::lookup_host; #[cfg(all(feature = "hickory-dns", unix, not(target_os = "android")))] use tokio::task::JoinHandle; #[cfg(feature = "hickory-dns")] use crate::net::ConnectOpts; #[cfg(feature = "hickory-dns")] use super::hickory_dns_resolver::DnsResolver as HickoryDnsResolver; /// Abstract DNS resolver #[trait_variant::make(Send)] #[dynosaur::dynosaur(DynDnsResolve = dyn(box) DnsResolve, bridge(dyn))] pub trait DnsResolve { /// Resolves `addr:port` to a list of `SocketAddr` async fn resolve(&self, addr: &str, port: u16) -> io::Result>; } // Equivalent to (dyn DnsResolve + Send + Sync) unsafe impl Send for DynDnsResolve<'_> {} unsafe impl Sync for DynDnsResolve<'_> {} #[cfg(feature = "hickory-dns")] #[derive(Debug)] pub struct HickoryDnsSystemResolver { resolver: ArcSwap, #[cfg_attr(any(windows, target_os = "android"), allow(dead_code))] connect_opts: ConnectOpts, #[cfg_attr(any(windows, target_os = "android"), allow(dead_code))] opts: Option, } /// Collections of DNS resolver #[allow(clippy::large_enum_variant)] pub enum DnsResolver { /// System Resolver, which is tokio's builtin resolver System, /// Trust-DNS's system resolver #[cfg(feature = "hickory-dns")] HickoryDnsSystem { inner: Arc, #[cfg(all(feature = "hickory-dns", unix, not(target_os = "android")))] abortable: JoinHandle<()>, }, /// Trust-DNS resolver #[cfg(feature = "hickory-dns")] HickoryDns(HickoryDnsResolver), /// Customized Resolver Custom(Box>), } impl Default for DnsResolver { fn default() -> Self { Self::system_resolver() } } impl Debug for DnsResolver { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { Self::System => f.write_str("System"), #[cfg(feature = "hickory-dns")] Self::HickoryDnsSystem { .. } => f.write_str("HickoryDnsSystem(..)"), #[cfg(feature = "hickory-dns")] Self::HickoryDns(..) => f.write_str("HickoryDns(..)"), Self::Custom(..) => f.write_str("Custom(..)"), } } } #[cfg(feature = "hickory-dns")] impl Drop for DnsResolver { fn drop(&mut self) { #[cfg(all(feature = "hickory-dns", unix, not(target_os = "android")))] if let Self::HickoryDnsSystem { ref abortable, .. } = *self { abortable.abort(); } } } cfg_if! { if #[cfg(feature = "hickory-dns")] { /// Resolved result enum EitherResolved { Tokio(A), HickoryDnsSystem(B), HickoryDns(C), Custom(D), } impl Iterator for EitherResolved where A: Iterator, B: Iterator, C: Iterator, D: Iterator, { type Item = SocketAddr; fn next(&mut self) -> Option { match *self { Self::Tokio(ref mut a) => a.next(), Self::HickoryDnsSystem(ref mut b) => b.next(), Self::HickoryDns(ref mut c) => c.next(), Self::Custom(ref mut d) => d.next(), } } } } else { /// Resolved result enum EitherResolved { Tokio(A), Custom(D), } impl Iterator for EitherResolved where A: Iterator, D: Iterator, { type Item = SocketAddr; fn next(&mut self) -> Option { match *self { EitherResolved::Tokio(ref mut a) => a.next(), EitherResolved::Custom(ref mut d) => d.next(), } } } } } #[cfg(all(feature = "hickory-dns", unix, not(target_os = "android")))] async fn hickory_dns_notify_update_dns(resolver: Arc) -> notify::Result<()> { use std::{path::Path, time::Duration}; use log::debug; use notify::{Event, EventKind, RecommendedWatcher, RecursiveMode, Result as NotifyResult, Watcher}; use tokio::{sync::watch, time}; use super::hickory_dns_resolver::create_resolver; const DNS_RESOLV_FILE_PATH: &str = "/etc/resolv.conf"; if !Path::new(DNS_RESOLV_FILE_PATH).exists() { trace!("resolv file {DNS_RESOLV_FILE_PATH} doesn't exist"); return Ok(()); } let (tx, mut rx) = watch::channel::(Event::default()); let mut watcher: RecommendedWatcher = notify::recommended_watcher(move |ev_result: NotifyResult| match ev_result { Ok(ev) => { trace!("received {DNS_RESOLV_FILE_PATH} event {ev:?}"); if let EventKind::Modify(..) = ev.kind { tx.send(ev).expect("watcher.send"); } } Err(err) => { error!("watching {DNS_RESOLV_FILE_PATH} error: {err}"); } })?; // NOTE: It is an undefined behavior if this file get renamed or removed. watcher.watch(Path::new(DNS_RESOLV_FILE_PATH), RecursiveMode::NonRecursive)?; // Delayed task let mut update_task: Option> = None; while rx.changed().await.is_ok() { trace!("received notify {DNS_RESOLV_FILE_PATH} changed"); // Kill the pending task if let Some(t) = update_task.take() { t.abort(); } let task = { let resolver = resolver.clone(); tokio::spawn(async move { // /etc/resolv.conf may be modified multiple time in 1 second // Update once for all those Modify events time::sleep(Duration::from_secs(1)).await; match create_resolver(None, resolver.opts.clone(), resolver.connect_opts.clone()).await { Ok(r) => { debug!("auto-reload {DNS_RESOLV_FILE_PATH}"); resolver.resolver.store(Arc::new(r)); } Err(err) => { error!("failed to reload {DNS_RESOLV_FILE_PATH}, error: {err}"); } } }) }; update_task = Some(task); } error!("auto-reload {DNS_RESOLV_FILE_PATH} task exited unexpectedly"); Ok(()) } impl DnsResolver { /// Use system DNS resolver. Tokio will call `getaddrinfo` in blocking pool. pub fn system_resolver() -> Self { Self::System } /// Use hickory-dns DNS system resolver (with DNS cache) /// /// On *nix system, it will try to read configurations from `/etc/resolv.conf`. #[cfg(feature = "hickory-dns")] pub async fn hickory_dns_system_resolver( opts: Option, connect_opts: ConnectOpts, ) -> io::Result { use super::hickory_dns_resolver::create_resolver; let resolver = create_resolver(None, opts.clone(), connect_opts.clone()).await?; let inner = Arc::new(HickoryDnsSystemResolver { resolver: ArcSwap::from(Arc::new(resolver)), connect_opts, opts, }); cfg_if! { if #[cfg(all(feature = "hickory-dns", unix, not(target_os = "android")))] { let abortable = { let inner = inner.clone(); tokio::spawn(async { if let Err(err) = hickory_dns_notify_update_dns(inner).await { error!("failed to watch DNS system configuration changes, error: {}", err); } }) }; Ok(Self::HickoryDnsSystem { inner, abortable }) } else { Ok(DnsResolver::HickoryDnsSystem { inner }) } } } /// Use hickory-dns DNS resolver (with DNS cache) #[cfg(feature = "hickory-dns")] pub async fn hickory_resolver( dns: ResolverConfig, opts: Option, connect_opts: ConnectOpts, ) -> io::Result { use super::hickory_dns_resolver::create_resolver; Ok(Self::HickoryDns(create_resolver(Some(dns), opts, connect_opts).await?)) } /// Custom DNS resolver pub fn custom_resolver(custom: R) -> Self where R: DnsResolve + Send + Sync + 'static, { Self::Custom(DynDnsResolve::new_box(custom)) } /// Resolve address into `SocketAddr`s pub async fn resolve<'a>( &self, addr: &'a str, port: u16, ) -> io::Result + 'a + use<'a>> { struct ResolverLogger<'x, 'y> { resolver: &'x DnsResolver, addr: &'y str, port: u16, start_time: Option, } impl<'x, 'y> ResolverLogger<'x, 'y> { fn new(resolver: &'x DnsResolver, addr: &'y str, port: u16) -> Self { let start_time = if log_enabled!(Level::Trace) { Some(Instant::now()) } else { None }; ResolverLogger { resolver, addr, port, start_time, } } } impl Drop for ResolverLogger<'_, '_> { fn drop(&mut self) { match self.start_time { Some(start_time) => { let end_time = Instant::now(); let elapsed = end_time - start_time; match *self.resolver { DnsResolver::System => { trace!( "DNS resolved {}:{} with tokio {}s", self.addr, self.port, elapsed.as_secs_f32() ); } #[cfg(feature = "hickory-dns")] DnsResolver::HickoryDnsSystem { .. } | DnsResolver::HickoryDns(..) => { trace!( "DNS resolved {}:{} with hickory-dns {}s", self.addr, self.port, elapsed.as_secs_f32() ); } DnsResolver::Custom(..) => { trace!( "DNS resolved {}:{} with customized {}s", self.addr, self.port, elapsed.as_secs_f32() ); } } } None => match *self.resolver { DnsResolver::System => { trace!("DNS resolved {}:{} with tokio", self.addr, self.port); } #[cfg(feature = "hickory-dns")] DnsResolver::HickoryDnsSystem { .. } | DnsResolver::HickoryDns(..) => { trace!("DNS resolved {}:{} with hickory-dns", self.addr, self.port); } DnsResolver::Custom(..) => { trace!("DNS resolved {}:{} with customized", self.addr, self.port); } }, } } } let _log_guard = ResolverLogger::new(self, addr, port); match *self { Self::System => match lookup_host((addr, port)).await { Ok(v) => Ok(EitherResolved::Tokio(v)), Err(err) => { let err = Error::other(format!("dns resolve {addr}:{port} error: {err}")); Err(err) } }, #[cfg(feature = "hickory-dns")] Self::HickoryDnsSystem { ref inner, .. } => match inner.resolver.load().lookup_ip(addr).await { Ok(lookup_result) => Ok(EitherResolved::HickoryDnsSystem( lookup_result.into_iter().map(move |ip| SocketAddr::new(ip, port)), )), Err(err) => { let err = Error::other(format!("dns resolve {addr}:{port} error: {err}")); Err(err) } }, #[cfg(feature = "hickory-dns")] Self::HickoryDns(ref resolver) => match resolver.lookup_ip(addr).await { Ok(lookup_result) => Ok(EitherResolved::HickoryDns( lookup_result.into_iter().map(move |ip| SocketAddr::new(ip, port)), )), Err(err) => { let err = Error::other(format!("dns resolve {addr}:{port} error: {err}")); Err(err) } }, Self::Custom(ref resolver) => match resolver.resolve(addr, port).await { Ok(v) => Ok(EitherResolved::Custom(v.into_iter())), Err(err) => { let err = Error::other(format!("dns resolve {addr}:{port} error: {err}")); Err(err) } }, } } /// Check if currently using system resolver pub fn is_system_resolver(&self) -> bool { matches!(*self, Self::System) } } ================================================ FILE: crates/shadowsocks/src/lib.rs ================================================ //! Shadowsocks Core Library #![crate_type = "lib"] pub use self::{ config::{ManagerAddr, ServerAddr, ServerConfig}, manager::{ManagerClient, ManagerListener}, relay::{ tcprelay::{proxy_listener::ProxyListener, proxy_stream::ProxyClientStream}, udprelay::proxy_socket::ProxySocket, }, }; pub use shadowsocks_crypto as crypto; pub mod config; pub mod context; pub mod dns_resolver; pub mod manager; pub mod net; pub mod plugin; pub mod relay; mod security; ================================================ FILE: crates/shadowsocks/src/manager/client.rs ================================================ //! Manager client use log::warn; use crate::{config::ManagerAddr, context::Context, net::ConnectOpts, relay::udprelay::MAXIMUM_UDP_PAYLOAD_SIZE}; use super::{ datagram::ManagerDatagram, error::Error, protocol::{ AddRequest, AddResponse, ListRequest, ListResponse, ManagerProtocol, PingRequest, PingResponse, RemoveRequest, RemoveResponse, StatRequest, }, }; /// Client for communicating with Manager pub struct ManagerClient { socket: ManagerDatagram, } macro_rules! impl_command { ($command:ident, $req:ty, $rsp:ty) => { /// Send command pub async fn $command(&mut self, req: &$req) -> Result<$rsp, Error> { self.request(req).await } }; } impl ManagerClient { impl_command!(add, AddRequest, AddResponse); impl_command!(list, ListRequest, ListResponse); impl_command!(ping, PingRequest, PingResponse); impl_command!(remove, RemoveRequest, RemoveResponse); /// Create a `ManagerDatagram` for sending data to manager pub async fn connect( context: &Context, bind_addr: &ManagerAddr, connect_opts: &ConnectOpts, ) -> Result { ManagerDatagram::connect(context, bind_addr, connect_opts) .await .map(|socket| Self { socket }) .map_err(Into::into) } /// Send `stat` report pub async fn stat(&mut self, req: &StatRequest) -> Result<(), Error> { let buf = req.to_bytes()?; let n = self.socket.send(&buf).await?; if n != buf.len() { warn!("manager send {} bytes != buffer {} bytes", n, buf.len()); } Ok(()) } async fn request(&mut self, req: &S) -> Result where S: ManagerProtocol, R: ManagerProtocol, { let buf = req.to_bytes()?; let n = self.socket.send(&buf).await?; if n != buf.len() { warn!("manager send {} bytes != buffer {} bytes", n, buf.len()); } let mut buf = [0u8; MAXIMUM_UDP_PAYLOAD_SIZE]; let n = self.socket.recv(&mut buf).await?; R::from_bytes(&buf[..n]).map_err(Into::into) } } ================================================ FILE: crates/shadowsocks/src/manager/datagram.rs ================================================ //! Shadowsocks manager connecting interface #[cfg(unix)] use std::io::ErrorKind; use std::{fmt, io, net::SocketAddr}; use tokio::net::UdpSocket; #[cfg(unix)] use tokio::net::{UnixDatagram, unix::SocketAddr as UnixSocketAddr}; use crate::{ config::ManagerAddr, context::Context, net::{ConnectOpts, UdpSocket as ShadowUdpSocket}, }; /// Address accepted from Manager #[derive(Debug)] pub enum ManagerSocketAddr { SocketAddr(SocketAddr), #[cfg(unix)] UnixSocketAddr(UnixSocketAddr), } impl ManagerSocketAddr { /// Check if it is unnamed (not binded to any valid address), only valid for `UnixSocketAddr` pub fn is_unnamed(&self) -> bool { match *self { Self::SocketAddr(..) => false, #[cfg(unix)] Self::UnixSocketAddr(ref s) => s.is_unnamed(), } } } impl fmt::Display for ManagerSocketAddr { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match *self { Self::SocketAddr(ref saddr) => fmt::Display::fmt(saddr, f), #[cfg(unix)] Self::UnixSocketAddr(ref saddr) => fmt::Debug::fmt(saddr, f), } } } /// Datagram socket for manager /// /// For *nix system, this is a wrapper for both UDP socket and Unix socket #[derive(Debug)] pub enum ManagerDatagram { UdpDatagram(UdpSocket), #[cfg(unix)] UnixDatagram(UnixDatagram), } impl ManagerDatagram { /// Create a `ManagerDatagram` binding to requested `bind_addr` pub async fn bind(context: &Context, bind_addr: &ManagerAddr) -> io::Result { match *bind_addr { ManagerAddr::SocketAddr(ref saddr) => Ok(Self::UdpDatagram(ShadowUdpSocket::listen(saddr).await?.into())), ManagerAddr::DomainName(ref dname, port) => { let (_, socket) = lookup_then!(context, dname, port, |saddr| { ShadowUdpSocket::listen(&saddr).await })?; Ok(Self::UdpDatagram(socket.into())) } #[cfg(unix)] ManagerAddr::UnixSocketAddr(ref path) => { use std::fs; // Remove it first incase it is already exists let _ = fs::remove_file(path); Ok(Self::UnixDatagram(UnixDatagram::bind(path)?)) } } } /// Create a `ManagerDatagram` for sending data to manager pub async fn connect(context: &Context, bind_addr: &ManagerAddr, connect_opts: &ConnectOpts) -> io::Result { match *bind_addr { ManagerAddr::SocketAddr(sa) => Self::connect_socket_addr(sa, connect_opts).await, ManagerAddr::DomainName(ref dname, port) => { // Try connect to all socket addresses lookup_then!(context, dname, port, |addr| { Self::connect_socket_addr(addr, connect_opts).await }) .map(|(_, d)| d) } #[cfg(unix)] // For unix socket, it doesn't need to bind to any valid address // Because manager won't response to you ManagerAddr::UnixSocketAddr(ref path) => { let dgram = UnixDatagram::unbound()?; dgram.connect(path)?; Ok(Self::UnixDatagram(dgram)) } } } async fn connect_socket_addr(sa: SocketAddr, connect_opts: &ConnectOpts) -> io::Result { let socket = ShadowUdpSocket::connect_with_opts(&sa, connect_opts).await?; Ok(Self::UdpDatagram(socket.into())) } /// Receives data from the socket. pub async fn recv(&mut self, buf: &mut [u8]) -> io::Result { match *self { Self::UdpDatagram(ref mut udp) => udp.recv(buf).await, #[cfg(unix)] Self::UnixDatagram(ref mut unix) => unix.recv(buf).await, } } /// Receives data from the socket. pub async fn recv_from(&mut self, buf: &mut [u8]) -> io::Result<(usize, ManagerSocketAddr)> { match *self { Self::UdpDatagram(ref mut udp) => { let (s, addr) = udp.recv_from(buf).await?; Ok((s, ManagerSocketAddr::SocketAddr(addr))) } #[cfg(unix)] Self::UnixDatagram(ref mut unix) => { let (s, addr) = unix.recv_from(buf).await?; Ok((s, ManagerSocketAddr::UnixSocketAddr(addr))) } } } /// Sends data to the socket pub async fn send(&mut self, buf: &[u8]) -> io::Result { match *self { Self::UdpDatagram(ref mut udp) => udp.send(buf).await, #[cfg(unix)] Self::UnixDatagram(ref mut unix) => unix.send(buf).await, } } /// Sends data to the socket to the specified address. pub async fn send_to(&mut self, buf: &[u8], target: &ManagerSocketAddr) -> io::Result { match *self { Self::UdpDatagram(ref mut udp) => match *target { ManagerSocketAddr::SocketAddr(ref saddr) => udp.send_to(buf, saddr).await, #[cfg(unix)] ManagerSocketAddr::UnixSocketAddr(..) => { let err = io::Error::new(ErrorKind::InvalidInput, "udp datagram requires IP address target"); Err(err) } }, #[cfg(unix)] Self::UnixDatagram(ref mut unix) => match *target { ManagerSocketAddr::UnixSocketAddr(ref saddr) => match saddr.as_pathname() { Some(paddr) => unix.send_to(buf, paddr).await, None => { let err = io::Error::new(ErrorKind::InvalidInput, "target address must not be unnamed"); Err(err) } }, ManagerSocketAddr::SocketAddr(..) => { let err = io::Error::new(ErrorKind::InvalidInput, "unix datagram requires path address target"); Err(err) } }, } } /// Sends data on the socket to the specified manager address pub async fn send_to_manager(&mut self, buf: &[u8], context: &Context, target: &ManagerAddr) -> io::Result { match *self { Self::UdpDatagram(ref mut udp) => match *target { ManagerAddr::SocketAddr(ref saddr) => udp.send_to(buf, saddr).await, ManagerAddr::DomainName(ref dname, port) => { let (_, n) = lookup_then!(context, dname, port, |saddr| { udp.send_to(buf, saddr).await })?; Ok(n) } #[cfg(unix)] ManagerAddr::UnixSocketAddr(..) => { let err = io::Error::new(ErrorKind::InvalidInput, "udp datagram requires IP address target"); Err(err) } }, #[cfg(unix)] Self::UnixDatagram(ref mut unix) => match *target { ManagerAddr::UnixSocketAddr(ref paddr) => unix.send_to(buf, paddr).await, ManagerAddr::SocketAddr(..) | ManagerAddr::DomainName(..) => { let err = io::Error::new(ErrorKind::InvalidInput, "unix datagram requires path address target"); Err(err) } }, } } /// Returns the local address that this socket is bound to. pub fn local_addr(&self) -> io::Result { match *self { Self::UdpDatagram(ref socket) => socket.local_addr().map(ManagerSocketAddr::SocketAddr), #[cfg(unix)] Self::UnixDatagram(ref dgram) => dgram.local_addr().map(ManagerSocketAddr::UnixSocketAddr), } } } ================================================ FILE: crates/shadowsocks/src/manager/error.rs ================================================ //! Manager API errors use std::io; use thiserror::Error; use super::protocol::Error as ProtocolError; /// Manager Error #[derive(Error, Debug)] pub enum Error { #[error("{0}")] IoError(#[from] io::Error), #[error(transparent)] ProtocolError(#[from] ProtocolError), } impl From for io::Error { fn from(e: Error) -> Self { match e { Error::IoError(e) => e, Error::ProtocolError(e) => From::from(e), } } } ================================================ FILE: crates/shadowsocks/src/manager/listener.rs ================================================ //! Manager server listener use std::io; use log::warn; use crate::{config::ManagerAddr, context::Context, relay::udprelay::MAXIMUM_UDP_PAYLOAD_SIZE}; use super::{ datagram::{ManagerDatagram, ManagerSocketAddr}, error::Error, protocol::{ManagerProtocol, ManagerRequest}, }; /// Manager server Listener #[derive(Debug)] pub struct ManagerListener { socket: ManagerDatagram, } impl ManagerListener { /// Create a `ManagerDatagram` binding to requested `bind_addr` pub async fn bind(context: &Context, bind_addr: &ManagerAddr) -> io::Result { ManagerDatagram::bind(context, bind_addr) .await .map(|socket| Self { socket }) } pub async fn recv_from(&mut self) -> Result<(ManagerRequest, ManagerSocketAddr), Error> { let mut buf = [0u8; MAXIMUM_UDP_PAYLOAD_SIZE]; let (n, peer_addr) = self.socket.recv_from(&mut buf).await?; Ok((ManagerRequest::from_bytes(&buf[..n])?, peer_addr)) } pub async fn send_to(&mut self, data: &P, target: &ManagerSocketAddr) -> Result<(), Error> { let buf = data.to_bytes()?; let n = self.socket.send_to(&buf, target).await?; if n != buf.len() { warn!("manager send_to {} bytes != buffer {} bytes", n, buf.len()); } Ok(()) } pub fn local_addr(&self) -> io::Result { self.socket.local_addr() } } ================================================ FILE: crates/shadowsocks/src/manager/mod.rs ================================================ //! Shadowsocks Server manager //! //! Service for managing multiple relay servers. [Manage Multiple Users](https://github.com/shadowsocks/shadowsocks/wiki/Manage-Multiple-Users) pub use self::{client::ManagerClient, listener::ManagerListener}; pub mod client; pub mod datagram; pub mod error; pub mod listener; pub mod protocol; ================================================ FILE: crates/shadowsocks/src/manager/protocol.rs ================================================ //! Shadowsocks server manager protocol use std::{collections::HashMap, io, str, string::ToString}; use serde::{Deserialize, Serialize}; use thiserror::Error; /// Abstract Manager Protocol pub trait ManagerProtocol: Sized { fn from_bytes(buf: &[u8]) -> Result; fn to_bytes(&self) -> Result, Error>; } /// Server's user configuration #[derive(Serialize, Deserialize, Debug, Clone)] pub struct ServerUserConfig { pub name: String, pub password: String, } /// Server's configuration #[derive(Serialize, Deserialize, Debug, Clone)] pub struct ServerConfig { pub server_port: u16, pub password: String, #[serde(skip_serializing_if = "Option::is_none")] pub method: Option, #[serde(skip_serializing_if = "Option::is_none")] pub no_delay: Option, #[serde(skip_serializing_if = "Option::is_none")] pub plugin: Option, #[serde(skip_serializing_if = "Option::is_none")] pub plugin_opts: Option, #[serde(skip_serializing_if = "Option::is_none")] pub plugin_mode: Option, #[serde(skip_serializing_if = "Option::is_none")] pub mode: Option, #[serde(skip_serializing_if = "Option::is_none")] pub users: Option>, } /// `add` request pub type AddRequest = ServerConfig; impl ManagerProtocol for AddRequest { fn from_bytes(buf: &[u8]) -> Result { let mut nsplit = buf.splitn(2, |b| *b == b':'); let cmd = nsplit.next().expect("first element shouldn't be None"); let cmd = str::from_utf8(cmd)?.trim(); if cmd != "add" { return Err(Error::UnrecognizedCommand(cmd.to_owned())); } match nsplit.next() { None => Err(Error::MissingParameter), Some(param) => { let req = serde_json::from_slice(param)?; Ok(req) } } } fn to_bytes(&self) -> Result, Error> { let mut buf = b"add: ".to_vec(); serde_json::to_writer(&mut buf, self)?; buf.push(b'\n'); Ok(buf) } } /// `add` response #[derive(Debug, Clone)] pub struct AddResponse(pub String); impl ManagerProtocol for AddResponse { fn from_bytes(buf: &[u8]) -> Result { Ok(Self(str::from_utf8(buf)?.trim().to_owned())) } fn to_bytes(&self) -> Result, Error> { let mut v = self.0.as_bytes().to_owned(); v.push(b'\n'); Ok(v) } } /// `remove` request #[derive(Serialize, Deserialize, Debug, Clone)] pub struct RemoveRequest { pub server_port: u16, } impl ManagerProtocol for RemoveRequest { fn from_bytes(buf: &[u8]) -> Result { let mut nsplit = buf.splitn(2, |b| *b == b':'); let cmd = nsplit.next().expect("first element shouldn't be None"); let cmd = str::from_utf8(cmd)?.trim(); if cmd != "remove" { return Err(Error::UnrecognizedCommand(cmd.to_owned())); } match nsplit.next() { None => Err(Error::MissingParameter), Some(param) => { let req = serde_json::from_slice(param)?; Ok(req) } } } fn to_bytes(&self) -> Result, Error> { let mut buf = b"remove: ".to_vec(); serde_json::to_writer(&mut buf, self)?; buf.push(b'\n'); Ok(buf) } } /// `remove` response #[derive(Debug, Clone)] pub struct RemoveResponse(pub String); impl ManagerProtocol for RemoveResponse { fn from_bytes(buf: &[u8]) -> Result { Ok(Self(str::from_utf8(buf)?.trim().to_owned())) } fn to_bytes(&self) -> Result, Error> { let mut v = self.0.as_bytes().to_owned(); v.push(b'\n'); Ok(v) } } /// `list` request #[derive(Debug, Clone)] pub struct ListRequest; impl ManagerProtocol for ListRequest { fn from_bytes(buf: &[u8]) -> Result { let cmd = str::from_utf8(buf)?; if cmd != "list" { return Err(Error::UnrecognizedCommand(cmd.to_owned())); } Ok(Self) } fn to_bytes(&self) -> Result, Error> { Ok(b"list\n".to_vec()) } } /// `list` response #[derive(Serialize, Deserialize, Debug, Clone)] #[serde(transparent)] pub struct ListResponse { pub servers: Vec, } impl ManagerProtocol for ListResponse { fn from_bytes(buf: &[u8]) -> Result { let req = serde_json::from_slice(buf)?; Ok(req) } fn to_bytes(&self) -> Result, Error> { let mut buf = serde_json::to_vec(self)?; buf.push(b'\n'); Ok(buf) } } /// `ping` request #[derive(Debug, Clone)] pub struct PingRequest; impl ManagerProtocol for PingRequest { fn from_bytes(buf: &[u8]) -> Result { let cmd = str::from_utf8(buf)?; if cmd != "ping" { return Err(Error::UnrecognizedCommand(cmd.to_owned())); } Ok(Self) } fn to_bytes(&self) -> Result, Error> { Ok(b"ping\n".to_vec()) } } /// `ping` response #[derive(Serialize, Deserialize, Debug, Clone)] #[serde(transparent)] pub struct PingResponse { pub stat: HashMap, } impl ManagerProtocol for PingResponse { fn from_bytes(buf: &[u8]) -> Result { let mut nsplit = buf.splitn(2, |b| *b == b':'); let cmd = nsplit.next().expect("first element shouldn't be None"); let cmd = str::from_utf8(cmd)?.trim(); if cmd != "stat" { return Err(Error::UnrecognizedCommand(cmd.to_owned())); } match nsplit.next() { None => Err(Error::MissingParameter), Some(param) => { let req = serde_json::from_slice(param)?; Ok(req) } } } fn to_bytes(&self) -> Result, Error> { let mut buf = b"stat: ".to_vec(); serde_json::to_writer(&mut buf, self)?; buf.push(b'\n'); Ok(buf) } } /// `stat` request #[derive(Serialize, Deserialize, Debug, Clone)] #[serde(transparent)] pub struct StatRequest { pub stat: HashMap, } impl ManagerProtocol for StatRequest { fn from_bytes(buf: &[u8]) -> Result { let mut nsplit = buf.splitn(2, |b| *b == b':'); let cmd = nsplit.next().expect("first element shouldn't be None"); let cmd = str::from_utf8(cmd)?.trim(); if cmd != "stat" { return Err(Error::UnrecognizedCommand(cmd.to_owned())); } match nsplit.next() { None => Err(Error::MissingParameter), Some(param) => { let req = serde_json::from_slice(param)?; Ok(req) } } } fn to_bytes(&self) -> Result, Error> { let mut buf = b"stat: ".to_vec(); serde_json::to_writer(&mut buf, self)?; buf.push(b'\n'); Ok(buf) } } /// Server's error message #[derive(Debug, Clone)] pub struct ErrorResponse(pub E); impl ManagerProtocol for ErrorResponse { fn from_bytes(_: &[u8]) -> Result { panic!("ErrorResponse is only for sending errors from manager servers"); } fn to_bytes(&self) -> Result, Error> { let mut v = self.0.to_string().into_bytes(); v.push(b'\n'); Ok(v) } } /// Collections of Manager's request #[derive(Debug, Clone)] pub enum ManagerRequest { Add(AddRequest), Remove(RemoveRequest), List(ListRequest), Ping(PingRequest), Stat(StatRequest), } impl ManagerRequest { /// Command key pub fn command(&self) -> &'static str { match *self { Self::Add(..) => "add", Self::Remove(..) => "remove", Self::List(..) => "list", Self::Ping(..) => "ping", Self::Stat(..) => "stat", } } } impl ManagerProtocol for ManagerRequest { fn to_bytes(&self) -> Result, Error> { match *self { Self::Add(ref req) => req.to_bytes(), Self::Remove(ref req) => req.to_bytes(), Self::List(ref req) => req.to_bytes(), Self::Ping(ref req) => req.to_bytes(), Self::Stat(ref req) => req.to_bytes(), } } fn from_bytes(buf: &[u8]) -> Result { let mut nsplit = buf.splitn(2, |b| *b == b':'); let cmd = nsplit.next().expect("first element shouldn't be None"); match str::from_utf8(cmd)?.trim() { "add" => match nsplit.next() { None => Err(Error::MissingParameter), Some(param) => { let req = serde_json::from_slice(param)?; Ok(Self::Add(req)) } }, "remove" => match nsplit.next() { None => Err(Error::MissingParameter), Some(param) => { let req = serde_json::from_slice(param)?; Ok(Self::Remove(req)) } }, "list" => { if nsplit.next().is_some() { return Err(Error::RedundantParameter); } Ok(Self::List(ListRequest)) } "ping" => { if nsplit.next().is_some() { return Err(Error::RedundantParameter); } Ok(Self::Ping(PingRequest)) } "stat" => match nsplit.next() { None => Err(Error::MissingParameter), Some(param) => { let req = serde_json::from_slice(param)?; Ok(Self::Stat(req)) } }, cmd => Err(Error::UnrecognizedCommand(cmd.to_owned())), } } } /// Manager's Error #[derive(Error, Debug)] pub enum Error { #[error("{0}")] JsonError(#[from] serde_json::Error), #[error("{0}")] FromUtf8Error(#[from] std::str::Utf8Error), #[error("missing parameter")] MissingParameter, #[error("redundant parameter")] RedundantParameter, #[error("unrecognized command \"{0}\"")] UnrecognizedCommand(String), } impl From for io::Error { fn from(err: Error) -> Self { Self::other(err.to_string()) } } ================================================ FILE: crates/shadowsocks/src/net/mod.rs ================================================ //! Network wrappers for shadowsocks' specific requirements use std::net::SocketAddr; #[cfg(unix)] pub use self::sys::uds::{UnixListener, UnixStream}; pub use self::{ option::{AcceptOpts, ConnectOpts, TcpSocketOpts, UdpSocketOpts}, sys::{IpStackCapabilities, get_ip_stack_capabilities, set_tcp_fastopen, socket_bind_dual_stack}, tcp::{TcpListener, TcpStream}, udp::UdpSocket, }; mod option; mod sys; pub mod tcp; pub mod udp; /// Address family `AF_INET`, `AF_INET6` #[derive(Clone, Copy, Debug, Eq, PartialEq)] pub enum AddrFamily { /// `AF_INET` Ipv4, /// `AF_INET6` Ipv6, } impl From<&SocketAddr> for AddrFamily { fn from(addr: &SocketAddr) -> Self { match *addr { SocketAddr::V4(..) => Self::Ipv4, SocketAddr::V6(..) => Self::Ipv6, } } } impl From for AddrFamily { fn from(addr: SocketAddr) -> Self { match addr { SocketAddr::V4(..) => Self::Ipv4, SocketAddr::V6(..) => Self::Ipv6, } } } /// Check if `SocketAddr` could be used for creating dual-stack sockets pub fn is_dual_stack_addr(addr: &SocketAddr) -> bool { if let SocketAddr::V6(ref v6) = *addr { let ip = v6.ip(); ip.is_unspecified() || ip.to_ipv4_mapped().is_some() } else { false } } ================================================ FILE: crates/shadowsocks/src/net/option.rs ================================================ //! Options for connecting to remote server use std::{net::SocketAddr, time::Duration}; /// Options for connecting to TCP remote server #[derive(Debug, Clone, Default)] pub struct TcpSocketOpts { /// TCP socket's `SO_SNDBUF` pub send_buffer_size: Option, /// TCP socket's `SO_RCVBUF` pub recv_buffer_size: Option, /// `TCP_NODELAY` pub nodelay: bool, /// `TCP_FASTOPEN`, enables TFO pub fastopen: bool, /// `SO_KEEPALIVE` and sets `TCP_KEEPIDLE`, `TCP_KEEPINTVL` and `TCP_KEEPCNT` respectively, /// enables keep-alive messages on connection-oriented sockets pub keepalive: Option, /// Enable Multipath-TCP (mptcp) /// https://en.wikipedia.org/wiki/Multipath_TCP /// /// Currently only supported on /// - macOS (iOS, watchOS, ...) with Client Support only. /// - Linux (>5.19) pub mptcp: bool, } /// Options for UDP server #[derive(Debug, Clone, Default)] pub struct UdpSocketOpts { /// Maximum Transmission Unit (MTU) for UDP socket `recv` /// /// NOTE: MTU includes IP header, UDP header, UDP payload pub mtu: Option, /// Outbound UDP socket allows IP fragmentation pub allow_fragmentation: bool, } /// Options for connecting to remote server #[derive(Debug, Clone, Default)] pub struct ConnectOpts { /// Linux mark based routing, going to set by `setsockopt` with `SO_MARK` option #[cfg(any(target_os = "linux", target_os = "android"))] pub fwmark: Option, /// FreeBSD SO_USER_COOKIE /// https://www.freebsd.org/cgi/man.cgi?query=setsockopt&sektion=2 #[cfg(target_os = "freebsd")] pub user_cookie: Option, /// An IPC unix socket path for sending file descriptors to call `VpnService.protect` /// /// This is an [Android shadowsocks implementation](https://github.com/shadowsocks/shadowsocks-android) specific feature #[cfg(target_os = "android")] pub vpn_protect_path: Option, /// A customizable socket protect implementation for Android for calling `VpnService.protect(fd)` /// /// see [`ConnectOpts::set_vpn_socket_protect`] #[cfg(target_os = "android")] pub vpn_socket_protect: Option>>, /// Outbound socket binds to this IP address, mostly for choosing network interfaces /// /// It only affects sockets that trying to connect to addresses with the same family pub bind_local_addr: Option, /// Outbound socket binds to interface pub bind_interface: Option, /// TCP options pub tcp: TcpSocketOpts, /// UDP options pub udp: UdpSocketOpts, } /// Inbound connection options #[derive(Clone, Debug, Default)] pub struct AcceptOpts { /// TCP options pub tcp: TcpSocketOpts, /// UDP options pub udp: UdpSocketOpts, /// Enable IPV6_V6ONLY option for socket pub ipv6_only: bool, } #[cfg(target_os = "android")] impl ConnectOpts { /// Set `vpn_protect_path` for Android VPNService.protect implementation /// /// Example: /// /// ```rust /// // Sync function for calling `VpnService.protect(fd)` /// opts.set_vpn_socket_protect(|fd| { /// // Your implementation here /// // For example, using `jni` to call Android's VpnService.protect(fd) /// Ok(()) /// }); /// ``` pub fn set_vpn_socket_protect(&mut self, f: F) where F: android::MakeSocketProtect + Send + Sync + 'static, F::SocketProtectType: android::SocketProtect + Send + Sync + 'static, { self.vpn_socket_protect = Some(std::sync::Arc::new(Box::new(f.make_socket_protect()))); } } /// Android specific features #[cfg(target_os = "android")] pub mod android { use sealed::sealed; use std::{fmt, io, os::unix::io::RawFd}; /// Android VPN socket protect implementation #[sealed] pub trait SocketProtect { /// Protects the socket file descriptor by calling `VpnService.protect(fd)` fn protect(&self, fd: RawFd) -> io::Result<()>; } impl fmt::Debug for dyn SocketProtect + Send + Sync { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("SocketProtect").finish_non_exhaustive() } } /// Creating an instance of `SocketProtect` #[sealed] pub trait MakeSocketProtect { type SocketProtectType: SocketProtect; /// Creates an instance of `SocketProtect` fn make_socket_protect(self) -> Self::SocketProtectType; } /// A function that implements `SocketProtect` trait pub struct SocketProtectFn { f: F, } #[sealed] impl SocketProtect for SocketProtectFn where F: Fn(RawFd) -> io::Result<()> + Send + Sync + 'static, { fn protect(&self, fd: RawFd) -> io::Result<()> { (self.f)(fd) } } #[sealed] impl MakeSocketProtect for F where F: Fn(RawFd) -> io::Result<()> + Send + Sync + 'static, { type SocketProtectType = SocketProtectFn; fn make_socket_protect(self) -> Self::SocketProtectType { SocketProtectFn { f: self } } } } ================================================ FILE: crates/shadowsocks/src/net/sys/mod.rs ================================================ use std::{ io::{self, ErrorKind}, net::{Ipv4Addr, Ipv6Addr, SocketAddr}, sync::LazyLock, }; use cfg_if::cfg_if; use log::{debug, warn}; use socket2::{Domain, Protocol, SockAddr, SockRef, Socket, Type}; use tokio::net::TcpSocket; use super::ConnectOpts; cfg_if! { if #[cfg(unix)] { mod unix; pub use self::unix::*; } else if #[cfg(windows)] { mod windows; pub use self::windows::*; } } fn set_common_sockopt_for_connect(addr: SocketAddr, socket: &TcpSocket, opts: &ConnectOpts) -> io::Result<()> { // Binds to IP address if let Some(baddr) = opts.bind_local_addr { match (baddr, addr) { (SocketAddr::V4(..), SocketAddr::V4(..)) => { socket.bind(baddr)?; } (SocketAddr::V4(v4baddr), SocketAddr::V6(..)) => { socket.bind(SocketAddr::new(v4baddr.ip().to_ipv6_mapped().into(), v4baddr.port()))?; } (SocketAddr::V6(..), SocketAddr::V6(..)) => { socket.bind(baddr)?; } (SocketAddr::V6(v6baddr), SocketAddr::V4(..)) => match v6baddr.ip().to_ipv4_mapped() { Some(v4baddr) => socket.bind(SocketAddr::new(v4baddr.into(), v6baddr.port()))?, None => { return Err(io::Error::new( ErrorKind::InvalidInput, "bind_local_addr is not a valid IPv4-mapped IPv6 address", )); } }, } } // Set `SO_SNDBUF` if let Some(buf_size) = opts.tcp.send_buffer_size { socket.set_send_buffer_size(buf_size)?; } // Set `SO_RCVBUF` if let Some(buf_size) = opts.tcp.recv_buffer_size { socket.set_recv_buffer_size(buf_size)?; } Ok(()) } #[cfg(all(not(windows), not(unix)))] #[inline] fn set_common_sockopt_after_connect_sys(_: &tokio::net::TcpStream, _: &ConnectOpts) -> io::Result<()> { Ok(()) } /// Try to call `bind()` with dual-stack enabled. /// /// Users have to ensure that `addr` is a dual-stack inbound address (`::`) when `ipv6_only` is `false`. #[cfg(unix)] pub fn socket_bind_dual_stack(socket: &S, addr: &SocketAddr, ipv6_only: bool) -> io::Result<()> where S: std::os::unix::io::AsFd, { let sock = SockRef::from(socket); socket_bind_dual_stack_inner(&sock, addr, ipv6_only) } /// Try to call `bind()` with dual-stack enabled. /// /// Users have to ensure that `addr` is a dual-stack inbound address (`::`) when `ipv6_only` is `false`. #[cfg(windows)] pub fn socket_bind_dual_stack(socket: &S, addr: &SocketAddr, ipv6_only: bool) -> io::Result<()> where S: std::os::windows::io::AsSocket, { let sock = SockRef::from(socket); socket_bind_dual_stack_inner(&sock, addr, ipv6_only) } fn socket_bind_dual_stack_inner(socket: &Socket, addr: &SocketAddr, ipv6_only: bool) -> io::Result<()> { let saddr = SockAddr::from(*addr); if ipv6_only { // Requested to set IPV6_V6ONLY socket.set_only_v6(true)?; socket.bind(&saddr)?; } else { if let Err(err) = socket.set_only_v6(false) { warn!("failed to set IPV6_V6ONLY: false for socket, error: {}", err); // This is not a fatal error, just warn and skip } match socket.bind(&saddr) { Ok(..) => {} Err(ref err) if err.kind() == ErrorKind::AddrInUse => { // This is probably 0.0.0.0 with the same port has already been occupied debug!( "0.0.0.0:{} may have already been occupied, retry with IPV6_V6ONLY", addr.port() ); if let Err(err) = socket.set_only_v6(true) { warn!("failed to set IPV6_V6ONLY: true for socket, error: {}", err); // This is not a fatal error, just warn and skip } socket.bind(&saddr)?; } Err(err) => return Err(err), } } Ok(()) } /// IP Stack Capabilities #[derive(Debug, Clone, Copy, Default)] pub struct IpStackCapabilities { /// IP stack supports IPv4 pub support_ipv4: bool, /// IP stack supports IPv6 pub support_ipv6: bool, /// IP stack supports IPv4-mapped-IPv6 pub support_ipv4_mapped_ipv6: bool, } static IP_STACK_CAPABILITIES: LazyLock = LazyLock::new(|| { // Reference Implementation: https://github.com/golang/go/blob/master/src/net/ipsock_posix.go let mut caps = IpStackCapabilities { support_ipv4: false, support_ipv6: false, support_ipv4_mapped_ipv6: false, }; // Check IPv4 if Socket::new(Domain::IPV4, Type::STREAM, Some(Protocol::TCP)).is_ok() { caps.support_ipv4 = true; debug!("IpStackCapability support_ipv4=true"); } // Check IPv6 (::1) if let Ok(ipv6_socket) = Socket::new(Domain::IPV6, Type::STREAM, Some(Protocol::TCP)) && ipv6_socket.set_only_v6(true).is_ok() { let local_host = SockAddr::from(SocketAddr::new(Ipv6Addr::LOCALHOST.into(), 0)); if ipv6_socket.bind(&local_host).is_ok() { caps.support_ipv6 = true; debug!("IpStackCapability support_ipv6=true"); } } // Check IPv4-mapped-IPv6 (127.0.0.1) if check_ipv4_mapped_ipv6_capability().is_ok() { caps.support_ipv4_mapped_ipv6 = true; debug!("IpStackCapability support_ipv4_mapped_ipv6=true"); } caps }); fn check_ipv4_mapped_ipv6_capability() -> io::Result<()> { let socket = Socket::new(Domain::IPV6, Type::STREAM, Some(Protocol::TCP))?; socket.set_only_v6(false)?; let local_host = SockAddr::from(SocketAddr::new(Ipv4Addr::LOCALHOST.to_ipv6_mapped().into(), 0)); socket.bind(&local_host)?; Ok(()) } /// Get globally probed `IpStackCapabilities` pub fn get_ip_stack_capabilities() -> &'static IpStackCapabilities { &IP_STACK_CAPABILITIES } ================================================ FILE: crates/shadowsocks/src/net/sys/unix/bsd/freebsd.rs ================================================ use std::{ io::{self, ErrorKind}, mem, net::{Ipv4Addr, Ipv6Addr, SocketAddr}, os::unix::io::{AsRawFd, RawFd}, pin::Pin, ptr, sync::atomic::{AtomicBool, Ordering}, task::{self, Poll}, }; use log::{debug, error, warn}; use pin_project::pin_project; use socket2::{Domain, Protocol, SockAddr, SockAddrStorage, Socket, Type}; use tokio::{ io::{AsyncRead, AsyncWrite, ReadBuf}, net::{TcpSocket, TcpStream as TokioTcpStream, UdpSocket}, }; use tokio_tfo::TfoStream; use crate::net::{ AcceptOpts, AddrFamily, ConnectOpts, sys::{set_common_sockopt_after_connect, set_common_sockopt_for_connect, socket_bind_dual_stack}, udp::{BatchRecvMessage, BatchSendMessage}, }; /// A `TcpStream` that supports TFO (TCP Fast Open) #[pin_project(project = TcpStreamProj)] pub enum TcpStream { Standard(#[pin] TokioTcpStream), FastOpen(#[pin] TfoStream), } impl TcpStream { pub async fn connect(addr: SocketAddr, opts: &ConnectOpts) -> io::Result { let socket = match addr { SocketAddr::V4(..) => TcpSocket::new_v4()?, SocketAddr::V6(..) => TcpSocket::new_v6()?, }; // Set SO_USER_COOKIE for mark-based routing on FreeBSD if let Some(user_cookie) = opts.user_cookie { let ret = unsafe { libc::setsockopt( socket.as_raw_fd(), libc::SOL_SOCKET, libc::SO_USER_COOKIE, &user_cookie as *const _ as *const _, mem::size_of_val(&user_cookie) as libc::socklen_t, ) }; if ret != 0 { let err = io::Error::last_os_error(); error!("set SO_USER_COOKIE error: {}", err); return Err(err); } } set_common_sockopt_for_connect(addr, &socket, opts)?; if !opts.tcp.fastopen { // If TFO is not enabled, it just works like a normal TcpStream let stream = socket.connect(addr).await?; set_common_sockopt_after_connect(&stream, opts)?; return Ok(TcpStream::Standard(stream)); } let stream = TfoStream::connect_with_socket(socket, addr).await?; set_common_sockopt_after_connect(&stream, opts)?; Ok(TcpStream::FastOpen(stream)) } pub fn local_addr(&self) -> io::Result { match *self { TcpStream::Standard(ref s) => s.local_addr(), TcpStream::FastOpen(ref s) => s.local_addr(), } } pub fn peer_addr(&self) -> io::Result { match *self { TcpStream::Standard(ref s) => s.peer_addr(), TcpStream::FastOpen(ref s) => s.peer_addr(), } } pub fn nodelay(&self) -> io::Result { match *self { TcpStream::Standard(ref s) => s.nodelay(), TcpStream::FastOpen(ref s) => s.nodelay(), } } pub fn set_nodelay(&self, nodelay: bool) -> io::Result<()> { match *self { TcpStream::Standard(ref s) => s.set_nodelay(nodelay), TcpStream::FastOpen(ref s) => s.set_nodelay(nodelay), } } } impl AsRawFd for TcpStream { fn as_raw_fd(&self) -> RawFd { match *self { TcpStream::Standard(ref s) => s.as_raw_fd(), TcpStream::FastOpen(ref s) => s.as_raw_fd(), } } } impl AsyncRead for TcpStream { fn poll_read(self: Pin<&mut Self>, cx: &mut task::Context<'_>, buf: &mut ReadBuf<'_>) -> Poll> { match self.project() { TcpStreamProj::Standard(s) => s.poll_read(cx, buf), TcpStreamProj::FastOpen(s) => s.poll_read(cx, buf), } } } impl AsyncWrite for TcpStream { fn poll_write(self: Pin<&mut Self>, cx: &mut task::Context<'_>, buf: &[u8]) -> Poll> { match self.project() { TcpStreamProj::Standard(s) => s.poll_write(cx, buf), TcpStreamProj::FastOpen(s) => s.poll_write(cx, buf), } } fn poll_flush(self: Pin<&mut Self>, cx: &mut task::Context<'_>) -> Poll> { match self.project() { TcpStreamProj::Standard(s) => s.poll_flush(cx), TcpStreamProj::FastOpen(s) => s.poll_flush(cx), } } fn poll_shutdown(self: Pin<&mut Self>, cx: &mut task::Context<'_>) -> Poll> { match self.project() { TcpStreamProj::Standard(s) => s.poll_shutdown(cx), TcpStreamProj::FastOpen(s) => s.poll_shutdown(cx), } } } /// Enable `TCP_FASTOPEN` /// /// TCP_FASTOPEN was supported since FreeBSD 12.0 /// /// Example program: pub fn set_tcp_fastopen(socket: &S) -> io::Result<()> { let enable: libc::c_int = 1; unsafe { let ret = libc::setsockopt( socket.as_raw_fd(), libc::IPPROTO_TCP, libc::TCP_FASTOPEN, &enable as *const _ as *const libc::c_void, mem::size_of_val(&enable) as libc::socklen_t, ); if ret != 0 { let err = io::Error::last_os_error(); error!("set TCP_FASTOPEN error: {}", err); return Err(err); } } Ok(()) } /// Create a TCP socket for listening pub async fn create_inbound_tcp_socket(bind_addr: &SocketAddr, _accept_opts: &AcceptOpts) -> io::Result { match bind_addr { SocketAddr::V4(..) => TcpSocket::new_v4(), SocketAddr::V6(..) => TcpSocket::new_v6(), } } /// Disable IP fragmentation #[inline] pub fn set_disable_ip_fragmentation(af: AddrFamily, socket: &S) -> io::Result<()> { // https://www.freebsd.org/cgi/man.cgi?query=ip&sektion=4&manpath=FreeBSD+9.0-RELEASE // sys/netinet/in.h const IP_DONTFRAG: libc::c_int = 67; // don't fragment packet // sys/netinet6/in6.h const IPV6_DONTFRAG: libc::c_int = 62; // bool; disable IPv6 fragmentation unsafe { match af { AddrFamily::Ipv4 => { let enable: i32 = 1; let ret = libc::setsockopt( socket.as_raw_fd(), libc::IPPROTO_IP, IP_DONTFRAG, &enable as *const _ as *const _, mem::size_of_val(&enable) as libc::socklen_t, ); if ret < 0 { return Err(io::Error::last_os_error()); } } AddrFamily::Ipv6 => { let enable: i32 = 1; let ret = libc::setsockopt( socket.as_raw_fd(), libc::IPPROTO_IPV6, IPV6_DONTFRAG, &enable as *const _ as *const _, mem::size_of_val(&enable) as libc::socklen_t, ); if ret < 0 { return Err(io::Error::last_os_error()); } } } } Ok(()) } /// Create a `UdpSocket` with specific address family #[inline] pub async fn create_outbound_udp_socket(af: AddrFamily, config: &ConnectOpts) -> io::Result { let bind_addr = match (af, config.bind_local_addr) { (AddrFamily::Ipv4, Some(SocketAddr::V4(addr))) => addr.into(), (AddrFamily::Ipv4, Some(SocketAddr::V6(addr))) => { // Map IPv6 bind_local_addr to IPv4 if AF is IPv4 match addr.ip().to_ipv4_mapped() { Some(addr) => SocketAddr::new(addr.into(), 0), None => return Err(io::Error::new(ErrorKind::InvalidInput, "Invalid IPv6 address")), } } (AddrFamily::Ipv6, Some(SocketAddr::V6(addr))) => addr.into(), (AddrFamily::Ipv6, Some(SocketAddr::V4(addr))) => { // Map IPv4 bind_local_addr to IPv6 if AF is IPv6 SocketAddr::new(addr.ip().to_ipv6_mapped().into(), 0) } (AddrFamily::Ipv4, ..) => SocketAddr::new(Ipv4Addr::UNSPECIFIED.into(), 0), (AddrFamily::Ipv6, ..) => SocketAddr::new(Ipv6Addr::UNSPECIFIED.into(), 0), }; bind_outbound_udp_socket(&bind_addr, config).await } /// Create a `UdpSocket` binded to `bind_addr` pub async fn bind_outbound_udp_socket(bind_addr: &SocketAddr, config: &ConnectOpts) -> io::Result { let af = AddrFamily::from(bind_addr); let socket = if af != AddrFamily::Ipv6 { UdpSocket::bind(bind_addr).await? } else { let socket = Socket::new(Domain::for_address(*bind_addr), Type::DGRAM, Some(Protocol::UDP))?; socket_bind_dual_stack(&socket, bind_addr, false)?; // UdpSocket::from_std requires socket to be non-blocked socket.set_nonblocking(true)?; UdpSocket::from_std(socket.into())? }; if !config.udp.allow_fragmentation { if let Err(err) = set_disable_ip_fragmentation(af, &socket) { warn!("failed to disable IP fragmentation, error: {}", err); } } Ok(socket) } static SUPPORT_BATCH_SEND_RECV_MSG: AtomicBool = AtomicBool::new(true); fn recvmsg_fallback(sock: &S, msg: &mut BatchRecvMessage<'_>) -> io::Result<()> { let mut hdr: libc::msghdr = unsafe { mem::zeroed() }; let addr_storage = SockAddrStorage::zeroed(); let addr_len = addr_storage.size_of() as libc::socklen_t; let sock_addr = unsafe { SockAddr::new(addr_storage, addr_len) }; hdr.msg_name = sock_addr.as_ptr() as *mut _; hdr.msg_namelen = sock_addr.len() as _; hdr.msg_iov = msg.data.as_ptr() as *mut _; hdr.msg_iovlen = msg.data.len() as _; let ret = unsafe { libc::recvmsg(sock.as_raw_fd(), &mut hdr as *mut _, 0) }; if ret < 0 { return Err(io::Error::last_os_error()); } msg.addr = sock_addr.as_socket().expect("SockAddr.as_socket"); msg.data_len = ret as usize; Ok(()) } pub fn batch_recvmsg(sock: &S, msgs: &mut [BatchRecvMessage<'_>]) -> io::Result { if msgs.is_empty() { return Ok(0); } if !SUPPORT_BATCH_SEND_RECV_MSG.load(Ordering::Relaxed) { recvmsg_fallback(sock, &mut msgs[0])?; return Ok(1); } let mut vec_msg_name = Vec::with_capacity(msgs.len()); let mut vec_msg_hdr = Vec::with_capacity(msgs.len()); for msg in msgs.iter_mut() { let mut hdr: libc::mmsghdr = unsafe { mem::zeroed() }; let addr_storage = SockAddrStorage::zeroed(); let addr_len = addr_storage.size_of() as libc::socklen_t; vec_msg_name.push(unsafe { SockAddr::new(addr_storage, addr_len) }); let sock_addr = vec_msg_name.last_mut().unwrap(); hdr.msg_hdr.msg_name = sock_addr.as_ptr() as *mut _; hdr.msg_hdr.msg_namelen = sock_addr.len() as _; hdr.msg_hdr.msg_iov = msg.data.as_ptr() as *mut _; hdr.msg_hdr.msg_iovlen = msg.data.len() as _; vec_msg_hdr.push(hdr); } let ret = unsafe { libc::recvmmsg( sock.as_raw_fd(), vec_msg_hdr.as_mut_ptr(), vec_msg_hdr.len() as _, 0, ptr::null(), ) }; if ret < 0 { let err = io::Error::last_os_error(); if let Some(libc::ENOSYS) = err.raw_os_error() { debug!("recvmmsg is not supported, fallback to recvmsg, error: {:?}", err); SUPPORT_BATCH_SEND_RECV_MSG.store(false, Ordering::Relaxed); recvmsg_fallback(sock, &mut msgs[0])?; return Ok(1); } return Err(err); } for idx in 0..ret as usize { let msg = &mut msgs[idx]; let hdr = &vec_msg_hdr[idx]; let name = &vec_msg_name[idx]; msg.addr = name.as_socket().expect("SockAddr.as_socket"); msg.data_len = hdr.msg_len as usize; } Ok(ret as usize) } fn sendmsg_fallback(sock: &S, msg: &mut BatchSendMessage<'_>) -> io::Result<()> { let mut hdr: libc::msghdr = unsafe { mem::zeroed() }; let sock_addr = msg.addr.map(SockAddr::from); if let Some(ref sa) = sock_addr { hdr.msg_name = sa.as_ptr() as *mut _; hdr.msg_namelen = sa.len() as _; } hdr.msg_iov = msg.data.as_ptr() as *mut _; hdr.msg_iovlen = msg.data.len() as _; let ret = unsafe { libc::sendmsg(sock.as_raw_fd(), &hdr as *const _, 0) }; if ret < 0 { return Err(io::Error::last_os_error()); } msg.data_len = ret as usize; Ok(()) } pub fn batch_sendmsg(sock: &S, msgs: &mut [BatchSendMessage<'_>]) -> io::Result { if msgs.is_empty() { return Ok(0); } if !SUPPORT_BATCH_SEND_RECV_MSG.load(Ordering::Relaxed) { sendmsg_fallback(sock, &mut msgs[0])?; return Ok(1); } let mut vec_msg_name = Vec::with_capacity(msgs.len()); let mut vec_msg_hdr = Vec::with_capacity(msgs.len()); for msg in msgs.iter_mut() { let mut hdr: libc::mmsghdr = unsafe { mem::zeroed() }; if let Some(addr) = msg.addr { vec_msg_name.push(SockAddr::from(addr)); let sock_addr = vec_msg_name.last_mut().unwrap(); hdr.msg_hdr.msg_name = sock_addr.as_ptr() as *mut _; hdr.msg_hdr.msg_namelen = sock_addr.len() as _; } hdr.msg_hdr.msg_iov = msg.data.as_ptr() as *mut _; hdr.msg_hdr.msg_iovlen = msg.data.len() as _; vec_msg_hdr.push(hdr); } let ret = unsafe { libc::sendmmsg(sock.as_raw_fd(), vec_msg_hdr.as_mut_ptr(), vec_msg_hdr.len() as _, 0) }; if ret < 0 { let err = io::Error::last_os_error(); if let Some(libc::ENOSYS) = err.raw_os_error() { debug!("sendmmsg is not supported, fallback to sendmsg, error: {:?}", err); SUPPORT_BATCH_SEND_RECV_MSG.store(false, Ordering::Relaxed); sendmsg_fallback(sock, &mut msgs[0])?; return Ok(1); } return Err(err); } for idx in 0..ret as usize { let msg = &mut msgs[idx]; let hdr = &vec_msg_hdr[idx]; msg.data_len = hdr.msg_len as usize; } Ok(ret as usize) } ================================================ FILE: crates/shadowsocks/src/net/sys/unix/bsd/macos.rs ================================================ use std::{ cell::RefCell, collections::HashMap, io::{self, ErrorKind}, mem, net::{Ipv4Addr, Ipv6Addr, SocketAddr, TcpStream as StdTcpStream}, os::unix::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd}, pin::Pin, ptr, sync::atomic::{AtomicBool, Ordering}, task::{self, Poll}, time::{Duration, Instant}, }; use log::{debug, error, warn}; use pin_project::pin_project; use socket2::{Domain, Protocol, SockAddr, SockAddrStorage, Socket, Type}; use tokio::{ io::{AsyncRead, AsyncWrite, Interest, ReadBuf}, net::{TcpSocket, TcpStream as TokioTcpStream, UdpSocket}, }; use tokio_tfo::TfoStream; use crate::net::{ AcceptOpts, AddrFamily, ConnectOpts, sys::{set_common_sockopt_after_connect, set_common_sockopt_for_connect, socket_bind_dual_stack}, udp::{BatchRecvMessage, BatchSendMessage}, }; /// A `TcpStream` that supports TFO (TCP Fast Open) #[pin_project(project = TcpStreamProj)] pub enum TcpStream { Standard(#[pin] TokioTcpStream), FastOpen(#[pin] TfoStream), } impl TcpStream { pub async fn connect(addr: SocketAddr, opts: &ConnectOpts) -> io::Result { if opts.tcp.mptcp { return TcpStream::connect_mptcp(addr, opts).await; } let socket = match addr { SocketAddr::V4(..) => TcpSocket::new_v4()?, SocketAddr::V6(..) => TcpSocket::new_v6()?, }; TcpStream::connect_with_socket(socket, addr, opts).await } async fn connect_mptcp(addr: SocketAddr, opts: &ConnectOpts) -> io::Result { // https://opensource.apple.com/source/xnu/xnu-4570.41.2/bsd/sys/socket.h.auto.html const AF_MULTIPATH: libc::c_int = 39; let socket = unsafe { let fd = libc::socket(AF_MULTIPATH, libc::SOCK_STREAM, libc::IPPROTO_TCP); if fd < 0 { let err = io::Error::last_os_error(); return Err(err); } let socket = Socket::from_raw_fd(fd); socket.set_nonblocking(true)?; TcpSocket::from_raw_fd(socket.into_raw_fd()) }; TcpStream::connect_with_socket(socket, addr, opts).await } #[inline] async fn connect_with_socket(socket: TcpSocket, addr: SocketAddr, opts: &ConnectOpts) -> io::Result { // Binds to a specific network interface (device) if let Some(ref iface) = opts.bind_interface { set_ip_bound_if(&socket, &addr, iface)?; } set_common_sockopt_for_connect(addr, &socket, opts)?; if !opts.tcp.fastopen { // If TFO is not enabled, it just works like a normal TcpStream // // But for Multipath-TCP, we must use connectx // http://blog.multipath-tcp.org/blog/html/2018/12/17/multipath_tcp_apis.html let stream = if opts.tcp.mptcp { let stream = unsafe { let raddr = SockAddr::from(addr); let mut endpoints: libc::sa_endpoints_t = mem::zeroed(); endpoints.sae_dstaddr = raddr.as_ptr() as *const _; endpoints.sae_dstaddrlen = raddr.len(); let ret = libc::connectx( socket.as_raw_fd(), &endpoints as *const _, libc::SAE_ASSOCID_ANY, 0, ptr::null(), 0, ptr::null_mut(), ptr::null_mut(), ); if ret != 0 { let err = io::Error::last_os_error(); if err.raw_os_error() != Some(libc::EINPROGRESS) { return Err(err); } } let fd = socket.into_raw_fd(); TokioTcpStream::from_std(StdTcpStream::from_raw_fd(fd))? }; stream.ready(Interest::WRITABLE).await?; stream.take_error()?; stream } else { socket.connect(addr).await? }; set_common_sockopt_after_connect(&stream, opts)?; return Ok(TcpStream::Standard(stream)); } let stream = TfoStream::connect_with_socket(socket, addr).await?; set_common_sockopt_after_connect(&stream, opts)?; Ok(TcpStream::FastOpen(stream)) } pub fn local_addr(&self) -> io::Result { match *self { TcpStream::Standard(ref s) => s.local_addr(), TcpStream::FastOpen(ref s) => s.local_addr(), } } pub fn peer_addr(&self) -> io::Result { match *self { TcpStream::Standard(ref s) => s.peer_addr(), TcpStream::FastOpen(ref s) => s.peer_addr(), } } pub fn nodelay(&self) -> io::Result { match *self { TcpStream::Standard(ref s) => s.nodelay(), TcpStream::FastOpen(ref s) => s.nodelay(), } } pub fn set_nodelay(&self, nodelay: bool) -> io::Result<()> { match *self { TcpStream::Standard(ref s) => s.set_nodelay(nodelay), TcpStream::FastOpen(ref s) => s.set_nodelay(nodelay), } } } impl AsRawFd for TcpStream { fn as_raw_fd(&self) -> RawFd { match *self { TcpStream::Standard(ref s) => s.as_raw_fd(), TcpStream::FastOpen(ref s) => s.as_raw_fd(), } } } impl AsyncRead for TcpStream { fn poll_read(self: Pin<&mut Self>, cx: &mut task::Context<'_>, buf: &mut ReadBuf<'_>) -> Poll> { match self.project() { TcpStreamProj::Standard(s) => s.poll_read(cx, buf), TcpStreamProj::FastOpen(s) => s.poll_read(cx, buf), } } } impl AsyncWrite for TcpStream { fn poll_write(self: Pin<&mut Self>, cx: &mut task::Context<'_>, buf: &[u8]) -> Poll> { match self.project() { TcpStreamProj::Standard(s) => s.poll_write(cx, buf), TcpStreamProj::FastOpen(s) => s.poll_write(cx, buf), } } fn poll_flush(self: Pin<&mut Self>, cx: &mut task::Context<'_>) -> Poll> { match self.project() { TcpStreamProj::Standard(s) => s.poll_flush(cx), TcpStreamProj::FastOpen(s) => s.poll_flush(cx), } } fn poll_shutdown(self: Pin<&mut Self>, cx: &mut task::Context<'_>) -> Poll> { match self.project() { TcpStreamProj::Standard(s) => s.poll_shutdown(cx), TcpStreamProj::FastOpen(s) => s.poll_shutdown(cx), } } } /// Enable `TCP_FASTOPEN` /// /// `TCP_FASTOPEN` was supported since /// macosx(10.11), ios(9.0), tvos(9.0), watchos(2.0) pub fn set_tcp_fastopen(socket: &S) -> io::Result<()> { let enable: libc::c_int = 1; unsafe { let ret = libc::setsockopt( socket.as_raw_fd(), libc::IPPROTO_TCP, libc::TCP_FASTOPEN, &enable as *const _ as *const libc::c_void, mem::size_of_val(&enable) as libc::socklen_t, ); if ret != 0 { let err = io::Error::last_os_error(); error!("set TCP_FASTOPEN error: {}", err); return Err(err); } } Ok(()) } /// Create a TCP socket for listening pub async fn create_inbound_tcp_socket(bind_addr: &SocketAddr, _accept_opts: &AcceptOpts) -> io::Result { match bind_addr { SocketAddr::V4(..) => TcpSocket::new_v4(), SocketAddr::V6(..) => TcpSocket::new_v6(), } } fn find_interface_index_cached(iface: &str) -> io::Result { const INDEX_EXPIRE_DURATION: Duration = Duration::from_secs(5); thread_local! { static INTERFACE_INDEX_CACHE: RefCell> = RefCell::new(HashMap::new()); } let cache_index = INTERFACE_INDEX_CACHE.with(|cache| cache.borrow().get(iface).cloned()); if let Some((idx, insert_time)) = cache_index { // short-path, cache hit for most cases let now = Instant::now(); if now - insert_time < INDEX_EXPIRE_DURATION { return Ok(idx); } } let index = unsafe { let mut ciface = [0u8; libc::IFNAMSIZ]; if iface.len() >= ciface.len() { return Err(ErrorKind::InvalidInput.into()); } let iface_bytes = iface.as_bytes(); ptr::copy_nonoverlapping(iface_bytes.as_ptr(), ciface.as_mut_ptr(), iface_bytes.len()); libc::if_nametoindex(ciface.as_ptr() as *const libc::c_char) }; if index == 0 { let err = io::Error::last_os_error(); error!("if_nametoindex ifname: {} error: {}", iface, err); return Err(err); } INTERFACE_INDEX_CACHE.with(|cache| { cache.borrow_mut().insert(iface.to_owned(), (index, Instant::now())); }); Ok(index) } fn set_ip_bound_if(socket: &S, addr: &SocketAddr, iface: &str) -> io::Result<()> { const IP_BOUND_IF: libc::c_int = 25; // bsd/netinet/in.h const IPV6_BOUND_IF: libc::c_int = 125; // bsd/netinet6/in6.h unsafe { let index = find_interface_index_cached(iface)?; let ret = match addr { SocketAddr::V4(..) => libc::setsockopt( socket.as_raw_fd(), libc::IPPROTO_IP, IP_BOUND_IF, &index as *const _ as *const _, mem::size_of_val(&index) as libc::socklen_t, ), SocketAddr::V6(..) => libc::setsockopt( socket.as_raw_fd(), libc::IPPROTO_IPV6, IPV6_BOUND_IF, &index as *const _ as *const _, mem::size_of_val(&index) as libc::socklen_t, ), }; if ret < 0 { let err = io::Error::last_os_error(); error!( "set IF_BOUND_IF/IPV6_BOUND_IF ifname: {} ifindex: {} error: {}", iface, index, err ); return Err(err); } } Ok(()) } /// Disable IP fragmentation #[inline] pub fn set_disable_ip_fragmentation(af: AddrFamily, socket: &S) -> io::Result<()> { unsafe { match af { AddrFamily::Ipv4 => { let enable: i32 = 1; let ret = libc::setsockopt( socket.as_raw_fd(), libc::IPPROTO_IP, libc::IP_DONTFRAG, &enable as *const _ as *const _, mem::size_of_val(&enable) as libc::socklen_t, ); if ret < 0 { return Err(io::Error::last_os_error()); } } AddrFamily::Ipv6 => { let enable: i32 = 1; let ret = libc::setsockopt( socket.as_raw_fd(), libc::IPPROTO_IPV6, libc::IPV6_DONTFRAG, &enable as *const _ as *const _, mem::size_of_val(&enable) as libc::socklen_t, ); if ret < 0 { return Err(io::Error::last_os_error()); } } } } Ok(()) } /// Create a `UdpSocket` with specific address family #[inline] pub async fn create_outbound_udp_socket(af: AddrFamily, config: &ConnectOpts) -> io::Result { let bind_addr = match (af, config.bind_local_addr) { (AddrFamily::Ipv4, Some(SocketAddr::V4(addr))) => addr.into(), (AddrFamily::Ipv4, Some(SocketAddr::V6(addr))) => { // Map IPv6 bind_local_addr to IPv4 if AF is IPv4 match addr.ip().to_ipv4_mapped() { Some(addr) => SocketAddr::new(addr.into(), 0), None => return Err(io::Error::new(ErrorKind::InvalidInput, "Invalid IPv6 address")), } } (AddrFamily::Ipv6, Some(SocketAddr::V6(addr))) => addr.into(), (AddrFamily::Ipv6, Some(SocketAddr::V4(addr))) => { // Map IPv4 bind_local_addr to IPv6 if AF is IPv6 SocketAddr::new(addr.ip().to_ipv6_mapped().into(), 0) } (AddrFamily::Ipv4, ..) => SocketAddr::new(Ipv4Addr::UNSPECIFIED.into(), 0), (AddrFamily::Ipv6, ..) => SocketAddr::new(Ipv6Addr::UNSPECIFIED.into(), 0), }; bind_outbound_udp_socket(&bind_addr, config).await } /// Create a `UdpSocket` binded to `bind_addr` pub async fn bind_outbound_udp_socket(bind_addr: &SocketAddr, config: &ConnectOpts) -> io::Result { let af = AddrFamily::from(bind_addr); let socket = if af != AddrFamily::Ipv6 { UdpSocket::bind(bind_addr).await? } else { let socket = Socket::new(Domain::for_address(*bind_addr), Type::DGRAM, Some(Protocol::UDP))?; socket_bind_dual_stack(&socket, bind_addr, false)?; // UdpSocket::from_std requires socket to be non-blocked socket.set_nonblocking(true)?; UdpSocket::from_std(socket.into())? }; if !config.udp.allow_fragmentation && let Err(err) = set_disable_ip_fragmentation(af, &socket) { warn!("failed to disable IP fragmentation, error: {}", err); } // Set IP_BOUND_IF for BSD-like if let Some(ref iface) = config.bind_interface { set_ip_bound_if(&socket, bind_addr, iface)?; } Ok(socket) } /// https://github.com/apple/darwin-xnu/blob/main/bsd/sys/socket.h #[repr(C)] #[allow(non_camel_case_types)] struct msghdr_x { msg_name: *mut libc::c_void, //< optional address msg_namelen: libc::socklen_t, //< size of address msg_iov: *mut libc::iovec, //< scatter/gather array msg_iovlen: libc::c_int, //< # elements in msg_iov msg_control: *mut libc::c_void, //< ancillary data, see below msg_controllen: libc::socklen_t, //< ancillary data buffer len msg_flags: libc::c_int, //< flags on received message msg_datalen: libc::size_t, //< byte length of buffer in msg_iov } unsafe extern "C" { fn recvmsg_x(s: libc::c_int, msgp: *const msghdr_x, cnt: libc::c_uint, flags: libc::c_int) -> libc::ssize_t; fn sendmsg_x(s: libc::c_int, msgp: *const msghdr_x, cnt: libc::c_uint, flags: libc::c_int) -> libc::ssize_t; } static SUPPORT_BATCH_SEND_RECV_MSG: AtomicBool = AtomicBool::new(true); fn recvmsg_fallback(sock: &S, msg: &mut BatchRecvMessage<'_>) -> io::Result<()> { let mut hdr: libc::msghdr = unsafe { mem::zeroed() }; let addr_storage = SockAddrStorage::zeroed(); let addr_len = addr_storage.size_of() as libc::socklen_t; let sock_addr = unsafe { SockAddr::new(addr_storage, addr_len) }; hdr.msg_name = sock_addr.as_ptr() as *mut _; hdr.msg_namelen = sock_addr.len() as _; hdr.msg_iov = msg.data.as_ptr() as *mut _; hdr.msg_iovlen = msg.data.len() as _; let ret = unsafe { libc::recvmsg(sock.as_raw_fd(), &mut hdr as *mut _, 0) }; if ret < 0 { return Err(io::Error::last_os_error()); } msg.addr = sock_addr.as_socket().expect("SockAddr.as_socket"); msg.data_len = ret as usize; Ok(()) } pub fn batch_recvmsg(sock: &S, msgs: &mut [BatchRecvMessage<'_>]) -> io::Result { if msgs.is_empty() { return Ok(0); } if !SUPPORT_BATCH_SEND_RECV_MSG.load(Ordering::Relaxed) { recvmsg_fallback(sock, &mut msgs[0])?; return Ok(1); } let mut vec_msg_name = Vec::with_capacity(msgs.len()); let mut vec_msg_hdr = Vec::with_capacity(msgs.len()); for msg in msgs.iter_mut() { let mut hdr: msghdr_x = unsafe { mem::zeroed() }; let addr_storage = SockAddrStorage::zeroed(); let addr_len = addr_storage.size_of() as libc::socklen_t; vec_msg_name.push(unsafe { SockAddr::new(addr_storage, addr_len) }); let sock_addr = vec_msg_name.last_mut().unwrap(); hdr.msg_name = sock_addr.as_ptr() as *mut _; hdr.msg_namelen = sock_addr.len() as _; hdr.msg_iov = msg.data.as_ptr() as *mut _; hdr.msg_iovlen = msg.data.len() as _; vec_msg_hdr.push(hdr); } let ret = unsafe { recvmsg_x(sock.as_raw_fd(), vec_msg_hdr.as_ptr(), vec_msg_hdr.len() as _, 0) }; if ret < 0 { let err = io::Error::last_os_error(); if let Some(libc::ENOSYS) = err.raw_os_error() { debug!("recvmsg_x is not supported, fallback to recvmsg, error: {:?}", err); SUPPORT_BATCH_SEND_RECV_MSG.store(false, Ordering::Relaxed); recvmsg_fallback(sock, &mut msgs[0])?; return Ok(1); } return Err(err); } for idx in 0..ret as usize { let msg = &mut msgs[idx]; let hdr = &vec_msg_hdr[idx]; let name = &vec_msg_name[idx]; msg.addr = name.as_socket().expect("SockAddr.as_socket"); msg.data_len = hdr.msg_datalen; } Ok(ret as usize) } fn sendmsg_fallback(sock: &S, msg: &mut BatchSendMessage<'_>) -> io::Result<()> { let mut hdr: libc::msghdr = unsafe { mem::zeroed() }; let sock_addr = msg.addr.map(SockAddr::from); if let Some(ref sa) = sock_addr { hdr.msg_name = sa.as_ptr() as *mut _; hdr.msg_namelen = sa.len() as _; } hdr.msg_iov = msg.data.as_ptr() as *mut _; hdr.msg_iovlen = msg.data.len() as _; let ret = unsafe { libc::sendmsg(sock.as_raw_fd(), &hdr as *const _, 0) }; if ret < 0 { return Err(io::Error::last_os_error()); } msg.data_len = ret as usize; Ok(()) } pub fn batch_sendmsg(sock: &S, msgs: &mut [BatchSendMessage<'_>]) -> io::Result { if msgs.is_empty() { return Ok(0); } if !SUPPORT_BATCH_SEND_RECV_MSG.load(Ordering::Relaxed) { sendmsg_fallback(sock, &mut msgs[0])?; return Ok(1); } let mut vec_msg_name = Vec::with_capacity(msgs.len()); let mut vec_msg_hdr = Vec::with_capacity(msgs.len()); for msg in msgs.iter_mut() { let mut hdr: msghdr_x = unsafe { mem::zeroed() }; if let Some(addr) = msg.addr { vec_msg_name.push(SockAddr::from(addr)); let sock_addr = vec_msg_name.last_mut().unwrap(); hdr.msg_name = sock_addr.as_ptr() as *mut _; hdr.msg_namelen = sock_addr.len() as _; } hdr.msg_iov = msg.data.as_ptr() as *mut _; hdr.msg_iovlen = msg.data.len() as _; vec_msg_hdr.push(hdr); } let ret = unsafe { sendmsg_x(sock.as_raw_fd(), vec_msg_hdr.as_ptr(), vec_msg_hdr.len() as _, 0) }; if ret < 0 { let err = io::Error::last_os_error(); if let Some(libc::ENOSYS) = err.raw_os_error() { debug!("sendmsg_x is not supported, fallback to sendmsg, error: {:?}", err); SUPPORT_BATCH_SEND_RECV_MSG.store(false, Ordering::Relaxed); sendmsg_fallback(sock, &mut msgs[0])?; return Ok(1); } return Err(err); } for idx in 0..ret as usize { let msg = &mut msgs[idx]; let hdr = &vec_msg_hdr[idx]; msg.data_len = hdr.msg_datalen; } Ok(ret as usize) } ================================================ FILE: crates/shadowsocks/src/net/sys/unix/bsd/mod.rs ================================================ use cfg_if::cfg_if; cfg_if! { if #[cfg(target_os = "freebsd")] { mod freebsd; pub use self::freebsd::*; } else if #[cfg(any(target_os = "macos", target_os = "ios", target_os = "watchos", target_os = "tvos"))] { mod macos; pub use self::macos::*; } else { mod others; pub use self::others::*; } } ================================================ FILE: crates/shadowsocks/src/net/sys/unix/bsd/others.rs ================================================ include!("../others.rs"); ================================================ FILE: crates/shadowsocks/src/net/sys/unix/linux/mod.rs ================================================ use std::{ io::{self, ErrorKind}, mem, net::{Ipv4Addr, Ipv6Addr, SocketAddr}, os::unix::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd}, pin::Pin, ptr, sync::atomic::{AtomicBool, Ordering}, task::{self, Poll}, }; use log::{debug, error, warn}; use pin_project::pin_project; use socket2::{Domain, Protocol, SockAddr, SockAddrStorage, Socket, Type}; use tokio::{ io::{AsyncRead, AsyncWrite, ReadBuf}, net::{TcpSocket, TcpStream as TokioTcpStream, UdpSocket}, }; use tokio_tfo::TfoStream; use crate::net::{ AcceptOpts, AddrFamily, ConnectOpts, sys::{set_common_sockopt_after_connect, set_common_sockopt_for_connect, socket_bind_dual_stack}, udp::{BatchRecvMessage, BatchSendMessage}, }; /// A `TcpStream` that supports TFO (TCP Fast Open) #[pin_project(project = TcpStreamProj)] pub enum TcpStream { Standard(#[pin] TokioTcpStream), FastOpen(#[pin] TfoStream), } impl TcpStream { pub async fn connect(addr: SocketAddr, opts: &ConnectOpts) -> io::Result { if opts.tcp.mptcp { return Self::connect_mptcp(addr, opts).await; } let socket = match addr { SocketAddr::V4(..) => TcpSocket::new_v4()?, SocketAddr::V6(..) => TcpSocket::new_v6()?, }; Self::connect_with_socket(socket, addr, opts).await } async fn connect_mptcp(addr: SocketAddr, opts: &ConnectOpts) -> io::Result { let socket = create_mptcp_socket(&addr)?; Self::connect_with_socket(socket, addr, opts).await } async fn connect_with_socket(socket: TcpSocket, addr: SocketAddr, opts: &ConnectOpts) -> io::Result { // Any traffic to localhost should not be protected // This is a workaround for VPNService #[cfg(target_os = "android")] if !addr.ip().is_loopback() { android::vpn_protect(&socket, opts).await?; } // Set SO_MARK for mark-based routing on Linux (since 2.6.25) // NOTE: This will require CAP_NET_ADMIN capability (root in most cases) if let Some(mark) = opts.fwmark { let ret = unsafe { libc::setsockopt( socket.as_raw_fd(), libc::SOL_SOCKET, libc::SO_MARK, &mark as *const _ as *const _, mem::size_of_val(&mark) as libc::socklen_t, ) }; if ret != 0 { let err = io::Error::last_os_error(); error!("set SO_MARK error: {}", err); return Err(err); } } // Set SO_BINDTODEVICE for binding to a specific interface if let Some(ref iface) = opts.bind_interface { set_bindtodevice(&socket, iface)?; } set_common_sockopt_for_connect(addr, &socket, opts)?; if !opts.tcp.fastopen { // If TFO is not enabled, it just works like a normal TcpStream let stream = socket.connect(addr).await?; set_common_sockopt_after_connect(&stream, opts)?; return Ok(Self::Standard(stream)); } let stream = TfoStream::connect_with_socket(socket, addr).await?; set_common_sockopt_after_connect(&stream, opts)?; Ok(Self::FastOpen(stream)) } pub fn local_addr(&self) -> io::Result { match *self { Self::Standard(ref s) => s.local_addr(), Self::FastOpen(ref s) => s.local_addr(), } } pub fn peer_addr(&self) -> io::Result { match *self { Self::Standard(ref s) => s.peer_addr(), Self::FastOpen(ref s) => s.peer_addr(), } } pub fn nodelay(&self) -> io::Result { match *self { Self::Standard(ref s) => s.nodelay(), Self::FastOpen(ref s) => s.nodelay(), } } pub fn set_nodelay(&self, nodelay: bool) -> io::Result<()> { match *self { Self::Standard(ref s) => s.set_nodelay(nodelay), Self::FastOpen(ref s) => s.set_nodelay(nodelay), } } } impl AsRawFd for TcpStream { fn as_raw_fd(&self) -> RawFd { match *self { Self::Standard(ref s) => s.as_raw_fd(), Self::FastOpen(ref s) => s.as_raw_fd(), } } } impl AsyncRead for TcpStream { fn poll_read(self: Pin<&mut Self>, cx: &mut task::Context<'_>, buf: &mut ReadBuf<'_>) -> Poll> { match self.project() { TcpStreamProj::Standard(s) => s.poll_read(cx, buf), TcpStreamProj::FastOpen(s) => s.poll_read(cx, buf), } } } impl AsyncWrite for TcpStream { fn poll_write(self: Pin<&mut Self>, cx: &mut task::Context<'_>, buf: &[u8]) -> Poll> { match self.project() { TcpStreamProj::Standard(s) => s.poll_write(cx, buf), TcpStreamProj::FastOpen(s) => s.poll_write(cx, buf), } } fn poll_flush(self: Pin<&mut Self>, cx: &mut task::Context<'_>) -> Poll> { match self.project() { TcpStreamProj::Standard(s) => s.poll_flush(cx), TcpStreamProj::FastOpen(s) => s.poll_flush(cx), } } fn poll_shutdown(self: Pin<&mut Self>, cx: &mut task::Context<'_>) -> Poll> { match self.project() { TcpStreamProj::Standard(s) => s.poll_shutdown(cx), TcpStreamProj::FastOpen(s) => s.poll_shutdown(cx), } } } /// Enable `TCP_FASTOPEN` /// /// `TCP_FASTOPEN` was supported since Linux 3.7 pub fn set_tcp_fastopen(socket: &S) -> io::Result<()> { // https://lwn.net/Articles/508865/ // // The option value, qlen, specifies this server's limit on the size of the queue of TFO requests that have // not yet completed the three-way handshake (see the remarks on prevention of resource-exhaustion attacks above). // // It was recommended to be `5` in this document. // // But since mio's TcpListener sets backlogs to 1024, it would be nice to have 1024 slots for handshaking TFO requests. let queue: libc::c_int = 1024; unsafe { let ret = libc::setsockopt( socket.as_raw_fd(), libc::IPPROTO_TCP, libc::TCP_FASTOPEN, &queue as *const _ as *const libc::c_void, mem::size_of_val(&queue) as libc::socklen_t, ); if ret != 0 { let err = io::Error::last_os_error(); error!("set TCP_FASTOPEN error: {}", err); return Err(err); } } Ok(()) } fn create_mptcp_socket(bind_addr: &SocketAddr) -> io::Result { // https://www.kernel.org/doc/html/next/networking/mptcp.html unsafe { let family = match bind_addr { SocketAddr::V4(..) => libc::AF_INET, SocketAddr::V6(..) => libc::AF_INET6, }; let fd = libc::socket(family, libc::SOCK_STREAM, libc::IPPROTO_MPTCP); if fd < 0 { let err = io::Error::last_os_error(); return Err(err); } let socket = Socket::from_raw_fd(fd); socket.set_nonblocking(true)?; Ok(TcpSocket::from_raw_fd(socket.into_raw_fd())) } } /// Create a TCP socket for listening pub async fn create_inbound_tcp_socket(bind_addr: &SocketAddr, accept_opts: &AcceptOpts) -> io::Result { if accept_opts.tcp.mptcp { create_mptcp_socket(bind_addr) } else { match bind_addr { SocketAddr::V4(..) => TcpSocket::new_v4(), SocketAddr::V6(..) => TcpSocket::new_v6(), } } } /// Disable IP fragmentation #[inline] pub fn set_disable_ip_fragmentation(af: AddrFamily, socket: &S) -> io::Result<()> { // For Linux, IP_MTU_DISCOVER should be enabled for both IPv4 and IPv6 sockets // https://man7.org/linux/man-pages/man7/ip.7.html unsafe { let value: i32 = libc::IP_PMTUDISC_DO; let ret = libc::setsockopt( socket.as_raw_fd(), libc::IPPROTO_IP, libc::IP_MTU_DISCOVER, &value as *const _ as *const _, mem::size_of_val(&value) as libc::socklen_t, ); if ret < 0 { return Err(io::Error::last_os_error()); } if af == AddrFamily::Ipv6 { let value: i32 = libc::IP_PMTUDISC_DO; let ret = libc::setsockopt( socket.as_raw_fd(), libc::IPPROTO_IPV6, libc::IPV6_MTU_DISCOVER, &value as *const _ as *const _, mem::size_of_val(&value) as libc::socklen_t, ); if ret < 0 { return Err(io::Error::last_os_error()); } } } Ok(()) } /// Create a `UdpSocket` with specific address family #[inline] pub async fn create_outbound_udp_socket(af: AddrFamily, config: &ConnectOpts) -> io::Result { let bind_addr = match (af, config.bind_local_addr) { (AddrFamily::Ipv4, Some(SocketAddr::V4(addr))) => addr.into(), (AddrFamily::Ipv4, Some(SocketAddr::V6(addr))) => { // Map IPv6 bind_local_addr to IPv4 if AF is IPv4 match addr.ip().to_ipv4_mapped() { Some(addr) => SocketAddr::new(addr.into(), 0), None => return Err(io::Error::new(ErrorKind::InvalidInput, "Invalid IPv6 address")), } } (AddrFamily::Ipv6, Some(SocketAddr::V6(addr))) => addr.into(), (AddrFamily::Ipv6, Some(SocketAddr::V4(addr))) => { // Map IPv4 bind_local_addr to IPv6 if AF is IPv6 SocketAddr::new(addr.ip().to_ipv6_mapped().into(), 0) } (AddrFamily::Ipv4, ..) => SocketAddr::new(Ipv4Addr::UNSPECIFIED.into(), 0), (AddrFamily::Ipv6, ..) => SocketAddr::new(Ipv6Addr::UNSPECIFIED.into(), 0), }; bind_outbound_udp_socket(&bind_addr, config).await } /// Create a `UdpSocket` binded to `bind_addr` pub async fn bind_outbound_udp_socket(bind_addr: &SocketAddr, config: &ConnectOpts) -> io::Result { let af = AddrFamily::from(bind_addr); let socket = if af != AddrFamily::Ipv6 { UdpSocket::bind(bind_addr).await? } else { let socket = Socket::new(Domain::for_address(*bind_addr), Type::DGRAM, Some(Protocol::UDP))?; socket_bind_dual_stack(&socket, bind_addr, false)?; // UdpSocket::from_std requires socket to be non-blocked socket.set_nonblocking(true)?; UdpSocket::from_std(socket.into())? }; if !config.udp.allow_fragmentation && let Err(err) = set_disable_ip_fragmentation(af, &socket) { warn!("failed to disable IP fragmentation, error: {}", err); } // Any traffic except localhost should be protected // This is a workaround for VPNService #[cfg(target_os = "android")] android::vpn_protect(&socket, config).await?; // Set SO_MARK for mark-based routing on Linux (since 2.6.25) // NOTE: This will require CAP_NET_ADMIN capability (root in most cases) if let Some(mark) = config.fwmark { let ret = unsafe { libc::setsockopt( socket.as_raw_fd(), libc::SOL_SOCKET, libc::SO_MARK, &mark as *const _ as *const _, mem::size_of_val(&mark) as libc::socklen_t, ) }; if ret != 0 { let err = io::Error::last_os_error(); error!("set SO_MARK error: {}", err); return Err(err); } } // Set SO_BINDTODEVICE for binding to a specific interface if let Some(ref iface) = config.bind_interface { set_bindtodevice(&socket, iface)?; } Ok(socket) } fn set_bindtodevice(socket: &S, iface: &str) -> io::Result<()> { let iface_bytes = iface.as_bytes(); unsafe { let ret = libc::setsockopt( socket.as_raw_fd(), libc::SOL_SOCKET, libc::SO_BINDTODEVICE, iface_bytes.as_ptr() as *const _ as *const libc::c_void, iface_bytes.len() as libc::socklen_t, ); if ret != 0 { let err = io::Error::last_os_error(); error!("set SO_BINDTODEVICE error: {}", err); return Err(err); } } Ok(()) } #[cfg(target_os = "android")] mod android { use std::{ io::{self, ErrorKind}, os::unix::io::{AsRawFd, RawFd}, path::Path, time::Duration, }; use tokio::{io::AsyncReadExt, time}; use super::super::uds::UnixStream; use super::ConnectOpts; /// This is a RPC for Android to `protect()` socket for connecting to remote servers /// /// https://developer.android.com/reference/android/net/VpnService#protect(java.net.Socket) /// /// More detail could be found in [shadowsocks-android](https://github.com/shadowsocks/shadowsocks-android) project. async fn send_vpn_protect_uds>(protect_path: P, fd: RawFd) -> io::Result<()> { let mut stream = UnixStream::connect(protect_path).await?; // send fds let dummy: [u8; 1] = [1]; let fds: [RawFd; 1] = [fd]; stream.send_with_fd(&dummy, &fds).await?; // receive the return value let mut response = [0; 1]; stream.read_exact(&mut response).await?; if response[0] == 0xFF { return Err(io::Error::other("protect() failed")); } Ok(()) } /// Try to run VPNService#protect on Android /// /// https://developer.android.com/reference/android/net/VpnService#protect(java.net.Socket) pub async fn vpn_protect(socket: &S, opts: &ConnectOpts) -> io::Result<()> where S: AsRawFd + Send + Sync + 'static, { // shadowsocks-android uses a Unix domain socket to communicate with the VPNService#protect if let Some(ref path) = opts.vpn_protect_path { // RPC calls to `VpnService.protect()` // Timeout in 3 seconds like shadowsocks-libev match time::timeout(Duration::from_secs(3), send_vpn_protect_uds(path, socket.as_raw_fd())).await { Ok(Ok(..)) => {} Ok(Err(err)) => return Err(err), Err(..) => return Err(io::Error::new(ErrorKind::TimedOut, "protect() timeout")), } } // Customized SocketProtect if let Some(ref protect) = opts.vpn_socket_protect { protect.protect(socket.as_raw_fd())?; } Ok(()) } } static SUPPORT_BATCH_SEND_RECV_MSG: AtomicBool = AtomicBool::new(true); fn recvmsg_fallback(sock: &S, msg: &mut BatchRecvMessage<'_>) -> io::Result<()> { let mut hdr: libc::msghdr = unsafe { mem::zeroed() }; let addr_storage = SockAddrStorage::zeroed(); let addr_len = addr_storage.size_of() as libc::socklen_t; let sock_addr = unsafe { SockAddr::new(addr_storage, addr_len) }; hdr.msg_name = sock_addr.as_ptr() as *mut _; hdr.msg_namelen = sock_addr.len() as _; hdr.msg_iov = msg.data.as_ptr() as *mut _; hdr.msg_iovlen = msg.data.len() as _; let ret = unsafe { libc::recvmsg(sock.as_raw_fd(), &mut hdr as *mut _, 0) }; if ret < 0 { return Err(io::Error::last_os_error()); } msg.addr = sock_addr.as_socket().expect("SockAddr.as_socket"); msg.data_len = ret as usize; Ok(()) } pub fn batch_recvmsg(sock: &S, msgs: &mut [BatchRecvMessage<'_>]) -> io::Result { if msgs.is_empty() { return Ok(0); } if !SUPPORT_BATCH_SEND_RECV_MSG.load(Ordering::Relaxed) { recvmsg_fallback(sock, &mut msgs[0])?; return Ok(1); } let mut vec_msg_name = Vec::with_capacity(msgs.len()); let mut vec_msg_hdr = Vec::with_capacity(msgs.len()); for msg in msgs.iter_mut() { let mut hdr: libc::mmsghdr = unsafe { mem::zeroed() }; let addr_storage = SockAddrStorage::zeroed(); let addr_len = addr_storage.size_of() as libc::socklen_t; vec_msg_name.push(unsafe { SockAddr::new(addr_storage, addr_len) }); let sock_addr = vec_msg_name.last_mut().unwrap(); hdr.msg_hdr.msg_name = sock_addr.as_ptr() as *mut _; hdr.msg_hdr.msg_namelen = sock_addr.len() as _; hdr.msg_hdr.msg_iov = msg.data.as_ptr() as *mut _; hdr.msg_hdr.msg_iovlen = msg.data.len() as _; vec_msg_hdr.push(hdr); } let ret = unsafe { libc::recvmmsg( sock.as_raw_fd(), vec_msg_hdr.as_mut_ptr(), vec_msg_hdr.len() as _, 0, ptr::null_mut(), ) }; if ret < 0 { let err = io::Error::last_os_error(); if let Some(libc::ENOSYS) = err.raw_os_error() { debug!("recvmmsg is not supported, fallback to recvmsg, error: {:?}", err); SUPPORT_BATCH_SEND_RECV_MSG.store(false, Ordering::Relaxed); recvmsg_fallback(sock, &mut msgs[0])?; return Ok(1); } return Err(err); } for idx in 0..ret as usize { let msg = &mut msgs[idx]; let hdr = &vec_msg_hdr[idx]; let name = &vec_msg_name[idx]; msg.addr = name.as_socket().expect("SockAddr.as_socket"); msg.data_len = hdr.msg_len as usize; } Ok(ret as usize) } fn sendmsg_fallback(sock: &S, msg: &mut BatchSendMessage<'_>) -> io::Result<()> { let mut hdr: libc::msghdr = unsafe { mem::zeroed() }; let sock_addr = msg.addr.map(SockAddr::from); if let Some(ref sa) = sock_addr { hdr.msg_name = sa.as_ptr() as *mut _; hdr.msg_namelen = sa.len() as _; } hdr.msg_iov = msg.data.as_ptr() as *mut _; hdr.msg_iovlen = msg.data.len() as _; let ret = unsafe { libc::sendmsg(sock.as_raw_fd(), &hdr as *const _, 0) }; if ret < 0 { return Err(io::Error::last_os_error()); } msg.data_len = ret as usize; Ok(()) } pub fn batch_sendmsg(sock: &S, msgs: &mut [BatchSendMessage<'_>]) -> io::Result { if msgs.is_empty() { return Ok(0); } if !SUPPORT_BATCH_SEND_RECV_MSG.load(Ordering::Relaxed) { sendmsg_fallback(sock, &mut msgs[0])?; return Ok(1); } let mut vec_msg_name = Vec::with_capacity(msgs.len()); let mut vec_msg_hdr = Vec::with_capacity(msgs.len()); for msg in msgs.iter_mut() { let mut hdr: libc::mmsghdr = unsafe { mem::zeroed() }; if let Some(addr) = msg.addr { vec_msg_name.push(SockAddr::from(addr)); let sock_addr = vec_msg_name.last_mut().unwrap(); hdr.msg_hdr.msg_name = sock_addr.as_ptr() as *mut _; hdr.msg_hdr.msg_namelen = sock_addr.len() as _; } hdr.msg_hdr.msg_iov = msg.data.as_ptr() as *mut _; hdr.msg_hdr.msg_iovlen = msg.data.len() as _; vec_msg_hdr.push(hdr); } let ret = unsafe { libc::sendmmsg(sock.as_raw_fd(), vec_msg_hdr.as_mut_ptr(), vec_msg_hdr.len() as _, 0) }; if ret < 0 { let err = io::Error::last_os_error(); if let Some(libc::ENOSYS) = err.raw_os_error() { debug!("sendmmsg is not supported, fallback to sendmsg, error: {:?}", err); SUPPORT_BATCH_SEND_RECV_MSG.store(false, Ordering::Relaxed); sendmsg_fallback(sock, &mut msgs[0])?; return Ok(1); } return Err(err); } for idx in 0..ret as usize { let msg = &mut msgs[idx]; let hdr = &vec_msg_hdr[idx]; msg.data_len = hdr.msg_len as usize; } Ok(ret as usize) } ================================================ FILE: crates/shadowsocks/src/net/sys/unix/mod.rs ================================================ use std::{io, net::SocketAddr, os::fd::AsFd}; use cfg_if::cfg_if; use log::warn; use socket2::{Domain, Protocol, SockRef, Socket, TcpKeepalive, Type}; use tokio::net::UdpSocket; use crate::net::{AcceptOpts, AddrFamily, ConnectOpts, TcpSocketOpts, is_dual_stack_addr, sys::socket_bind_dual_stack}; cfg_if! { if #[cfg(any(target_os = "linux", target_os = "android"))] { mod linux; pub use self::linux::*; } else if #[cfg(any(target_os = "freebsd", target_os = "openbsd", target_os = "netbsd", target_os = "dragonfly", target_os = "macos", target_os = "ios", target_os = "watchos", target_os = "tvos"))] { mod bsd; pub use self::bsd::*; } else { mod others; pub use self::others::*; } } pub mod uds; /// Create a `UdpSocket` binded to `addr` pub async fn create_inbound_udp_socket(addr: &SocketAddr, ipv6_only: bool) -> io::Result { let set_dual_stack = is_dual_stack_addr(addr); let socket = if !set_dual_stack { UdpSocket::bind(addr).await? } else { let socket = Socket::new(Domain::for_address(*addr), Type::DGRAM, Some(Protocol::UDP))?; socket_bind_dual_stack(&socket, addr, ipv6_only)?; // UdpSocket::from_std requires socket to be non-blocked socket.set_nonblocking(true)?; UdpSocket::from_std(socket.into())? }; let addr_family = match addr { SocketAddr::V4(..) => AddrFamily::Ipv4, SocketAddr::V6(..) => AddrFamily::Ipv6, }; if let Err(err) = set_disable_ip_fragmentation(addr_family, &socket) { warn!("failed to disable IP fragmentation, error: {}", err); } Ok(socket) } #[inline] fn set_tcp_keepalive(socket: &Socket, tcp: &TcpSocketOpts) -> io::Result<()> { if let Some(intv) = tcp.keepalive { #[allow(unused_mut)] let mut keepalive = TcpKeepalive::new().with_time(intv); #[cfg(any( target_os = "freebsd", target_os = "fuchsia", target_os = "linux", target_os = "netbsd", target_vendor = "apple", ))] { keepalive = keepalive.with_interval(intv); } cfg_if! { if #[cfg(any(target_os = "linux", target_os = "android"))] { // FIXME: Linux Kernel doesn't support setting TCP Keep Alive. (MPTCP) // SO_KEEPALIVE works fine. But TCP_KEEPIDLE, TCP_KEEPINTV are not supported. // https://github.com/multipath-tcp/mptcp_net-next/issues/383 // https://github.com/multipath-tcp/mptcp_net-next/issues/353 if let Err(err) = socket.set_tcp_keepalive(&keepalive) { log::debug!("set TCP keep-alive with time & interval failed with error: {:?}", err); // Try again without time & interval let keepalive = TcpKeepalive::new(); socket.set_tcp_keepalive(&keepalive)?; } } else { socket.set_tcp_keepalive(&keepalive)?; } } } Ok(()) } #[inline(always)] fn socket_call_warp(stream: &S, f: F) -> io::Result<()> where S: AsFd, F: FnOnce(&Socket) -> io::Result<()>, { let socket = SockRef::from(stream); f(&socket) } pub fn set_common_sockopt_after_connect(stream: &S, opts: &ConnectOpts) -> io::Result<()> where S: AsFd, { socket_call_warp(stream, |socket| set_common_sockopt_after_connect_impl(socket, opts)) } fn set_common_sockopt_after_connect_impl(socket: &Socket, opts: &ConnectOpts) -> io::Result<()> { if opts.tcp.nodelay { socket.set_tcp_nodelay(true)?; } set_tcp_keepalive(socket, &opts.tcp)?; Ok(()) } pub fn set_common_sockopt_after_accept(stream: &S, opts: &AcceptOpts) -> io::Result<()> where S: AsFd, { socket_call_warp(stream, |socket| set_common_sockopt_after_accept_impl(socket, opts)) } fn set_common_sockopt_after_accept_impl(socket: &Socket, opts: &AcceptOpts) -> io::Result<()> { if let Some(buf_size) = opts.tcp.send_buffer_size { socket.set_send_buffer_size(buf_size as usize)?; } if let Some(buf_size) = opts.tcp.recv_buffer_size { socket.set_recv_buffer_size(buf_size as usize)?; } socket.set_tcp_nodelay(opts.tcp.nodelay)?; set_tcp_keepalive(socket, &opts.tcp)?; Ok(()) } ================================================ FILE: crates/shadowsocks/src/net/sys/unix/others.rs ================================================ use std::{ io::{self, ErrorKind}, net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr}, ops::{Deref, DerefMut}, os::fd::AsRawFd, pin::Pin, task::{self, Poll}, }; use pin_project::pin_project; use tokio::{ io::{AsyncRead, AsyncWrite, ReadBuf}, net::{TcpSocket, TcpStream as TokioTcpStream, UdpSocket}, }; use crate::net::{ AcceptOpts, AddrFamily, ConnectOpts, sys::{set_common_sockopt_after_connect, set_common_sockopt_for_connect}, }; /// A wrapper of `TcpStream` #[pin_project] pub struct TcpStream(#[pin] TokioTcpStream); impl TcpStream { pub async fn connect(addr: SocketAddr, opts: &ConnectOpts) -> io::Result { let socket = match addr { SocketAddr::V4(..) => TcpSocket::new_v4()?, SocketAddr::V6(..) => TcpSocket::new_v6()?, }; set_common_sockopt_for_connect(addr, &socket, opts)?; let stream = socket.connect(addr).await?; set_common_sockopt_after_connect(&stream, opts)?; Ok(TcpStream(stream)) } } impl Deref for TcpStream { type Target = TokioTcpStream; fn deref(&self) -> &Self::Target { &self.0 } } impl DerefMut for TcpStream { fn deref_mut(&mut self) -> &mut Self::Target { &mut self.0 } } impl AsyncRead for TcpStream { fn poll_read(self: Pin<&mut Self>, cx: &mut task::Context<'_>, buf: &mut ReadBuf<'_>) -> Poll> { self.project().0.poll_read(cx, buf) } } impl AsyncWrite for TcpStream { fn poll_write(self: Pin<&mut Self>, cx: &mut task::Context<'_>, buf: &[u8]) -> Poll> { self.project().0.poll_write(cx, buf) } fn poll_flush(self: Pin<&mut Self>, cx: &mut task::Context<'_>) -> Poll> { self.project().0.poll_flush(cx) } fn poll_shutdown(self: Pin<&mut Self>, cx: &mut task::Context<'_>) -> Poll> { self.project().0.poll_shutdown(cx) } } /// Disable IP fragmentation #[inline] pub fn set_disable_ip_fragmentation(_af: AddrFamily, _socket: &S) -> io::Result<()> { Ok(()) } /// Create a `UdpSocket` with specific address family #[inline] pub async fn create_outbound_udp_socket(af: AddrFamily, config: &ConnectOpts) -> io::Result { let bind_addr = match (af, config.bind_local_addr) { (AddrFamily::Ipv4, Some(SocketAddr::V4(addr))) => addr.into(), (AddrFamily::Ipv4, Some(SocketAddr::V6(addr))) => { // Map IPv6 bind_local_addr to IPv4 if AF is IPv4 match addr.ip().to_ipv4_mapped() { Some(addr) => SocketAddr::new(IpAddr::from(addr), 0), None => return Err(io::Error::new(ErrorKind::InvalidInput, "Invalid IPv6 address")), } } (AddrFamily::Ipv6, Some(SocketAddr::V6(addr))) => addr.into(), (AddrFamily::Ipv6, Some(SocketAddr::V4(addr))) => { // Map IPv4 bind_local_addr to IPv6 if AF is IPv6 let ip_addr: IpAddr = addr.ip().to_ipv6_mapped().into(); SocketAddr::new(ip_addr, 0) } (AddrFamily::Ipv4, ..) => SocketAddr::new(Ipv4Addr::UNSPECIFIED.into(), 0), (AddrFamily::Ipv6, ..) => SocketAddr::new(Ipv6Addr::UNSPECIFIED.into(), 0), }; bind_outbound_udp_socket(&bind_addr, config).await } /// Create a `UdpSocket` binded to `bind_addr` pub async fn bind_outbound_udp_socket(bind_addr: &SocketAddr, _config: &ConnectOpts) -> io::Result { let af = AddrFamily::from(bind_addr); let socket = UdpSocket::bind(bind_addr).await?; let _ = set_disable_ip_fragmentation(af, &socket); Ok(socket) } /// Enable TCP Fast Open pub fn set_tcp_fastopen(_: &S) -> io::Result<()> { let err = io::Error::other("TFO is not supported in this platform"); Err(err) } /// Create a TCP socket for listening pub async fn create_inbound_tcp_socket(bind_addr: &SocketAddr, _accept_opts: &AcceptOpts) -> io::Result { match bind_addr { SocketAddr::V4(..) => TcpSocket::new_v4(), SocketAddr::V6(..) => TcpSocket::new_v6(), } } ================================================ FILE: crates/shadowsocks/src/net/sys/unix/uds.rs ================================================ //! Android specific features use std::{ io::{self, ErrorKind}, os::unix::io::RawFd, path::Path, pin::Pin, task::{Context, Poll}, }; use futures::{future, ready}; use pin_project::pin_project; use sendfd::{RecvWithFd, SendWithFd}; use tokio::{ io::{AsyncRead, AsyncWrite, Interest, ReadBuf}, net::{UnixListener as TokioUnixListener, UnixStream as TokioUnixStream, unix::SocketAddr}, }; /// A UnixStream supports transferring FDs between processes #[pin_project] pub struct UnixStream { #[pin] io: TokioUnixStream, } impl UnixStream { /// Connects to the socket named by `path`. pub async fn connect>(path: P) -> io::Result { TokioUnixStream::connect(path).await.map(|io| Self { io }) } fn poll_send_with_fd(&self, cx: &mut Context, buf: &[u8], fds: &[RawFd]) -> Poll> { loop { ready!(self.io.poll_write_ready(cx))?; match self.io.try_io(Interest::WRITABLE, || self.io.send_with_fd(buf, fds)) { // self.io.poll_write_ready indicates that writable event have been received by tokio, // so it is not a common case that sendto returns EAGAIN. Err(ref err) if err.kind() == ErrorKind::WouldBlock => {} x => return Poll::Ready(x), } } } /// Send data with file descriptors pub async fn send_with_fd(&mut self, buf: &[u8], fds: &[RawFd]) -> io::Result { future::poll_fn(|cx| self.poll_send_with_fd(cx, buf, fds)).await } fn poll_recv_with_fd( &self, cx: &mut Context, buf: &mut [u8], fds: &mut [RawFd], ) -> Poll> { loop { ready!(self.io.poll_read_ready(cx))?; match self.io.try_io(Interest::READABLE, || self.io.recv_with_fd(buf, fds)) { // self.io.poll_write_ready indicates that writable event have been received by tokio, // so it is not a common case that recvto returns EAGAIN. // // Just for double check. If EAGAIN actually returns, clear the readiness state. Err(ref err) if err.kind() == ErrorKind::WouldBlock => {} x => return Poll::Ready(x), } } } /// Recv data with file descriptors pub async fn recv_with_fd(&mut self, buf: &mut [u8], fds: &mut [RawFd]) -> io::Result<(usize, usize)> { future::poll_fn(|cx| self.poll_recv_with_fd(cx, buf, fds)).await } } impl AsyncRead for UnixStream { fn poll_read(self: Pin<&mut Self>, cx: &mut Context<'_>, buf: &mut ReadBuf<'_>) -> Poll> { self.project().io.poll_read(cx, buf) } } impl AsyncWrite for UnixStream { fn poll_write(self: Pin<&mut Self>, cx: &mut Context<'_>, buf: &[u8]) -> Poll> { self.project().io.poll_write(cx, buf) } fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { self.project().io.poll_flush(cx) } fn poll_shutdown(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { self.project().io.poll_shutdown(cx) } } /// A UnixListener supports transferring FDs between processes pub struct UnixListener { io: TokioUnixListener, } impl UnixListener { /// Creates a new `UnixListener` bound to the specified socket. pub fn bind>(path: P) -> io::Result { TokioUnixListener::bind(path).map(|io| Self { io }) } /// Accepts a new incoming connection to this listener. pub fn poll_accept(&self, cx: &mut Context<'_>) -> Poll> { let (stream, peer_addr) = ready!(self.io.poll_accept(cx))?; Ok((UnixStream { io: stream }, peer_addr)).into() } /// Accepts a new incoming connection to this listener. pub async fn accept(&self) -> io::Result<(UnixStream, SocketAddr)> { future::poll_fn(|cx| self.poll_accept(cx)).await } } ================================================ FILE: crates/shadowsocks/src/net/sys/windows/mod.rs ================================================ use std::{ cell::RefCell, collections::HashMap, ffi::{CStr, CString, OsString, c_void}, io::{self, ErrorKind}, mem, net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr}, os::windows::{ ffi::OsStringExt, io::{AsRawSocket, AsSocket, RawSocket}, }, pin::Pin, ptr, slice, task::{self, Poll}, time::{Duration, Instant}, }; use bytes::BytesMut; use log::{error, warn}; use pin_project::pin_project; use socket2::{Domain, Protocol, SockAddr, SockRef, Socket, TcpKeepalive, Type}; use tokio::{ io::{AsyncRead, AsyncWrite, ReadBuf}, net::{TcpSocket, TcpStream as TokioTcpStream, UdpSocket}, }; use tokio_tfo::TfoStream; use windows_sys::{ Win32::{ Foundation::{ERROR_BUFFER_OVERFLOW, ERROR_NO_DATA, ERROR_SUCCESS, FALSE}, NetworkManagement::IpHelper::{ GAA_FLAG_SKIP_ANYCAST, GAA_FLAG_SKIP_DNS_SERVER, GAA_FLAG_SKIP_MULTICAST, GAA_FLAG_SKIP_UNICAST, GetAdaptersAddresses, IP_ADAPTER_ADDRESSES_LH, if_nametoindex, }, Networking::WinSock::{ AF_UNSPEC, IP_MTU_DISCOVER, IP_PMTUDISC_DO, IP_UNICAST_IF, IPPROTO_IP, IPPROTO_IPV6, IPPROTO_TCP, IPV6_MTU_DISCOVER, IPV6_UNICAST_IF, SIO_UDP_CONNRESET, SOCKET, SOCKET_ERROR, TCP_FASTOPEN, WSAGetLastError, WSAIoctl, htonl, setsockopt, }, }, core::{BOOL, PCSTR}, }; use crate::net::{ AcceptOpts, AddrFamily, ConnectOpts, is_dual_stack_addr, sys::{set_common_sockopt_for_connect, socket_bind_dual_stack}, }; /// A `TcpStream` that supports TFO (TCP Fast Open) #[pin_project(project = TcpStreamProj)] pub enum TcpStream { Standard(#[pin] TokioTcpStream), FastOpen(#[pin] TfoStream), } impl TcpStream { pub async fn connect(addr: SocketAddr, opts: &ConnectOpts) -> io::Result { let socket = match addr { SocketAddr::V4(..) => TcpSocket::new_v4()?, SocketAddr::V6(..) => TcpSocket::new_v6()?, }; // Binds to a specific network interface (device) if let Some(ref iface) = opts.bind_interface { set_ip_unicast_if(&socket, &addr, iface)?; } set_common_sockopt_for_connect(addr, &socket, opts)?; if !opts.tcp.fastopen { // If TFO is not enabled, it just works like a normal TcpStream let stream = socket.connect(addr).await?; set_common_sockopt_after_connect(&stream, opts)?; return Ok(TcpStream::Standard(stream)); } let stream = TfoStream::connect_with_socket(socket, addr).await?; set_common_sockopt_after_connect(&stream, opts)?; Ok(TcpStream::FastOpen(stream)) } pub fn local_addr(&self) -> io::Result { match *self { TcpStream::Standard(ref s) => s.local_addr(), TcpStream::FastOpen(ref s) => s.local_addr(), } } pub fn peer_addr(&self) -> io::Result { match *self { TcpStream::Standard(ref s) => s.peer_addr(), TcpStream::FastOpen(ref s) => s.peer_addr(), } } pub fn nodelay(&self) -> io::Result { match *self { TcpStream::Standard(ref s) => s.nodelay(), TcpStream::FastOpen(ref s) => s.nodelay(), } } pub fn set_nodelay(&self, nodelay: bool) -> io::Result<()> { match *self { TcpStream::Standard(ref s) => s.set_nodelay(nodelay), TcpStream::FastOpen(ref s) => s.set_nodelay(nodelay), } } } impl AsRawSocket for TcpStream { fn as_raw_socket(&self) -> RawSocket { match *self { TcpStream::Standard(ref s) => s.as_raw_socket(), TcpStream::FastOpen(ref s) => s.as_raw_socket(), } } } impl AsyncRead for TcpStream { fn poll_read(self: Pin<&mut Self>, cx: &mut task::Context<'_>, buf: &mut ReadBuf<'_>) -> Poll> { match self.project() { TcpStreamProj::Standard(s) => s.poll_read(cx, buf), TcpStreamProj::FastOpen(s) => s.poll_read(cx, buf), } } } impl AsyncWrite for TcpStream { fn poll_write(self: Pin<&mut Self>, cx: &mut task::Context<'_>, buf: &[u8]) -> Poll> { match self.project() { TcpStreamProj::Standard(s) => s.poll_write(cx, buf), TcpStreamProj::FastOpen(s) => s.poll_write(cx, buf), } } fn poll_flush(self: Pin<&mut Self>, cx: &mut task::Context<'_>) -> Poll> { match self.project() { TcpStreamProj::Standard(s) => s.poll_flush(cx), TcpStreamProj::FastOpen(s) => s.poll_flush(cx), } } fn poll_shutdown(self: Pin<&mut Self>, cx: &mut task::Context<'_>) -> Poll> { match self.project() { TcpStreamProj::Standard(s) => s.poll_shutdown(cx), TcpStreamProj::FastOpen(s) => s.poll_shutdown(cx), } } } /// Enable `TCP_FASTOPEN` /// /// Program borrowed from /// https://social.msdn.microsoft.com/Forums/en-US/94d1fe8e-4f17-4b28-89eb-1ac776a2e134/how-to-create-tcp-fast-open-connections-with-winsock-?forum=windowsgeneraldevelopmentissues /// /// TCP_FASTOPEN document /// https://docs.microsoft.com/en-us/windows/win32/winsock/ipproto-tcp-socket-options /// /// TCP_FASTOPEN is supported since Windows 10 pub fn set_tcp_fastopen(socket: &S) -> io::Result<()> { let enable: u32 = 1; unsafe { let ret = setsockopt( socket.as_raw_socket() as SOCKET, IPPROTO_TCP, TCP_FASTOPEN, &enable as *const _ as PCSTR, mem::size_of_val(&enable) as i32, ); if ret == SOCKET_ERROR { let err = io::Error::from_raw_os_error(WSAGetLastError()); error!("set TCP_FASTOPEN error: {}", err); return Err(err); } } Ok(()) } /// Create a TCP socket for listening pub async fn create_inbound_tcp_socket(bind_addr: &SocketAddr, _accept_opts: &AcceptOpts) -> io::Result { match bind_addr { SocketAddr::V4(..) => TcpSocket::new_v4(), SocketAddr::V6(..) => TcpSocket::new_v6(), } } fn find_adapter_interface_index(addr: &SocketAddr, iface: &str) -> io::Result> { // https://learn.microsoft.com/en-us/windows/win32/api/iphlpapi/nf-iphlpapi-getadaptersaddresses let ip = addr.ip(); unsafe { let mut ip_adapter_addresses_buffer = BytesMut::with_capacity(15 * 1024); ip_adapter_addresses_buffer.set_len(15 * 1024); let mut ip_adapter_addresses_buffer_size: u32 = ip_adapter_addresses_buffer.len() as u32; loop { let ret = GetAdaptersAddresses( AF_UNSPEC as u32, GAA_FLAG_SKIP_UNICAST | GAA_FLAG_SKIP_ANYCAST | GAA_FLAG_SKIP_MULTICAST | GAA_FLAG_SKIP_DNS_SERVER, ptr::null(), ip_adapter_addresses_buffer.as_mut_ptr() as *mut _, &mut ip_adapter_addresses_buffer_size as *mut _, ); match ret { ERROR_SUCCESS => break, ERROR_BUFFER_OVERFLOW => { // resize buffer to ip_adapter_addresses_buffer_size ip_adapter_addresses_buffer.resize(ip_adapter_addresses_buffer_size as usize, 0); continue; } ERROR_NO_DATA => return Ok(None), _ => { let err = io::Error::other(format!("GetAdaptersAddresses failed with error: {}", ret)); return Err(err); } } } // IP_ADAPTER_ADDRESSES_LH is a linked-list let mut current_ip_adapter_address: *mut IP_ADAPTER_ADDRESSES_LH = ip_adapter_addresses_buffer.as_mut_ptr() as *mut _; while !current_ip_adapter_address.is_null() { let ip_adapter_address: &IP_ADAPTER_ADDRESSES_LH = &*current_ip_adapter_address; // Friendly Name let friendly_name_len: usize = libc::wcslen(ip_adapter_address.FriendlyName); let friendly_name_slice: &[u16] = slice::from_raw_parts(ip_adapter_address.FriendlyName, friendly_name_len); let friendly_name_os = OsString::from_wide(friendly_name_slice); // UTF-16 to UTF-8 if let Some(friendly_name) = friendly_name_os.to_str() && friendly_name == iface { match ip { IpAddr::V4(..) => return Ok(Some(ip_adapter_address.Anonymous1.Anonymous.IfIndex)), IpAddr::V6(..) => return Ok(Some(ip_adapter_address.Ipv6IfIndex)), } } // Adapter Name let adapter_name = CStr::from_ptr(ip_adapter_address.AdapterName as *mut _ as *const _); if adapter_name.to_bytes() == iface.as_bytes() { match ip { IpAddr::V4(..) => return Ok(Some(ip_adapter_address.Anonymous1.Anonymous.IfIndex)), IpAddr::V6(..) => return Ok(Some(ip_adapter_address.Ipv6IfIndex)), } } current_ip_adapter_address = ip_adapter_address.Next; } } Ok(None) } fn find_interface_index_cached(addr: &SocketAddr, iface: &str) -> io::Result { const INDEX_EXPIRE_DURATION: Duration = Duration::from_secs(5); thread_local! { static INTERFACE_INDEX_CACHE: RefCell> = RefCell::new(HashMap::new()); } let cache_index = INTERFACE_INDEX_CACHE.with(|cache| cache.borrow().get(iface).cloned()); if let Some((idx, insert_time)) = cache_index { // short-path, cache hit for most cases let now = Instant::now(); if now - insert_time < INDEX_EXPIRE_DURATION { return Ok(idx); } } // Get from API GetAdaptersAddresses let idx = match find_adapter_interface_index(addr, iface)? { Some(idx) => idx, None => unsafe { // Windows if_nametoindex requires a C-string for interface name let ifname = CString::new(iface).expect("iface"); // https://docs.microsoft.com/en-us/previous-versions/windows/hardware/drivers/ff553788(v=vs.85) let if_index = if_nametoindex(ifname.as_ptr() as PCSTR); if if_index == 0 { // If the if_nametoindex function fails and returns zero, it is not possible to determine an error code. error!("if_nametoindex {} fails", iface); return Err(io::Error::new(ErrorKind::InvalidInput, "invalid interface name")); } if_index }, }; INTERFACE_INDEX_CACHE.with(|cache| { cache.borrow_mut().insert(iface.to_owned(), (idx, Instant::now())); }); Ok(idx) } fn set_ip_unicast_if(socket: &S, addr: &SocketAddr, iface: &str) -> io::Result<()> { let handle = socket.as_raw_socket() as SOCKET; let if_index = find_interface_index_cached(addr, iface)?; unsafe { // https://docs.microsoft.com/en-us/windows/win32/winsock/ipproto-ip-socket-options let ret = match addr { SocketAddr::V4(..) => { // Interface index is in network byte order for IPPROTO_IP. let if_index = htonl(if_index); setsockopt( handle, IPPROTO_IP, IP_UNICAST_IF, &if_index as *const _ as PCSTR, mem::size_of_val(&if_index) as i32, ) } SocketAddr::V6(..) => { // Interface index is in host byte order for IPPROTO_IPV6. setsockopt( handle, IPPROTO_IPV6, IPV6_UNICAST_IF, &if_index as *const _ as PCSTR, mem::size_of_val(&if_index) as i32, ) } }; if ret == SOCKET_ERROR { let err = io::Error::from_raw_os_error(WSAGetLastError()); error!( "set IP_UNICAST_IF / IPV6_UNICAST_IF interface: {}, index: {}, error: {}", iface, if_index, err ); return Err(err); } } Ok(()) } fn disable_connection_reset(socket: &UdpSocket) -> io::Result<()> { let handle = socket.as_raw_socket() as SOCKET; unsafe { // Ignoring UdpSocket's WSAECONNRESET error // https://github.com/shadowsocks/shadowsocks-rust/issues/179 // https://stackoverflow.com/questions/30749423/is-winsock-error-10054-wsaeconnreset-normal-with-udp-to-from-localhost // // This is because `UdpSocket::recv_from` may return WSAECONNRESET // if you called `UdpSocket::send_to` a destination that is not existed (may be closed). // // It is not an error. Could be ignored completely. // We have to ignore it here because it will crash the server. let mut bytes_returned: u32 = 0; let enable: BOOL = FALSE; let ret = WSAIoctl( handle, SIO_UDP_CONNRESET, &enable as *const _ as *const c_void, mem::size_of_val(&enable) as u32, ptr::null_mut(), 0, &mut bytes_returned as *mut _, ptr::null_mut(), None, ); if ret == SOCKET_ERROR { use std::io::Error; // Error occurs let err_code = WSAGetLastError(); return Err(Error::from_raw_os_error(err_code)); } } Ok(()) } /// Disable IP fragmentation #[inline] pub fn set_disable_ip_fragmentation(af: AddrFamily, socket: &S) -> io::Result<()> { let handle = socket.as_raw_socket() as SOCKET; unsafe { // For Windows, IP_MTU_DISCOVER should be enabled for both IPv4 and IPv6 sockets // https://docs.microsoft.com/en-us/windows/win32/winsock/ipproto-ip-socket-options let value = IP_PMTUDISC_DO; let ret = setsockopt( handle, IPPROTO_IP, IP_MTU_DISCOVER, &value as *const _ as PCSTR, mem::size_of_val(&value) as i32, ); if ret == SOCKET_ERROR { let err = io::Error::from_raw_os_error(WSAGetLastError()); return Err(err); } if af == AddrFamily::Ipv6 { let value = IP_PMTUDISC_DO; let ret = setsockopt( handle, IPPROTO_IPV6, IPV6_MTU_DISCOVER, &value as *const _ as PCSTR, mem::size_of_val(&value) as i32, ); if ret == SOCKET_ERROR { let err = io::Error::from_raw_os_error(WSAGetLastError()); return Err(err); } } } Ok(()) } /// Create a `UdpSocket` binded to `addr` /// /// It also disables `WSAECONNRESET` for UDP socket pub async fn create_inbound_udp_socket(addr: &SocketAddr, ipv6_only: bool) -> io::Result { let set_dual_stack = is_dual_stack_addr(addr); let socket = if !set_dual_stack { UdpSocket::bind(addr).await? } else { let socket = Socket::new(Domain::for_address(*addr), Type::DGRAM, Some(Protocol::UDP))?; socket_bind_dual_stack(&socket, addr, ipv6_only)?; // UdpSocket::from_std requires socket to be non-blocked socket.set_nonblocking(true)?; UdpSocket::from_std(socket.into())? }; let addr_family = match addr { SocketAddr::V4(..) => AddrFamily::Ipv4, SocketAddr::V6(..) => AddrFamily::Ipv6, }; if let Err(err) = set_disable_ip_fragmentation(addr_family, &socket) { warn!("failed to disable IP fragmentation, error: {}", err); } disable_connection_reset(&socket)?; Ok(socket) } /// Create a `UdpSocket` for connecting to `addr` #[inline(always)] pub async fn create_outbound_udp_socket(af: AddrFamily, opts: &ConnectOpts) -> io::Result { let bind_addr = match (af, opts.bind_local_addr) { (AddrFamily::Ipv4, Some(SocketAddr::V4(addr))) => addr.into(), (AddrFamily::Ipv4, Some(SocketAddr::V6(addr))) => { // Map IPv6 bind_local_addr to IPv4 if AF is IPv4 match addr.ip().to_ipv4_mapped() { Some(addr) => SocketAddr::new(addr.into(), 0), None => return Err(io::Error::new(ErrorKind::InvalidInput, "Invalid IPv6 address")), } } (AddrFamily::Ipv6, Some(SocketAddr::V6(addr))) => addr.into(), (AddrFamily::Ipv6, Some(SocketAddr::V4(addr))) => { // Map IPv4 bind_local_addr to IPv6 if AF is IPv6 SocketAddr::new(addr.ip().to_ipv6_mapped().into(), 0) } (AddrFamily::Ipv4, ..) => SocketAddr::new(Ipv4Addr::UNSPECIFIED.into(), 0), (AddrFamily::Ipv6, ..) => SocketAddr::new(Ipv6Addr::UNSPECIFIED.into(), 0), }; bind_outbound_udp_socket(&bind_addr, opts).await } /// Create a `UdpSocket` binded to `bind_addr` pub async fn bind_outbound_udp_socket(bind_addr: &SocketAddr, opts: &ConnectOpts) -> io::Result { let af = AddrFamily::from(bind_addr); let socket = Socket::new(Domain::for_address(*bind_addr), Type::DGRAM, Some(Protocol::UDP))?; if let Some(ref iface) = opts.bind_interface { set_ip_unicast_if(&socket, bind_addr, iface)?; } // bind() should be called after IP_UNICAST_IF if af != AddrFamily::Ipv6 { let bind_addr = SockAddr::from(*bind_addr); socket.bind(&bind_addr)?; } else { socket_bind_dual_stack(&socket, bind_addr, false)?; } socket.set_nonblocking(true)?; let socket = UdpSocket::from_std(socket.into())?; if !opts.udp.allow_fragmentation && let Err(err) = set_disable_ip_fragmentation(af, &socket) { warn!("failed to disable IP fragmentation, error: {}", err); } disable_connection_reset(&socket)?; Ok(socket) } #[inline(always)] fn socket_call_warp(stream: &S, f: F) -> io::Result<()> where S: AsSocket, F: FnOnce(&Socket) -> io::Result<()>, { let socket = SockRef::from(stream); f(&socket) } pub fn set_common_sockopt_after_connect(stream: &S, opts: &ConnectOpts) -> io::Result<()> where S: AsSocket, { socket_call_warp(stream, |socket| set_common_sockopt_after_connect_impl(socket, opts)) } fn set_common_sockopt_after_connect_impl(socket: &Socket, opts: &ConnectOpts) -> io::Result<()> { if opts.tcp.nodelay { socket.set_tcp_nodelay(true)?; } if let Some(intv) = opts.tcp.keepalive { let keepalive = TcpKeepalive::new().with_time(intv).with_interval(intv); socket.set_tcp_keepalive(&keepalive)?; } Ok(()) } pub fn set_common_sockopt_after_accept(stream: &S, opts: &AcceptOpts) -> io::Result<()> where S: AsSocket, { socket_call_warp(stream, |socket| set_common_sockopt_after_accept_impl(socket, opts)) } fn set_common_sockopt_after_accept_impl(socket: &Socket, opts: &AcceptOpts) -> io::Result<()> { if let Some(buf_size) = opts.tcp.send_buffer_size { socket.set_send_buffer_size(buf_size as usize)?; } if let Some(buf_size) = opts.tcp.recv_buffer_size { socket.set_recv_buffer_size(buf_size as usize)?; } socket.set_tcp_nodelay(opts.tcp.nodelay)?; if let Some(intv) = opts.tcp.keepalive { let keepalive = TcpKeepalive::new().with_time(intv).with_interval(intv); socket.set_tcp_keepalive(&keepalive)?; } Ok(()) } ================================================ FILE: crates/shadowsocks/src/net/tcp.rs ================================================ //! TcpStream wrappers that supports connecting with options #[cfg(unix)] use std::os::unix::io::{AsRawFd, RawFd}; #[cfg(windows)] use std::os::windows::io::{AsRawSocket, RawSocket}; use std::{ io, net::SocketAddr, ops::{Deref, DerefMut}, pin::Pin, task::{self, Poll}, }; use futures::{future, ready}; use pin_project::pin_project; use tokio::{ io::{AsyncRead, AsyncWrite, ReadBuf}, net::{TcpListener as TokioTcpListener, TcpStream as TokioTcpStream}, }; use crate::{ServerAddr, context::Context, relay::socks5::Address}; use super::{ AcceptOpts, ConnectOpts, is_dual_stack_addr, sys::{ TcpStream as SysTcpStream, create_inbound_tcp_socket, set_common_sockopt_after_accept, set_tcp_fastopen, socket_bind_dual_stack, }, }; /// TcpStream for outbound connections #[pin_project] pub struct TcpStream(#[pin] SysTcpStream); impl TcpStream { /// Connects to address pub async fn connect_with_opts(addr: &SocketAddr, opts: &ConnectOpts) -> io::Result { // tcp_stream_connect(addr, opts).await.map(TcpStream) SysTcpStream::connect(*addr, opts).await.map(TcpStream) } /// Connects shadowsocks server pub async fn connect_server_with_opts( context: &Context, addr: &ServerAddr, opts: &ConnectOpts, ) -> io::Result { let stream = match *addr { ServerAddr::SocketAddr(ref addr) => SysTcpStream::connect(*addr, opts).await?, ServerAddr::DomainName(ref domain, port) => { lookup_then_connect!(context, domain, port, |addr| { SysTcpStream::connect(addr, opts).await })? .1 } }; Ok(Self(stream)) } /// Connects proxy remote target pub async fn connect_remote_with_opts(context: &Context, addr: &Address, opts: &ConnectOpts) -> io::Result { let stream = match *addr { Address::SocketAddress(ref addr) => SysTcpStream::connect(*addr, opts).await?, Address::DomainNameAddress(ref domain, port) => { lookup_then_connect!(context, domain, port, |addr| { SysTcpStream::connect(addr, opts).await })? .1 } }; Ok(Self(stream)) } /// Returns the local address that this stream is bound to. pub fn local_addr(&self) -> io::Result { self.0.local_addr() } /// Returns the remote address that this stream is connected to. pub fn peer_addr(&self) -> io::Result { self.0.peer_addr() } /// Gets the value of the `TCP_NODELAY` option on this socket. pub fn nodelay(&self) -> io::Result { self.0.nodelay() } /// Sets the value of the `TCP_NODELAY` option on this socket. pub fn set_nodelay(&self, nodelay: bool) -> io::Result<()> { self.0.set_nodelay(nodelay) } } impl AsyncRead for TcpStream { fn poll_read(self: Pin<&mut Self>, cx: &mut task::Context<'_>, buf: &mut ReadBuf<'_>) -> Poll> { self.project().0.poll_read(cx, buf) } } impl AsyncWrite for TcpStream { fn poll_write(self: Pin<&mut Self>, cx: &mut task::Context<'_>, buf: &[u8]) -> Poll> { self.project().0.poll_write(cx, buf) } fn poll_flush(self: Pin<&mut Self>, cx: &mut task::Context<'_>) -> Poll> { self.project().0.poll_flush(cx) } fn poll_shutdown(self: Pin<&mut Self>, cx: &mut task::Context<'_>) -> Poll> { self.project().0.poll_shutdown(cx) } } /// `TcpListener` for accepting inbound connections #[derive(Debug)] pub struct TcpListener { inner: TokioTcpListener, accept_opts: AcceptOpts, } impl TcpListener { /// Creates a new TcpListener, which will be bound to the specified address. pub async fn bind_with_opts(addr: &SocketAddr, accept_opts: AcceptOpts) -> io::Result { let socket = create_inbound_tcp_socket(addr, &accept_opts).await?; if let Some(size) = accept_opts.tcp.send_buffer_size { socket.set_send_buffer_size(size)?; } if let Some(size) = accept_opts.tcp.recv_buffer_size { socket.set_recv_buffer_size(size)?; } // On platforms with Berkeley-derived sockets, this allows to quickly // rebind a socket, without needing to wait for the OS to clean up the // previous one. // // On Windows, this allows rebinding sockets which are actively in use, // which allows “socket hijacking”, so we explicitly don't set it here. // https://docs.microsoft.com/en-us/windows/win32/winsock/using-so-reuseaddr-and-so-exclusiveaddruse #[cfg(not(windows))] socket.set_reuseaddr(true)?; let set_dual_stack = is_dual_stack_addr(addr); if set_dual_stack { socket_bind_dual_stack(&socket, addr, accept_opts.ipv6_only)?; } else { socket.bind(*addr)?; } // mio's default backlog is 1024 let inner = socket.listen(1024)?; // Enable TFO if supported // macos requires TCP_FASTOPEN to be set after listen(), but other platform doesn't have this constraint if accept_opts.tcp.fastopen { set_tcp_fastopen(&inner)?; } Ok(Self { inner, accept_opts }) } /// Create a `TcpListener` from tokio's `TcpListener` pub fn from_listener(listener: TokioTcpListener, accept_opts: AcceptOpts) -> io::Result { // Enable TFO if supported // macos requires TCP_FASTOPEN to be set after listen(), but other platform doesn't have this constraint if accept_opts.tcp.fastopen { set_tcp_fastopen(&listener)?; } Ok(Self { inner: listener, accept_opts, }) } /// Polls to accept a new incoming connection to this listener. pub fn poll_accept(&self, cx: &mut task::Context<'_>) -> Poll> { let (stream, peer_addr) = ready!(self.inner.poll_accept(cx))?; set_common_sockopt_after_accept(&stream, &self.accept_opts)?; Poll::Ready(Ok((stream, peer_addr))) } /// Accept a new incoming connection to this listener pub async fn accept(&self) -> io::Result<(TokioTcpStream, SocketAddr)> { future::poll_fn(|cx| self.poll_accept(cx)).await } /// Unwraps and take the internal `TcpListener` pub fn into_inner(self) -> TokioTcpListener { self.inner } } impl Deref for TcpListener { type Target = TokioTcpListener; fn deref(&self) -> &Self::Target { &self.inner } } impl DerefMut for TcpListener { fn deref_mut(&mut self) -> &mut Self::Target { &mut self.inner } } impl From for TokioTcpListener { fn from(listener: TcpListener) -> Self { listener.inner } } #[cfg(unix)] impl AsRawFd for TcpStream { fn as_raw_fd(&self) -> RawFd { self.0.as_raw_fd() } } #[cfg(windows)] impl AsRawSocket for TcpStream { fn as_raw_socket(&self) -> RawSocket { self.0.as_raw_socket() } } ================================================ FILE: crates/shadowsocks/src/net/udp.rs ================================================ //! UDP socket wrappers #[cfg(any( target_os = "linux", target_os = "android", target_os = "macos", target_os = "ios", target_os = "freebsd" ))] use std::io::{ErrorKind, IoSlice, IoSliceMut}; use std::{ io, net::SocketAddr, ops::{Deref, DerefMut}, task::{Context as TaskContext, Poll}, }; #[cfg(any( target_os = "linux", target_os = "android", target_os = "macos", target_os = "ios", target_os = "freebsd" ))] use futures::future; use futures::ready; #[cfg(any( target_os = "linux", target_os = "android", target_os = "macos", target_os = "ios", target_os = "freebsd" ))] use tokio::io::Interest; use tokio::{io::ReadBuf, net::ToSocketAddrs}; use crate::{ServerAddr, context::Context, relay::socks5::Address}; use super::{ AcceptOpts, AddrFamily, ConnectOpts, sys::{bind_outbound_udp_socket, create_inbound_udp_socket, create_outbound_udp_socket}, }; /// Message struct for `batch_send` #[cfg(any( target_os = "linux", target_os = "android", target_os = "macos", target_os = "ios", target_os = "freebsd" ))] pub struct BatchSendMessage<'a> { /// Optional target address pub addr: Option, /// Data to be transmitted pub data: &'a [IoSlice<'a>], /// Output result. The number of bytes sent by `batch_send` pub data_len: usize, } /// Message struct for `batch_recv` #[cfg(any( target_os = "linux", target_os = "android", target_os = "macos", target_os = "ios", target_os = "freebsd" ))] pub struct BatchRecvMessage<'a> { /// Peer address pub addr: SocketAddr, /// Data buffer for receiving pub data: &'a mut [IoSliceMut<'a>], /// Output result. The number of bytes received by `batch_recv` pub data_len: usize, } #[inline] fn make_mtu_error(packet_size: usize, mtu: usize) -> io::Error { io::Error::other(format!("UDP packet {} > MTU {}", packet_size, mtu)) } /// Wrappers for outbound `UdpSocket` #[derive(Debug)] pub struct UdpSocket { socket: tokio::net::UdpSocket, mtu: Option, } impl UdpSocket { /// Connects to shadowsocks server pub async fn connect_server_with_opts( context: &Context, addr: &ServerAddr, opts: &ConnectOpts, ) -> io::Result { let socket = match *addr { ServerAddr::SocketAddr(ref remote_addr) => { let socket = create_outbound_udp_socket(From::from(remote_addr), opts).await?; socket.connect(remote_addr).await?; socket } ServerAddr::DomainName(ref dname, port) => { lookup_then!(context, dname, port, |remote_addr| { let s = create_outbound_udp_socket(From::from(&remote_addr), opts).await?; s.connect(remote_addr).await.map(|_| s) })? .1 } }; Ok(Self { socket, mtu: opts.udp.mtu, }) } /// Connects to proxy target pub async fn connect_remote_with_opts(context: &Context, addr: &Address, opts: &ConnectOpts) -> io::Result { let socket = match *addr { Address::SocketAddress(ref remote_addr) => { let socket = create_outbound_udp_socket(From::from(remote_addr), opts).await?; socket.connect(remote_addr).await?; socket } Address::DomainNameAddress(ref dname, port) => { lookup_then!(context, dname, port, |remote_addr| { let s = create_outbound_udp_socket(From::from(&remote_addr), opts).await?; s.connect(remote_addr).await.map(|_| s) })? .1 } }; Ok(Self { socket, mtu: opts.udp.mtu, }) } /// Connects to shadowsocks server pub async fn connect_with_opts(addr: &SocketAddr, opts: &ConnectOpts) -> io::Result { let socket = create_outbound_udp_socket(From::from(addr), opts).await?; socket.connect(addr).await?; Ok(Self { socket, mtu: opts.udp.mtu, }) } /// Binds to a specific address with opts pub async fn connect_any_with_opts>(af: AF, opts: &ConnectOpts) -> io::Result { create_outbound_udp_socket(af.into(), opts).await.map(|socket| Self { socket, mtu: opts.udp.mtu, }) } /// Binds to a specific address as an outbound socket #[inline] pub async fn bind(addr: &SocketAddr) -> io::Result { Self::bind_with_opts(addr, &ConnectOpts::default()).await } /// Binds to a specific address with opts as an outbound socket pub async fn bind_with_opts(addr: &SocketAddr, opts: &ConnectOpts) -> io::Result { bind_outbound_udp_socket(addr, opts).await.map(|socket| Self { socket, mtu: opts.udp.mtu, }) } /// Binds to a specific address (inbound) #[inline] pub async fn listen(addr: &SocketAddr) -> io::Result { Self::listen_with_opts(addr, AcceptOpts::default()).await } /// Binds to a specific address (inbound) pub async fn listen_with_opts(addr: &SocketAddr, opts: AcceptOpts) -> io::Result { let socket = create_inbound_udp_socket(addr, opts.ipv6_only).await?; Ok(Self { socket, mtu: opts.udp.mtu, }) } /// Wrapper of `UdpSocket::poll_send` pub fn poll_send(&self, cx: &mut TaskContext<'_>, buf: &[u8]) -> Poll> { // Check MTU if let Some(mtu) = self.mtu && buf.len() > mtu { return Err(make_mtu_error(buf.len(), mtu)).into(); } self.socket.poll_send(cx, buf) } /// Wrapper of `UdpSocket::send` #[inline] pub async fn send(&self, buf: &[u8]) -> io::Result { // Check MTU if let Some(mtu) = self.mtu && buf.len() > mtu { return Err(make_mtu_error(buf.len(), mtu)); } self.socket.send(buf).await } /// Wrapper of `UdpSocket::poll_send_to` pub fn poll_send_to(&self, cx: &mut TaskContext<'_>, buf: &[u8], target: SocketAddr) -> Poll> { // Check MTU if let Some(mtu) = self.mtu && buf.len() > mtu { return Err(make_mtu_error(buf.len(), mtu)).into(); } self.socket.poll_send_to(cx, buf, target) } /// Wrapper of `UdpSocket::send_to` #[inline] pub async fn send_to(&self, buf: &[u8], target: A) -> io::Result { // Check MTU if let Some(mtu) = self.mtu && buf.len() > mtu { return Err(make_mtu_error(buf.len(), mtu)); } self.socket.send_to(buf, target).await } /// Wrapper of `UdpSocket::poll_recv` #[inline] pub fn poll_recv(&self, cx: &mut TaskContext<'_>, buf: &mut ReadBuf<'_>) -> Poll> { ready!(self.socket.poll_recv(cx, buf))?; if let Some(mtu) = self.mtu && buf.filled().len() > mtu { return Err(make_mtu_error(buf.filled().len(), mtu)).into(); } Ok(()).into() } /// Wrapper of `UdpSocket::recv` #[inline] pub async fn recv(&self, buf: &mut [u8]) -> io::Result { let n = self.socket.recv(buf).await?; if let Some(mtu) = self.mtu && n > mtu { return Err(make_mtu_error(n, mtu)); } Ok(n) } /// Wrapper of `UdpSocket::poll_recv_from` #[inline] pub fn poll_recv_from(&self, cx: &mut TaskContext<'_>, buf: &mut ReadBuf<'_>) -> Poll> { let addr = ready!(self.socket.poll_recv_from(cx, buf))?; if let Some(mtu) = self.mtu && buf.filled().len() > mtu { return Err(make_mtu_error(buf.filled().len(), mtu)).into(); } Ok(addr).into() } /// Wrapper of `UdpSocket::recv` #[inline] pub async fn recv_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> { let (n, addr) = self.socket.recv_from(buf).await?; if let Some(mtu) = self.mtu && n > mtu { return Err(make_mtu_error(n, mtu)); } Ok((n, addr)) } /// Batch send packets #[cfg(any( target_os = "linux", target_os = "android", target_os = "macos", target_os = "ios", target_os = "freebsd" ))] pub fn poll_batch_send( &self, cx: &mut TaskContext<'_>, msgs: &mut [BatchSendMessage<'_>], ) -> Poll> { use super::sys::batch_sendmsg; loop { ready!(self.socket.poll_send_ready(cx))?; match self .socket .try_io(Interest::WRITABLE, || batch_sendmsg(&self.socket, msgs)) { Ok(n) => return Ok(n).into(), Err(ref err) if err.kind() == ErrorKind::WouldBlock => {} Err(err) => return Err(err).into(), } } } /// Batch send packets #[cfg(any( target_os = "linux", target_os = "android", target_os = "macos", target_os = "ios", target_os = "freebsd" ))] pub async fn batch_send(&self, msgs: &mut [BatchSendMessage<'_>]) -> io::Result { future::poll_fn(|cx| self.poll_batch_send(cx, msgs)).await } /// Batch recv packets #[cfg(any( target_os = "linux", target_os = "android", target_os = "ios", target_os = "macos", target_os = "freebsd" ))] pub fn poll_batch_recv( &self, cx: &mut TaskContext<'_>, msgs: &mut [BatchRecvMessage<'_>], ) -> Poll> { use super::sys::batch_recvmsg; loop { ready!(self.socket.poll_recv_ready(cx))?; match self .socket .try_io(Interest::READABLE, || batch_recvmsg(&self.socket, msgs)) { Ok(n) => return Ok(n).into(), Err(ref err) if err.kind() == ErrorKind::WouldBlock => {} Err(err) => return Err(err).into(), } } } /// Batch recv packets #[cfg(any( target_os = "linux", target_os = "android", target_os = "macos", target_os = "ios", target_os = "freebsd" ))] pub async fn batch_recv(&self, msgs: &mut [BatchRecvMessage<'_>]) -> io::Result { future::poll_fn(|cx| self.poll_batch_recv(cx, msgs)).await } } impl Deref for UdpSocket { type Target = tokio::net::UdpSocket; fn deref(&self) -> &Self::Target { &self.socket } } impl DerefMut for UdpSocket { fn deref_mut(&mut self) -> &mut Self::Target { &mut self.socket } } impl From for UdpSocket { fn from(socket: tokio::net::UdpSocket) -> Self { Self { socket, mtu: None } } } impl From for tokio::net::UdpSocket { fn from(s: UdpSocket) -> Self { s.socket } } #[cfg(unix)] impl std::os::fd::AsRawFd for UdpSocket { fn as_raw_fd(&self) -> std::os::fd::RawFd { self.socket.as_raw_fd() } } #[cfg(unix)] impl std::os::fd::AsFd for UdpSocket { fn as_fd(&self) -> std::os::fd::BorrowedFd<'_> { self.socket.as_fd() } } #[cfg(windows)] impl std::os::windows::io::AsRawSocket for UdpSocket { fn as_raw_socket(&self) -> std::os::windows::io::RawSocket { self.socket.as_raw_socket() } } #[cfg(windows)] impl std::os::windows::io::AsSocket for UdpSocket { fn as_socket(&self) -> std::os::windows::io::BorrowedSocket<'_> { self.socket.as_socket() } } ================================================ FILE: crates/shadowsocks/src/plugin/mod.rs ================================================ //! Plugin (SIP003) //! //! ```plain //! +------------+ +---------------------------+ //! | SS Client +-- Local Loopback --+ Plugin Client (Tunnel) +--+ //! +------------+ +---------------------------+ | //! | //! Public Internet (Obfuscated/Transformed traffic) ==> | //! | //! +------------+ +---------------------------+ | //! | SS Server +-- Local Loopback --+ Plugin Server (Tunnel) +--+ //! +------------+ +---------------------------+ //! ``` use std::{ io, net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr, TcpListener}, process::ExitStatus, time::{Duration, Instant}, }; use log::{debug, error}; use tokio::{net::TcpStream, process::Child, time}; use crate::config::{Mode, ServerAddr}; mod obfs_proxy; mod ss_plugin; /// Config for plugin #[derive(Debug, Clone)] pub struct PluginConfig { pub plugin: String, pub plugin_opts: Option, pub plugin_args: Vec, pub plugin_mode: Mode, } /// Mode of Plugin #[derive(Debug, Clone, Copy)] pub enum PluginMode { /// Server's Plugin /// /// ```plain /// LOCAL -> PLUGIN -> SERVER -> REMOTE /// ``` /// /// Plugin listens to the inbound address of server Server, /// Local's Plugin /// /// ```plain /// CLIENT -> LOCAL -> PLUGIN -> SERVER -> ... /// ``` /// /// Plugin sends data to the outbound address of server Client, } /// A shadowsocks SIP004 Plugin #[derive(Debug)] pub struct Plugin { process: Child, local_addr: SocketAddr, mode: Mode, } impl Plugin { /// Start a plugin subprocess /// /// `PluginMode::Client`: Plugin listens to `local_addr` and send data to `remote_addr`, client should send data to `local_addr` /// `PluginMode::Server`: Plugin listens to `remote_addr` and send data to `local_addr`, server should listen to `local_addr` pub fn start(c: &PluginConfig, remote_addr: &ServerAddr, mode: PluginMode) -> io::Result { let loop_ip = match remote_addr { ServerAddr::SocketAddr(sa) => match sa.ip() { IpAddr::V4(..) => Ipv4Addr::LOCALHOST.into(), IpAddr::V6(..) => Ipv6Addr::LOCALHOST.into(), }, ServerAddr::DomainName(..) => Ipv4Addr::LOCALHOST.into(), }; let local_addr = get_local_port(loop_ip)?; match start_plugin(c, remote_addr, &local_addr, mode) { Err(err) => { error!( "failed to start plugin \"{}\" for server {}, err: {}", c.plugin, remote_addr, err ); Err(err) } Ok(process) => { match mode { PluginMode::Client => { debug!( "started plugin \"{}\" on {} <-> {} ({}) {}", c.plugin, local_addr, remote_addr, process.id().unwrap_or(0), c.plugin_mode ); } PluginMode::Server => { debug!( "started plugin \"{}\" on {} <-> {} ({}) {}", c.plugin, remote_addr, local_addr, process.id().unwrap_or(0), c.plugin_mode ); } } Ok(Self { process, local_addr, mode: c.plugin_mode, }) } } } /// Join until plugin exits pub async fn join(mut self) -> io::Result { self.process.wait().await } /// Check if plugin have been started pub async fn wait_started(&self, timeout: Duration) -> bool { // Only test started with TCP connect() // XXX: Is there an easy way to test if UDP port was listening? (no ICMP!) if !self.mode.enable_tcp() { return true; } let start_time = Instant::now(); loop { let now_time = Instant::now(); let elapsed_time = now_time - start_time; if elapsed_time >= timeout { return false; } let remain_time = timeout - elapsed_time; match time::timeout(remain_time, TcpStream::connect(self.local_addr)).await { Ok(Ok(..)) => { return true; } Ok(Err(..)) => {} Err(..) => { return false; } } } } /// Get listen address of plugin pub fn local_addr(&self) -> SocketAddr { self.local_addr } } impl Drop for Plugin { // NOTE: Even we have set `Command.kill_on_drop(true)`, processes may not be killed when `Child` handles are dropped. // https://github.com/tokio-rs/tokio/issues/2685 #[cfg(not(unix))] fn drop(&mut self) { debug!( "killing plugin process {:?}, local_addr: {}", self.process.id(), self.local_addr ); let _ = self.process.start_kill(); } #[cfg(unix)] fn drop(&mut self) { debug!( "terminating plugin process {:?}, local_addr: {}", self.process.id(), self.local_addr ); let mut terminated = false; if let Some(id) = self.process.id() { unsafe { let ret = libc::kill(id as libc::pid_t, libc::SIGTERM); if ret != 0 { let err = io::Error::last_os_error(); error!("terminating plugin process {}, error: {}", id, err); } } const MAX_WAIT_DURATION: Duration = Duration::from_millis(10); let start_wait = Instant::now(); loop { match self.process.try_wait() { Ok(Some(status)) => { // subprocess is finished debug!( "plugin process {} is terminated gracefully with status: {:?}", id, status ); terminated = true; break; } Ok(None) => {} Err(err) => { error!("plugin process waitpid error: {}", err); break; } } let elapsed = Instant::now() - start_wait; if elapsed > MAX_WAIT_DURATION { debug!("plugin process {} isn't terminated in {:?}", id, MAX_WAIT_DURATION); break; } std::thread::yield_now(); } } if !terminated && self.process.start_kill().is_ok() { debug!("killed plugin process {:?}", self.process.id()); } } } fn start_plugin(plugin: &PluginConfig, remote: &ServerAddr, local: &SocketAddr, mode: PluginMode) -> io::Result { let mut cmd = if plugin.plugin == "obfsproxy" { obfs_proxy::plugin_cmd(plugin, remote, local, mode) } else { ss_plugin::plugin_cmd(plugin, remote, local, mode) }; cmd.spawn() } fn get_local_port(loop_ip: IpAddr) -> io::Result { let listener = TcpListener::bind(SocketAddr::new(loop_ip, 0))?; listener.local_addr() } #[cfg(test)] mod test { use super::*; #[test] fn generate_random_port() { let loop_ip = Ipv4Addr::LOCALHOST.into(); let addr = get_local_port(loop_ip).unwrap(); println!("{addr:?}"); } } ================================================ FILE: crates/shadowsocks/src/plugin/obfs_proxy.rs ================================================ use super::{PluginConfig, PluginMode}; use crate::config::ServerAddr; use std::{net::SocketAddr, process::Stdio}; use tokio::process::Command; /// For obfsproxy, we use standalone mode for now. /// Managed mode needs to use SOCKS5 proxy as forwarder, which is not supported /// yet. /// /// The idea of using standalone mode is quite simple, just assemble the /// internal port into obfsproxy parameters. /// /// Using manually ran scramblesuit as an example: /// obfsproxy \ /// --data-dir /tmp/ss_libev_plugin_with_suffix \ /// scramblesuit \ /// --password SOMEMEANINGLESSPASSWORDASEXAMPLE \ /// --dest some.server.org:12345 \ /// client \ /// 127.0.0.1:54321 /// /// In above case, @plugin = "obfsproxy", /// @plugin_opts = "scramblesuit --password SOMEMEANINGLESSPASSWORDASEXAMPLE" /// For obfs3, it's even easier, just pass @plugin = "obfsproxy" /// @plugin_opts = "obfs3" /// /// And the rest parameters are all assembled here. /// Some old obfsproxy will not be supported as it doesn't even support /// "--data-dir" option pub fn plugin_cmd(plugin: &PluginConfig, remote: &ServerAddr, local: &SocketAddr, mode: PluginMode) -> Command { let mut cmd = Command::new(&plugin.plugin); cmd.stdin(Stdio::null()) .kill_on_drop(true) .arg("--data-dir") .arg(format!("/tmp/{}_{}_{}", plugin.plugin, remote, local)); // FIXME: Not compatible in Windows if let Some(ref opt) = plugin.plugin_opts { cmd.args(opt.split(' ')); } match mode { PluginMode::Client => cmd .arg("--dest") .arg(remote.to_string()) .arg("client") .arg(local.to_string()), PluginMode::Server => cmd .arg("--dest") .arg(local.to_string()) .arg("server") .arg(remote.to_string()), }; if !plugin.plugin_args.is_empty() { cmd.args(&plugin.plugin_args); } cmd } ================================================ FILE: crates/shadowsocks/src/plugin/ss_plugin.rs ================================================ use super::{PluginConfig, PluginMode}; use crate::config::ServerAddr; use log::trace; use std::{net::SocketAddr, process::Stdio}; use tokio::process::Command; pub fn plugin_cmd(plugin: &PluginConfig, remote: &ServerAddr, local: &SocketAddr, _mode: PluginMode) -> Command { trace!( "Starting plugin \"{}\", opt: {:?}, arg: {:?}, remote: {}, local: {}", plugin.plugin, plugin.plugin_opts, plugin.plugin_args, remote, local ); let mut cmd = Command::new(&plugin.plugin); cmd.env("SS_REMOTE_HOST", remote.host()) .env("SS_REMOTE_PORT", remote.port().to_string()) .env("SS_LOCAL_HOST", local.ip().to_string()) .env("SS_LOCAL_PORT", local.port().to_string()) .stdin(Stdio::null()) .kill_on_drop(true); if let Some(ref opt) = plugin.plugin_opts { cmd.env("SS_PLUGIN_OPTIONS", opt); } if !plugin.plugin_args.is_empty() { cmd.args(&plugin.plugin_args); } cmd } ================================================ FILE: crates/shadowsocks/src/relay/mod.rs ================================================ //! Relay server in local and server side implementations. pub use self::socks5::Address; pub mod socks5; pub mod tcprelay; pub mod udprelay; /// AEAD 2022 maximum padding length #[cfg(feature = "aead-cipher-2022")] const AEAD2022_MAX_PADDING_SIZE: usize = 900; /// Get a properly AEAD 2022 padding size according to payload's length #[cfg(feature = "aead-cipher-2022")] fn get_aead_2022_padding_size(payload: &[u8]) -> usize { use std::cell::RefCell; use rand::{RngExt, rngs::SmallRng}; thread_local! { static PADDING_RNG: RefCell = RefCell::new(rand::make_rng()); } if payload.is_empty() { PADDING_RNG.with(|rng| rng.borrow_mut().random_range::(0..=AEAD2022_MAX_PADDING_SIZE)) } else { 0 } } ================================================ FILE: crates/shadowsocks/src/relay/socks5.rs ================================================ //! Socks5 protocol definition (RFC1928) //! //! Implements [SOCKS Protocol Version 5](https://www.ietf.org/rfc/rfc1928.txt) proxy protocol use std::{ convert::From, fmt::{self, Debug, Display, Formatter}, io::{self, ErrorKind}, net::{Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6, ToSocketAddrs}, slice, str::FromStr, vec, }; use bytes::{Buf, BufMut, BytesMut}; use tokio::io::{AsyncRead, AsyncReadExt, AsyncWrite, AsyncWriteExt}; pub use self::consts::{ SOCKS5_AUTH_METHOD_GSSAPI, SOCKS5_AUTH_METHOD_NONE, SOCKS5_AUTH_METHOD_NOT_ACCEPTABLE, SOCKS5_AUTH_METHOD_PASSWORD, }; #[rustfmt::skip] mod consts { pub const SOCKS5_VERSION: u8 = 0x05; pub const SOCKS5_AUTH_METHOD_NONE: u8 = 0x00; pub const SOCKS5_AUTH_METHOD_GSSAPI: u8 = 0x01; pub const SOCKS5_AUTH_METHOD_PASSWORD: u8 = 0x02; pub const SOCKS5_AUTH_METHOD_NOT_ACCEPTABLE: u8 = 0xff; pub const SOCKS5_CMD_TCP_CONNECT: u8 = 0x01; pub const SOCKS5_CMD_TCP_BIND: u8 = 0x02; pub const SOCKS5_CMD_UDP_ASSOCIATE: u8 = 0x03; pub const SOCKS5_ADDR_TYPE_IPV4: u8 = 0x01; pub const SOCKS5_ADDR_TYPE_DOMAIN_NAME: u8 = 0x03; pub const SOCKS5_ADDR_TYPE_IPV6: u8 = 0x04; pub const SOCKS5_REPLY_SUCCEEDED: u8 = 0x00; pub const SOCKS5_REPLY_GENERAL_FAILURE: u8 = 0x01; pub const SOCKS5_REPLY_CONNECTION_NOT_ALLOWED: u8 = 0x02; pub const SOCKS5_REPLY_NETWORK_UNREACHABLE: u8 = 0x03; pub const SOCKS5_REPLY_HOST_UNREACHABLE: u8 = 0x04; pub const SOCKS5_REPLY_CONNECTION_REFUSED: u8 = 0x05; pub const SOCKS5_REPLY_TTL_EXPIRED: u8 = 0x06; pub const SOCKS5_REPLY_COMMAND_NOT_SUPPORTED: u8 = 0x07; pub const SOCKS5_REPLY_ADDRESS_TYPE_NOT_SUPPORTED: u8 = 0x08; } /// SOCKS5 command #[derive(Clone, Debug, Copy)] pub enum Command { /// CONNECT command (TCP tunnel) TcpConnect, /// BIND command (Not supported in ShadowSocks) TcpBind, /// UDP ASSOCIATE command UdpAssociate, } impl Command { #[inline] #[rustfmt::skip] fn as_u8(self) -> u8 { match self { Self::TcpConnect => consts::SOCKS5_CMD_TCP_CONNECT, Self::TcpBind => consts::SOCKS5_CMD_TCP_BIND, Self::UdpAssociate => consts::SOCKS5_CMD_UDP_ASSOCIATE, } } #[inline] #[rustfmt::skip] fn from_u8(code: u8) -> Option { match code { consts::SOCKS5_CMD_TCP_CONNECT => Some(Self::TcpConnect), consts::SOCKS5_CMD_TCP_BIND => Some(Self::TcpBind), consts::SOCKS5_CMD_UDP_ASSOCIATE => Some(Self::UdpAssociate), _ => None, } } } /// SOCKS5 reply code #[derive(Clone, Debug, Copy)] pub enum Reply { Succeeded, GeneralFailure, ConnectionNotAllowed, NetworkUnreachable, HostUnreachable, ConnectionRefused, TtlExpired, CommandNotSupported, AddressTypeNotSupported, OtherReply(u8), } impl Reply { #[inline] #[rustfmt::skip] pub fn as_u8(self) -> u8 { match self { Self::Succeeded => consts::SOCKS5_REPLY_SUCCEEDED, Self::GeneralFailure => consts::SOCKS5_REPLY_GENERAL_FAILURE, Self::ConnectionNotAllowed => consts::SOCKS5_REPLY_CONNECTION_NOT_ALLOWED, Self::NetworkUnreachable => consts::SOCKS5_REPLY_NETWORK_UNREACHABLE, Self::HostUnreachable => consts::SOCKS5_REPLY_HOST_UNREACHABLE, Self::ConnectionRefused => consts::SOCKS5_REPLY_CONNECTION_REFUSED, Self::TtlExpired => consts::SOCKS5_REPLY_TTL_EXPIRED, Self::CommandNotSupported => consts::SOCKS5_REPLY_COMMAND_NOT_SUPPORTED, Self::AddressTypeNotSupported => consts::SOCKS5_REPLY_ADDRESS_TYPE_NOT_SUPPORTED, Self::OtherReply(c) => c, } } #[inline] #[rustfmt::skip] pub fn from_u8(code: u8) -> Self { match code { consts::SOCKS5_REPLY_SUCCEEDED => Self::Succeeded, consts::SOCKS5_REPLY_GENERAL_FAILURE => Self::GeneralFailure, consts::SOCKS5_REPLY_CONNECTION_NOT_ALLOWED => Self::ConnectionNotAllowed, consts::SOCKS5_REPLY_NETWORK_UNREACHABLE => Self::NetworkUnreachable, consts::SOCKS5_REPLY_HOST_UNREACHABLE => Self::HostUnreachable, consts::SOCKS5_REPLY_CONNECTION_REFUSED => Self::ConnectionRefused, consts::SOCKS5_REPLY_TTL_EXPIRED => Self::TtlExpired, consts::SOCKS5_REPLY_COMMAND_NOT_SUPPORTED => Self::CommandNotSupported, consts::SOCKS5_REPLY_ADDRESS_TYPE_NOT_SUPPORTED => Self::AddressTypeNotSupported, _ => Self::OtherReply(code), } } } impl fmt::Display for Reply { #[rustfmt::skip] fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { Self::Succeeded => write!(f, "Succeeded"), Self::AddressTypeNotSupported => write!(f, "Address type not supported"), Self::CommandNotSupported => write!(f, "Command not supported"), Self::ConnectionNotAllowed => write!(f, "Connection not allowed"), Self::ConnectionRefused => write!(f, "Connection refused"), Self::GeneralFailure => write!(f, "General failure"), Self::HostUnreachable => write!(f, "Host unreachable"), Self::NetworkUnreachable => write!(f, "Network unreachable"), Self::OtherReply(u) => write!(f, "Other reply ({u})"), Self::TtlExpired => write!(f, "TTL expired"), } } } /// SOCKS5 protocol error #[derive(Debug, thiserror::Error)] pub enum Error { #[error("{0}")] IoError(#[from] io::Error), #[error("address type {0:#x} not supported")] AddressTypeNotSupported(u8), #[error("address domain name must be UTF-8 encoding")] AddressDomainInvalidEncoding, #[error("unsupported socks version {0:#x}")] UnsupportedSocksVersion(u8), #[error("unsupported command {0:#x}")] UnsupportedCommand(u8), #[error("unsupported username/password authentication version {0:#x}")] UnsupportedPasswdAuthVersion(u8), #[error("username/password authentication invalid request")] PasswdAuthInvalidRequest, #[error("{0}")] Reply(Reply), } impl From for io::Error { fn from(err: Error) -> Self { match err { Error::IoError(err) => err, e => Self::other(e), } } } impl Error { /// Convert to `Reply` for responding pub fn as_reply(&self) -> Reply { match *self { Self::IoError(ref err) => match err.kind() { ErrorKind::ConnectionRefused => Reply::ConnectionRefused, _ => Reply::GeneralFailure, }, Self::AddressTypeNotSupported(..) => Reply::AddressTypeNotSupported, Self::AddressDomainInvalidEncoding => Reply::GeneralFailure, Self::UnsupportedSocksVersion(..) => Reply::GeneralFailure, Self::UnsupportedCommand(..) => Reply::CommandNotSupported, Self::UnsupportedPasswdAuthVersion(..) => Reply::GeneralFailure, Self::PasswdAuthInvalidRequest => Reply::GeneralFailure, Self::Reply(r) => r, } } } /// SOCKS5 address type #[derive(Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] pub enum Address { /// Socket address (IP Address) SocketAddress(SocketAddr), /// Domain name address DomainNameAddress(String, u16), } impl Address { /// read from a cursor pub fn read_cursor>(cur: &mut io::Cursor) -> Result { if cur.remaining() < 2 { return Err(io::Error::other("invalid buf").into()); } let atyp = cur.get_u8(); match atyp { consts::SOCKS5_ADDR_TYPE_IPV4 => { if cur.remaining() < 4 + 2 { return Err(io::Error::other("invalid buf").into()); } let addr = Ipv4Addr::from(cur.get_u32()); let port = cur.get_u16(); Ok(Self::SocketAddress(SocketAddr::V4(SocketAddrV4::new(addr, port)))) } consts::SOCKS5_ADDR_TYPE_IPV6 => { if cur.remaining() < 16 + 2 { return Err(io::Error::other("invalid buf").into()); } let addr = Ipv6Addr::from(cur.get_u128()); let port = cur.get_u16(); Ok(Self::SocketAddress(SocketAddr::V6(SocketAddrV6::new(addr, port, 0, 0)))) } consts::SOCKS5_ADDR_TYPE_DOMAIN_NAME => { let domain_len = cur.get_u8() as usize; if cur.remaining() < domain_len { return Err(Error::AddressDomainInvalidEncoding); } let mut buf = vec![0u8; domain_len]; cur.copy_to_slice(&mut buf); let port = cur.get_u16(); let addr = String::from_utf8(buf).map_err(|_| Error::AddressDomainInvalidEncoding)?; Ok(Self::DomainNameAddress(addr, port)) } _ => Err(Error::AddressTypeNotSupported(atyp)), } } /// Parse from a `AsyncRead` pub async fn read_from(stream: &mut R) -> Result where R: AsyncRead + Unpin, { let mut addr_type_buf = [0u8; 1]; let _ = stream.read_exact(&mut addr_type_buf).await?; let addr_type = addr_type_buf[0]; match addr_type { consts::SOCKS5_ADDR_TYPE_IPV4 => { let mut buf = [0u8; 6]; let _ = stream.read_exact(&mut buf).await?; let v4addr = Ipv4Addr::new(buf[0], buf[1], buf[2], buf[3]); let port = u16::from_be_bytes([buf[4], buf[5]]); Ok(Self::SocketAddress(SocketAddr::V4(SocketAddrV4::new(v4addr, port)))) } consts::SOCKS5_ADDR_TYPE_IPV6 => { let mut buf = [0u16; 9]; let bytes_buf = unsafe { slice::from_raw_parts_mut(buf.as_mut_ptr() as *mut _, 18) }; let _ = stream.read_exact(bytes_buf).await?; let v6addr = Ipv6Addr::new( u16::from_be(buf[0]), u16::from_be(buf[1]), u16::from_be(buf[2]), u16::from_be(buf[3]), u16::from_be(buf[4]), u16::from_be(buf[5]), u16::from_be(buf[6]), u16::from_be(buf[7]), ); let port = u16::from_be(buf[8]); Ok(Self::SocketAddress(SocketAddr::V6(SocketAddrV6::new( v6addr, port, 0, 0, )))) } consts::SOCKS5_ADDR_TYPE_DOMAIN_NAME => { let mut length_buf = [0u8; 1]; let _ = stream.read_exact(&mut length_buf).await?; let length = length_buf[0] as usize; // Len(Domain) + Len(Port) let buf_length = length + 2; let mut raw_addr = vec![0u8; buf_length]; let _ = stream.read_exact(&mut raw_addr).await?; let raw_port = &raw_addr[length..]; let port = u16::from_be_bytes([raw_port[0], raw_port[1]]); raw_addr.truncate(length); let addr = match String::from_utf8(raw_addr) { Ok(addr) => addr, Err(..) => return Err(Error::AddressDomainInvalidEncoding), }; Ok(Self::DomainNameAddress(addr, port)) } _ => { // Wrong Address Type . Socks5 only supports ipv4, ipv6 and domain name Err(Error::AddressTypeNotSupported(addr_type)) } } } /// Writes to writer #[inline] pub async fn write_to(&self, writer: &mut W) -> io::Result<()> where W: AsyncWrite + Unpin, { let mut buf = BytesMut::with_capacity(self.serialized_len()); self.write_to_buf(&mut buf); writer.write_all(&buf).await } /// Writes to buffer #[inline] pub fn write_to_buf(&self, buf: &mut B) { write_address(self, buf) } /// Get required buffer size for serializing #[inline] pub fn serialized_len(&self) -> usize { get_addr_len(self) } /// Get maximum required buffer size for serializing #[inline] pub fn max_serialized_len() -> usize { 1 // ADDR_TYPE + 1 // DOMAIN LENGTH + u8::MAX as usize // MAX DOMAIN + 2 // PORT } /// Get associated port number pub fn port(&self) -> u16 { match *self { Self::SocketAddress(addr) => addr.port(), Self::DomainNameAddress(.., port) => port, } } /// Get host address string pub fn host(&self) -> String { match *self { Self::SocketAddress(ref addr) => addr.ip().to_string(), Self::DomainNameAddress(ref domain, ..) => domain.to_owned(), } } } impl Debug for Address { #[inline] fn fmt(&self, f: &mut Formatter) -> fmt::Result { match *self { Self::SocketAddress(ref addr) => write!(f, "{addr}"), Self::DomainNameAddress(ref addr, ref port) => write!(f, "{addr}:{port}"), } } } impl fmt::Display for Address { #[inline] fn fmt(&self, f: &mut Formatter) -> fmt::Result { match *self { Self::SocketAddress(ref addr) => write!(f, "{addr}"), Self::DomainNameAddress(ref addr, ref port) => write!(f, "{addr}:{port}"), } } } impl ToSocketAddrs for Address { type Iter = vec::IntoIter; fn to_socket_addrs(&self) -> io::Result> { match self.clone() { Self::SocketAddress(addr) => Ok(vec![addr].into_iter()), Self::DomainNameAddress(addr, port) => (&addr[..], port).to_socket_addrs(), } } } impl From for Address { fn from(s: SocketAddr) -> Self { Self::SocketAddress(s) } } impl From<(String, u16)> for Address { fn from((dn, port): (String, u16)) -> Self { Self::DomainNameAddress(dn, port) } } impl From<&Self> for Address { fn from(addr: &Self) -> Self { addr.clone() } } /// Parse `Address` error #[derive(Debug)] pub struct AddressError; impl Display for AddressError { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { f.write_str("invalid Address") } } impl std::error::Error for AddressError {} impl FromStr for Address { type Err = AddressError; fn from_str(s: &str) -> Result { match s.parse::() { Ok(addr) => Ok(Self::SocketAddress(addr)), Err(..) => { let mut sp = s.split(':'); match (sp.next(), sp.next()) { (Some(dn), Some(port)) => match port.parse::() { Ok(port) => Ok(Self::DomainNameAddress(dn.to_owned(), port)), Err(..) => Err(AddressError), }, (Some(dn), None) => { // Assume it is 80 (http's default port) Ok(Self::DomainNameAddress(dn.to_owned(), 80)) } _ => Err(AddressError), } } } } } fn write_ipv4_address(addr: &SocketAddrV4, buf: &mut B) { buf.put_u8(consts::SOCKS5_ADDR_TYPE_IPV4); // Address type buf.put_slice(&addr.ip().octets()); // Ipv4 bytes buf.put_u16(addr.port()); // Port } fn write_ipv6_address(addr: &SocketAddrV6, buf: &mut B) { buf.put_u8(consts::SOCKS5_ADDR_TYPE_IPV6); // Address type for seg in &addr.ip().segments() { buf.put_u16(*seg); // Ipv6 bytes } buf.put_u16(addr.port()); // Port } fn write_domain_name_address(dnaddr: &str, port: u16, buf: &mut B) { assert!(dnaddr.len() <= u8::MAX as usize); buf.put_u8(consts::SOCKS5_ADDR_TYPE_DOMAIN_NAME); assert!( dnaddr.len() <= u8::MAX as usize, "domain name length must be smaller than 256" ); buf.put_u8(dnaddr.len() as u8); buf.put_slice(dnaddr.as_bytes()); buf.put_u16(port); } fn write_socket_address(addr: &SocketAddr, buf: &mut B) { match *addr { SocketAddr::V4(ref addr) => write_ipv4_address(addr, buf), SocketAddr::V6(ref addr) => write_ipv6_address(addr, buf), } } fn write_address(addr: &Address, buf: &mut B) { match *addr { Address::SocketAddress(ref addr) => write_socket_address(addr, buf), Address::DomainNameAddress(ref dnaddr, ref port) => write_domain_name_address(dnaddr, *port, buf), } } #[inline] fn get_addr_len(atyp: &Address) -> usize { match *atyp { Address::SocketAddress(SocketAddr::V4(..)) => 1 + 4 + 2, Address::SocketAddress(SocketAddr::V6(..)) => 1 + 8 * 2 + 2, Address::DomainNameAddress(ref dmname, _) => 1 + 1 + dmname.len() + 2, } } /// TCP request header after handshake /// /// ```plain /// +----+-----+-------+------+----------+----------+ /// |VER | CMD | RSV | ATYP | DST.ADDR | DST.PORT | /// +----+-----+-------+------+----------+----------+ /// | 1 | 1 | X'00' | 1 | Variable | 2 | /// +----+-----+-------+------+----------+----------+ /// ``` #[derive(Clone, Debug)] pub struct TcpRequestHeader { /// SOCKS5 command pub command: Command, /// Remote address pub address: Address, } impl TcpRequestHeader { /// Creates a request header pub fn new(cmd: Command, addr: Address) -> Self { Self { command: cmd, address: addr, } } /// Read from a reader pub async fn read_from(r: &mut R) -> Result where R: AsyncRead + Unpin, { let mut buf = [0u8; 3]; let _ = r.read_exact(&mut buf).await?; let ver = buf[0]; if ver != consts::SOCKS5_VERSION { return Err(Error::UnsupportedSocksVersion(ver)); } let cmd = buf[1]; let command = match Command::from_u8(cmd) { Some(c) => c, None => return Err(Error::UnsupportedCommand(cmd)), }; let address = Address::read_from(r).await?; Ok(Self { command, address }) } /// Write data into a writer pub async fn write_to(&self, w: &mut W) -> io::Result<()> where W: AsyncWrite + Unpin, { let mut buf = BytesMut::with_capacity(self.serialized_len()); self.write_to_buf(&mut buf); w.write_all(&buf).await } /// Writes to buffer pub fn write_to_buf(&self, buf: &mut B) { let Self { ref address, ref command, } = *self; buf.put_slice(&[consts::SOCKS5_VERSION, command.as_u8(), 0x00]); address.write_to_buf(buf); } /// Length in bytes #[inline] pub fn serialized_len(&self) -> usize { self.address.serialized_len() + 3 } } /// TCP response header /// /// ```plain /// +----+-----+-------+------+----------+----------+ /// |VER | REP | RSV | ATYP | BND.ADDR | BND.PORT | /// +----+-----+-------+------+----------+----------+ /// | 1 | 1 | X'00' | 1 | Variable | 2 | /// +----+-----+-------+------+----------+----------+ /// ``` #[derive(Clone, Debug)] pub struct TcpResponseHeader { /// SOCKS5 reply pub reply: Reply, /// Reply address pub address: Address, } impl TcpResponseHeader { /// Creates a response header pub fn new(reply: Reply, address: Address) -> Self { Self { reply, address } } /// Read from a reader pub async fn read_from(r: &mut R) -> Result where R: AsyncRead + Unpin, { let mut buf = [0u8; 3]; let _ = r.read_exact(&mut buf).await?; let ver = buf[0]; let reply_code = buf[1]; if ver != consts::SOCKS5_VERSION { return Err(Error::UnsupportedSocksVersion(ver)); } let address = Address::read_from(r).await?; Ok(Self { reply: Reply::from_u8(reply_code), address, }) } /// Write to a writer pub async fn write_to(&self, w: &mut W) -> io::Result<()> where W: AsyncWrite + Unpin, { let mut buf = BytesMut::with_capacity(self.serialized_len()); self.write_to_buf(&mut buf); w.write_all(&buf).await } /// Writes to buffer pub fn write_to_buf(&self, buf: &mut B) { let Self { ref reply, ref address } = *self; buf.put_slice(&[consts::SOCKS5_VERSION, reply.as_u8(), 0x00]); address.write_to_buf(buf); } /// Length in bytes #[inline] pub fn serialized_len(&self) -> usize { self.address.serialized_len() + 3 } } /// SOCKS5 handshake request packet /// /// ```plain /// +----+----------+----------+ /// |VER | NMETHODS | METHODS | /// +----+----------+----------+ /// | 5 | 1 | 1 to 255 | /// +----+----------+----------| /// ``` #[derive(Clone, Debug)] pub struct HandshakeRequest { pub methods: Vec, } impl HandshakeRequest { /// Creates a handshake request pub fn new(methods: Vec) -> Self { Self { methods } } /// Read from a reader pub async fn read_from(r: &mut R) -> Result where R: AsyncRead + Unpin, { let mut buf = [0u8; 2]; let _ = r.read_exact(&mut buf).await?; let ver = buf[0]; let nmet = buf[1]; if ver != consts::SOCKS5_VERSION { return Err(Error::UnsupportedSocksVersion(ver)); } let mut methods = vec![0u8; nmet as usize]; let _ = r.read_exact(&mut methods).await?; Ok(Self { methods }) } /// Write to a writer pub async fn write_to(&self, w: &mut W) -> io::Result<()> where W: AsyncWrite + Unpin, { let mut buf = BytesMut::with_capacity(self.serialized_len()); self.write_to_buf(&mut buf); w.write_all(&buf).await } /// Write to buffer pub fn write_to_buf(&self, buf: &mut B) { let Self { ref methods } = *self; buf.put_slice(&[consts::SOCKS5_VERSION, methods.len() as u8]); buf.put_slice(methods); } /// Get length of bytes pub fn serialized_len(&self) -> usize { 2 + self.methods.len() } } /// SOCKS5 handshake response packet /// /// ```plain /// +----+--------+ /// |VER | METHOD | /// +----+--------+ /// | 1 | 1 | /// +----+--------+ /// ``` #[derive(Clone, Debug, Copy)] pub struct HandshakeResponse { pub chosen_method: u8, } impl HandshakeResponse { /// Creates a handshake response pub fn new(cm: u8) -> Self { Self { chosen_method: cm } } /// Read from a reader pub async fn read_from(r: &mut R) -> Result where R: AsyncRead + Unpin, { let mut buf = [0u8; 2]; let _ = r.read_exact(&mut buf).await?; let ver = buf[0]; let met = buf[1]; if ver != consts::SOCKS5_VERSION { Err(Error::UnsupportedSocksVersion(ver)) } else { Ok(Self { chosen_method: met }) } } /// Write to a writer pub async fn write_to(self, w: &mut W) -> io::Result<()> where W: AsyncWrite + Unpin, { let mut buf = BytesMut::with_capacity(self.serialized_len()); self.write_to_buf(&mut buf); w.write_all(&buf).await } /// Write to buffer pub fn write_to_buf(self, buf: &mut B) { buf.put_slice(&[consts::SOCKS5_VERSION, self.chosen_method]); } /// Length in bytes pub fn serialized_len(self) -> usize { 2 } } /// UDP ASSOCIATE request header /// /// ```plain /// +----+------+------+----------+----------+----------+ /// |RSV | FRAG | ATYP | DST.ADDR | DST.PORT | DATA | /// +----+------+------+----------+----------+----------+ /// | 2 | 1 | 1 | Variable | 2 | Variable | /// +----+------+------+----------+----------+----------+ /// ``` #[derive(Clone, Debug)] pub struct UdpAssociateHeader { /// Fragment /// /// ShadowSocks does not support fragment, so this frag must be 0x00 pub frag: u8, /// Remote address pub address: Address, } impl UdpAssociateHeader { /// Creates a header pub fn new(frag: u8, address: Address) -> Self { Self { frag, address } } /// Read from a reader pub async fn read_from(r: &mut R) -> Result where R: AsyncRead + Unpin, { let mut buf = [0u8; 3]; let _ = r.read_exact(&mut buf).await?; let frag = buf[2]; let address = Address::read_from(r).await?; Ok(Self::new(frag, address)) } /// Write to a writer pub async fn write_to(&self, w: &mut W) -> io::Result<()> where W: AsyncWrite + Unpin, { let mut buf = BytesMut::with_capacity(self.serialized_len()); self.write_to_buf(&mut buf); w.write_all(&buf).await } /// Write to buffer pub fn write_to_buf(&self, buf: &mut B) { let Self { ref frag, ref address } = *self; buf.put_slice(&[0x00, 0x00, *frag]); address.write_to_buf(buf); } /// Length in bytes #[inline] pub fn serialized_len(&self) -> usize { 3 + self.address.serialized_len() } } /// Username/Password Authentication Initial Negotiation /// /// https://datatracker.ietf.org/doc/html/rfc1929 /// /// ```plain /// +----+------+----------+------+----------+ /// |VER | ULEN | UNAME | PLEN | PASSWD | /// +----+------+----------+------+----------+ /// | 1 | 1 | 1 to 255 | 1 | 1 to 255 | /// +----+------+----------+------+----------+ /// ``` pub struct PasswdAuthRequest { pub uname: Vec, pub passwd: Vec, } impl PasswdAuthRequest { /// Create a Username/Password Authentication Request pub fn new(uname: U, passwd: P) -> Self where U: Into>, P: Into>, { let uname = uname.into(); let passwd = passwd.into(); assert!( !uname.is_empty() && uname.len() <= u8::MAX as usize && !passwd.is_empty() && passwd.len() <= u8::MAX as usize ); Self { uname, passwd } } /// Read from a reader pub async fn read_from(r: &mut R) -> Result where R: AsyncRead + Unpin, { let mut ver_buf = [0u8; 1]; let _ = r.read_exact(&mut ver_buf).await?; // The only valid subnegotiation version if ver_buf[0] != 0x01 { return Err(Error::UnsupportedPasswdAuthVersion(ver_buf[0])); } let mut ulen_buf = [0u8; 1]; let _ = r.read_exact(&mut ulen_buf).await?; let ulen = ulen_buf[0] as usize; if ulen == 0 { return Err(Error::PasswdAuthInvalidRequest); } let mut uname = vec![0u8; ulen]; if ulen > 0 { let _ = r.read_exact(&mut uname).await?; } let mut plen_buf = [0u8; 1]; let _ = r.read_exact(&mut plen_buf).await?; let plen = plen_buf[0] as usize; if plen == 0 { return Err(Error::PasswdAuthInvalidRequest); } let mut passwd = vec![0u8; plen]; if plen > 0 { let _ = r.read_exact(&mut passwd).await?; } Ok(Self { uname, passwd }) } /// Write to a writer pub async fn write_to(&self, w: &mut W) -> io::Result<()> where W: AsyncWrite + Unpin, { let mut buf = BytesMut::with_capacity(self.serialized_len()); self.write_to_buf(&mut buf); w.write_all(&buf).await } /// Write to buffer fn write_to_buf(&self, buf: &mut B) { buf.put_u8(0x01); buf.put_u8(self.uname.len() as u8); buf.put_slice(&self.uname); buf.put_u8(self.passwd.len() as u8); buf.put_slice(&self.passwd); } /// Length in bytes #[inline] pub fn serialized_len(&self) -> usize { 1 + 1 + self.uname.len() + 1 + self.passwd.len() } } pub struct PasswdAuthResponse { pub status: u8, } impl PasswdAuthResponse { pub fn new(status: u8) -> Self { Self { status } } /// Read from a reader pub async fn read_from(r: &mut R) -> Result where R: AsyncRead + Unpin, { let mut buf = [0u8; 2]; let _ = r.read_exact(&mut buf).await; if buf[0] != 0x01 { return Err(Error::UnsupportedPasswdAuthVersion(buf[0])); } Ok(Self { status: buf[1] }) } /// Write to a writer pub async fn write_to(&self, w: &mut W) -> io::Result<()> where W: AsyncWrite + Unpin, { let mut buf = BytesMut::with_capacity(self.serialized_len()); self.write_to_buf(&mut buf); w.write_all(&buf).await } /// Write to buffer fn write_to_buf(&self, buf: &mut B) { buf.put_u8(0x01); buf.put_u8(self.status); } /// Length in bytes #[inline] pub fn serialized_len(&self) -> usize { 2 } } ================================================ FILE: crates/shadowsocks/src/relay/tcprelay/aead.rs ================================================ //! AEAD packet I/O facilities //! //! AEAD protocol is defined in . //! //! ```plain //! TCP request (before encryption) //! +------+---------------------+------------------+ //! | ATYP | Destination Address | Destination Port | //! +------+---------------------+------------------+ //! | 1 | Variable | 2 | //! +------+---------------------+------------------+ //! //! TCP request (after encryption, *ciphertext*) //! +--------+--------------+------------------+--------------+---------------+ //! | NONCE | *HeaderLen* | HeaderLen_TAG | *Header* | Header_TAG | //! +--------+--------------+------------------+--------------+---------------+ //! | Fixed | 2 | Fixed | Variable | Fixed | //! +--------+--------------+------------------+--------------+---------------+ //! //! TCP Chunk (before encryption) //! +----------+ //! | DATA | //! +----------+ //! | Variable | //! +----------+ //! //! TCP Chunk (after encryption, *ciphertext*) //! +--------------+---------------+--------------+------------+ //! | *DataLen* | DataLen_TAG | *Data* | Data_TAG | //! +--------------+---------------+--------------+------------+ //! | 2 | Fixed | Variable | Fixed | //! +--------------+---------------+--------------+------------+ //! ``` use std::{ io::{self, ErrorKind}, marker::Unpin, pin::Pin, slice, task::{self, Poll}, }; use byte_string::ByteStr; use bytes::{BufMut, Bytes, BytesMut}; use futures::ready; use log::trace; use tokio::io::{AsyncRead, AsyncWrite, ReadBuf}; use crate::{ context::Context, crypto::{CipherKind, v1::Cipher}, }; /// AEAD packet payload must be smaller than 0x3FFF pub const MAX_PACKET_SIZE: usize = 0x3FFF; /// AEAD Protocol Error #[derive(thiserror::Error, Debug)] pub enum ProtocolError { #[error(transparent)] IoError(#[from] io::Error), #[error("header too short, expecting {0} bytes, but found {1} bytes")] HeaderTooShort(usize, usize), #[error("decrypt data failed")] DecryptDataError, #[error("decrypt length failed")] DecryptLengthError, #[error( "buffer size too large ({0:#x}), AEAD encryption protocol requires buffer to be smaller than 0x3FFF, the higher two bits must be set to zero" )] DataTooLong(usize), } /// AEAD Protocol result pub type ProtocolResult = Result; impl From for io::Error { fn from(e: ProtocolError) -> Self { match e { ProtocolError::IoError(err) => err, _ => Self::other(e), } } } #[derive(Debug)] enum DecryptReadState { WaitSalt { key: Bytes }, ReadLength, ReadData { length: usize }, BufferedData { pos: usize }, } /// Reader wrapper that will decrypt data automatically pub struct DecryptedReader { state: DecryptReadState, cipher: Option, buffer: BytesMut, method: CipherKind, salt: Option, has_handshaked: bool, } impl DecryptedReader { pub fn new(method: CipherKind, key: &[u8]) -> Self { if method.salt_len() > 0 { Self { state: DecryptReadState::WaitSalt { key: Bytes::copy_from_slice(key), }, cipher: None, buffer: BytesMut::with_capacity(method.salt_len()), method, salt: None, has_handshaked: false, } } else { Self { state: DecryptReadState::ReadLength, cipher: Some(Cipher::new(method, key, &[])), buffer: BytesMut::with_capacity(2 + method.tag_len()), method, salt: None, has_handshaked: false, } } } pub fn salt(&self) -> Option<&[u8]> { self.salt.as_deref() } /// Attempt to read decrypted data from stream pub fn poll_read_decrypted( &mut self, cx: &mut task::Context<'_>, context: &Context, stream: &mut S, buf: &mut ReadBuf<'_>, ) -> Poll> where S: AsyncRead + Unpin + ?Sized, { loop { match self.state { DecryptReadState::WaitSalt { ref key } => { let key = unsafe { &*(key.as_ref() as *const _) }; ready!(self.poll_read_salt(cx, stream, key))?; self.buffer.clear(); self.state = DecryptReadState::ReadLength; self.buffer.reserve(2 + self.method.tag_len()); self.has_handshaked = true; } DecryptReadState::ReadLength => match ready!(self.poll_read_length(cx, stream))? { None => { return Ok(()).into(); } Some(length) => { self.buffer.clear(); self.state = DecryptReadState::ReadData { length }; self.buffer.reserve(length + self.method.tag_len()); } }, DecryptReadState::ReadData { length } => { ready!(self.poll_read_data(cx, context, stream, length))?; self.state = DecryptReadState::BufferedData { pos: 0 }; } DecryptReadState::BufferedData { ref mut pos } => { if *pos < self.buffer.len() { let buffered = &self.buffer[*pos..]; let consumed = usize::min(buffered.len(), buf.remaining()); buf.put_slice(&buffered[..consumed]); *pos += consumed; return Ok(()).into(); } self.buffer.clear(); self.state = DecryptReadState::ReadLength; self.buffer.reserve(2 + self.method.tag_len()); } } } } fn poll_read_salt(&mut self, cx: &mut task::Context<'_>, stream: &mut S, key: &[u8]) -> Poll> where S: AsyncRead + Unpin + ?Sized, { let salt_len = self.method.salt_len(); let n = ready!(self.poll_read_exact(cx, stream, salt_len))?; if n < salt_len { return Err(io::Error::from(ErrorKind::UnexpectedEof).into()).into(); } let salt = &self.buffer[..salt_len]; // #442 Remember salt in filter after first successful decryption. // // If we check salt right here will allow attacker to flood our filter and eventually block all of our legitimate clients' requests. self.salt = Some(Bytes::copy_from_slice(salt)); trace!("got AEAD salt {:?}", ByteStr::new(salt)); let cipher = Cipher::new(self.method, key, salt); self.cipher = Some(cipher); Ok(()).into() } fn poll_read_length(&mut self, cx: &mut task::Context<'_>, stream: &mut S) -> Poll>> where S: AsyncRead + Unpin + ?Sized, { let length_len = 2 + self.method.tag_len(); let n = ready!(self.poll_read_exact(cx, stream, length_len))?; if n == 0 { return Ok(None).into(); } let cipher = self.cipher.as_mut().expect("cipher is None"); let m = &mut self.buffer[..length_len]; let length = Self::decrypt_length(cipher, m)?; Ok(Some(length)).into() } fn poll_read_data( &mut self, cx: &mut task::Context<'_>, context: &Context, stream: &mut S, size: usize, ) -> Poll> where S: AsyncRead + Unpin + ?Sized, { let data_len = size + self.method.tag_len(); let n = ready!(self.poll_read_exact(cx, stream, data_len))?; if n == 0 { return Err(io::Error::from(ErrorKind::UnexpectedEof).into()).into(); } let cipher = self.cipher.as_mut().expect("cipher is None"); let m = &mut self.buffer[..data_len]; if !cipher.decrypt_packet(m) { return Err(ProtocolError::DecryptDataError).into(); } // Check repeated salt after first successful decryption #442 if self.salt.is_some() { let salt = self.salt.take().unwrap(); context.check_nonce_replay(self.method, &salt)?; } // Remote TAG self.buffer.truncate(size); Ok(()).into() } fn poll_read_exact(&mut self, cx: &mut task::Context<'_>, stream: &mut S, size: usize) -> Poll> where S: AsyncRead + Unpin + ?Sized, { assert!(size != 0); while self.buffer.len() < size { let remaining = size - self.buffer.len(); let buffer = &mut self.buffer.chunk_mut()[..remaining]; let mut read_buf = ReadBuf::uninit(unsafe { slice::from_raw_parts_mut(buffer.as_mut_ptr() as *mut _, remaining) }); ready!(Pin::new(&mut *stream).poll_read(cx, &mut read_buf))?; let n = read_buf.filled().len(); if n == 0 { if !self.buffer.is_empty() { return Err(ErrorKind::UnexpectedEof.into()).into(); } else { return Ok(0).into(); } } unsafe { self.buffer.advance_mut(n); } } Ok(size).into() } fn decrypt_length(cipher: &mut Cipher, m: &mut [u8]) -> ProtocolResult { let plen = { if !cipher.decrypt_packet(m) { return Err(ProtocolError::DecryptLengthError); } u16::from_be_bytes([m[0], m[1]]) as usize }; if plen > MAX_PACKET_SIZE { // https://shadowsocks.org/doc/aead.html // // AEAD TCP protocol have reserved the higher two bits for future use return Err(ProtocolError::DataTooLong(plen)); } Ok(plen) } /// Check if handshake finished pub fn handshaked(&self) -> bool { self.has_handshaked } } #[derive(Debug)] enum EncryptWriteState { AssemblePacket, Writing { pos: usize }, } /// Writer wrapper that will encrypt data automatically pub struct EncryptedWriter { cipher: Cipher, buffer: BytesMut, state: EncryptWriteState, salt: Bytes, } impl EncryptedWriter { /// Creates a new EncryptedWriter pub fn new(method: CipherKind, key: &[u8], nonce: &[u8]) -> Self { // nonce should be sent with the first packet let mut buffer = BytesMut::with_capacity(nonce.len()); buffer.put(nonce); Self { cipher: Cipher::new(method, key, nonce), buffer, state: EncryptWriteState::AssemblePacket, salt: Bytes::copy_from_slice(nonce), } } /// Salt (nonce) pub fn salt(&self) -> &[u8] { self.salt.as_ref() } /// Attempt to write encrypted data into the writer pub fn poll_write_encrypted( &mut self, cx: &mut task::Context<'_>, stream: &mut S, mut buf: &[u8], ) -> Poll> where S: AsyncWrite + Unpin + ?Sized, { if buf.len() > MAX_PACKET_SIZE { buf = &buf[..MAX_PACKET_SIZE]; } loop { match self.state { EncryptWriteState::AssemblePacket => { // Step 1. Append Length let length_size = 2 + self.cipher.tag_len(); self.buffer.reserve(length_size); let mbuf = &mut self.buffer.chunk_mut()[..length_size]; let mbuf = unsafe { slice::from_raw_parts_mut(mbuf.as_mut_ptr(), mbuf.len()) }; self.buffer.put_u16(buf.len() as u16); self.cipher.encrypt_packet(mbuf); unsafe { self.buffer.advance_mut(self.cipher.tag_len()) }; // Step 2. Append data let data_size = buf.len() + self.cipher.tag_len(); self.buffer.reserve(data_size); let mbuf = &mut self.buffer.chunk_mut()[..data_size]; let mbuf = unsafe { slice::from_raw_parts_mut(mbuf.as_mut_ptr(), mbuf.len()) }; self.buffer.put_slice(buf); self.cipher.encrypt_packet(mbuf); unsafe { self.buffer.advance_mut(self.cipher.tag_len()) }; // Step 3. Write all self.state = EncryptWriteState::Writing { pos: 0 }; } EncryptWriteState::Writing { ref mut pos } => { while *pos < self.buffer.len() { let n = ready!(Pin::new(&mut *stream).poll_write(cx, &self.buffer[*pos..]))?; if n == 0 { return Err(ErrorKind::UnexpectedEof.into()).into(); } *pos += n; } // Reset state self.state = EncryptWriteState::AssemblePacket; self.buffer.clear(); return Ok(buf.len()).into(); } } } } } ================================================ FILE: crates/shadowsocks/src/relay/tcprelay/aead_2022.rs ================================================ //! AEAD 2022 packet I/O facilities //! //! ```plain //! TCP Header (before encryption) //! //! +--------+--------+--------+--------+--------+--------+--------+--------+--------+ //! | TYPE | TIMESTAMP (BE) | //! +--------+--------+--------+--------+--------+--------+--------+--------+--------+ //! | ATYP | ADDRESS ... (Variable Length ...) //! +--------+--------+--------+--------+--------+--------+--------+--------+--------+ //! | PORT (BE) | Padding Length | Padding (Variable Length ...) //! +--------+--------+--------+--------+--------+--------+--------+--------+--------+ //! //! TCP Request Header (after encryption, *ciphertext*) //! //! +--------+--------+--------+--------+--------+--------+--------+--------+ //! | SALT (Variable Length ...) //! +--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+ //! | AEAD (TYPE + TIMESTAMP + HEADER_LENGTH) | //! +--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+ //! | AEAD (ATYP + ADDRESS + PORT + PADDING_LENGTH + PADDING) //! +--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+ //! //! TCP Respond Header (after encryption, *ciphertext*) //! //! +--------+--------+--------+--------+--------+--------+--------+--------+ //! | SALT (Variable Length ...) //! +--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+ //! | AEAD (TYPE + TIMESTAMP + REQUEST_SALT + DATA_LENGTH) //! +--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+ //! //! TCP Chunk (before encryption) //! +----------+ //! | DATA | //! +----------+ //! | Variable | //! +----------+ //! //! TCP Chunk (after encryption, *ciphertext*) //! +--------------+---------------+--------------+------------+ //! | *DataLen* | DataLen_TAG | *Data* | Data_TAG | //! +--------------+---------------+--------------+------------+ //! | 2 | Fixed | Variable | Fixed | //! +--------------+---------------+--------------+------------+ //! ``` use std::{ io::{self, Cursor, ErrorKind, Read}, marker::Unpin, pin::Pin, slice, sync::Arc, task::{self, Poll}, time::SystemTime, }; use aes::{ Aes128, Aes256, Block, cipher::{BlockDecrypt, BlockEncrypt, KeyInit}, }; use byte_string::ByteStr; use bytes::{Buf, BufMut, Bytes, BytesMut}; use futures::ready; use log::{error, trace}; use tokio::io::{AsyncRead, AsyncWrite, ReadBuf}; use super::{crypto_io::StreamType, proxy_stream::protocol::v2::SERVER_STREAM_TIMESTAMP_MAX_DIFF}; use crate::{ config::{ServerUserManager, method_support_eih}, context::Context, crypto::{CipherKind, v2::tcp::TcpCipher}, }; #[inline] fn get_now_timestamp() -> u64 { match SystemTime::now().duration_since(SystemTime::UNIX_EPOCH) { Ok(n) => n.as_secs(), Err(_) => panic!("SystemTime::now() is before UNIX Epoch!"), } } /// AEAD packet payload must be smaller than 0xFFFF (u16::MAX) pub const MAX_PACKET_SIZE: usize = 0xFFFF; const AEAD2022_EIH_SUBKEY_CONTEXT: &str = "shadowsocks 2022 identity subkey"; /// AEAD 2022 Protocol Error #[derive(thiserror::Error, Debug)] pub enum ProtocolError { #[error(transparent)] IoError(#[from] io::Error), #[error("header too short, expecting {0} bytes, but found {1} bytes")] HeaderTooShort(usize, usize), #[error("missing extended identity header")] MissingExtendedIdentityHeader, #[error("invalid client user identity {:?}", ByteStr::new(.0))] InvalidClientUser(Bytes), #[error("decrypt header chunk failed")] DecryptHeaderChunkError, #[error("decrypt data failed")] DecryptDataError, #[error("decrypt length failed")] DecryptLengthError, #[error("invalid stream type, expecting {0:#x}, but found {1:#x}")] InvalidStreamType(u8, u8), #[error("invalid timestamp {0} - now {1} = {ts_diff}", ts_diff = *.0 as i64 - *.1 as i64)] InvalidTimestamp(u64, u64), } /// AEAD 2022 Protocol result pub type ProtocolResult = Result; impl From for io::Error { fn from(e: ProtocolError) -> Self { match e { ProtocolError::IoError(err) => err, _ => Self::other(e), } } } enum DecryptReadState { ReadHeader { key: Bytes }, ReadLength, ReadData { length: usize }, BufferedData { pos: usize }, } /// Reader wrapper that will decrypt data automatically pub struct DecryptedReader { stream_ty: StreamType, state: DecryptReadState, cipher: Option, buffer: BytesMut, method: CipherKind, salt: Option, request_salt: Option, data_chunk_count: u64, user_manager: Option>, user_key: Option, has_handshaked: bool, } impl DecryptedReader { pub fn new(stream_ty: StreamType, method: CipherKind, key: &[u8]) -> Self { Self::with_user_manager(stream_ty, method, key, None) } pub fn with_user_manager( stream_ty: StreamType, method: CipherKind, key: &[u8], user_manager: Option>, ) -> Self { if method.salt_len() > 0 { Self { stream_ty, state: DecryptReadState::ReadHeader { key: Bytes::copy_from_slice(key), }, cipher: None, buffer: BytesMut::new(), method, salt: None, request_salt: None, data_chunk_count: 0, user_manager, user_key: None, has_handshaked: false, } } else { Self { stream_ty, state: DecryptReadState::ReadHeader { key: Bytes::new(), // EMPTY SALT, no allocation }, cipher: Some(TcpCipher::new(method, key, &[])), buffer: BytesMut::new(), method, salt: None, request_salt: None, data_chunk_count: 0, user_manager, user_key: None, has_handshaked: false, } } } pub fn salt(&self) -> Option<&[u8]> { self.salt.as_deref() } pub fn request_salt(&self) -> Option<&[u8]> { self.request_salt.as_deref().filter(|&n| !n.is_empty()) } /// Attempt to read decrypted data from stream pub fn poll_read_decrypted( &mut self, cx: &mut task::Context<'_>, context: &Context, stream: &mut S, buf: &mut ReadBuf<'_>, ) -> Poll> where S: AsyncRead + Unpin + ?Sized, { loop { match self.state { DecryptReadState::ReadHeader { ref key } => { let key = unsafe { &*(key.as_ref() as *const _) }; match ready!(self.poll_read_header(cx, context, stream, key))? { None => { return Ok(()).into(); } Some(length) => { self.buffer.clear(); self.state = DecryptReadState::ReadData { length }; self.buffer.reserve(length + self.method.tag_len()); self.has_handshaked = true; } } } DecryptReadState::ReadLength => match ready!(self.poll_read_length(cx, stream))? { None => { return Ok(()).into(); } Some(length) => { self.buffer.clear(); self.state = DecryptReadState::ReadData { length }; self.buffer.reserve(length + self.method.tag_len()); } }, DecryptReadState::ReadData { length } => { ready!(self.poll_read_data(cx, stream, length))?; self.state = DecryptReadState::BufferedData { pos: 0 }; self.data_chunk_count = self.data_chunk_count.wrapping_add(1); } DecryptReadState::BufferedData { ref mut pos } => { if *pos < self.buffer.len() { let buffered = &self.buffer[*pos..]; let consumed = usize::min(buffered.len(), buf.remaining()); buf.put_slice(&buffered[..consumed]); *pos += consumed; return Ok(()).into(); } self.buffer.clear(); self.state = DecryptReadState::ReadLength; self.buffer.reserve(2 + self.method.tag_len()); } } } } fn poll_read_header( &mut self, cx: &mut task::Context<'_>, context: &Context, stream: &mut S, key: &[u8], ) -> Poll>> where S: AsyncRead + Unpin + ?Sized, { let salt_len = self.method.salt_len(); // Header chunk, SALE + AEAD(TYPE + TIMESTAMP [+ REQUEST_SALT] + LENGTH) must be read in one call let request_salt_len = match self.stream_ty { StreamType::Client => salt_len, StreamType::Server => 0, }; let require_eih = self.stream_ty == StreamType::Server && method_support_eih(self.method) && self.user_manager.is_some(); let eih_len = if require_eih { 16 } else { 0 }; let header_len = salt_len + eih_len + 1 + 8 + request_salt_len + 2 + self.method.tag_len(); if self.buffer.len() < header_len { self.buffer.resize(header_len, 0); } let mut read_buf = ReadBuf::new(&mut self.buffer[..header_len]); ready!(Pin::new(stream).poll_read(cx, &mut read_buf))?; let header_buf = read_buf.filled_mut(); if header_buf.is_empty() { // EOF. return Ok(None).into(); } else if header_buf.len() != header_len { return Err(ProtocolError::HeaderTooShort(header_len, header_buf.len())).into(); } let (salt, mut header_chunk) = header_buf.split_at_mut(salt_len); trace!("got AEAD salt {:?}", ByteStr::new(salt)); // Extensible Identity Header // https://github.com/Shadowsocks-NET/shadowsocks-specs/blob/main/2022-2-shadowsocks-2022-extensible-identity-headers.md let mut cipher = if require_eih { match self.user_manager { Some(ref user_manager) => { // Assume we have at least 1 EIH if header_chunk.len() < 16 { error!("expecting EIH, but header chunk len: {}", header_chunk.len()); return Err(ProtocolError::MissingExtendedIdentityHeader).into(); } let (eih, remain_header_chunk) = header_chunk.split_at_mut(16); header_chunk = remain_header_chunk; let key_material = [key, salt].concat(); let identity_sub_key = blake3::derive_key(AEAD2022_EIH_SUBKEY_CONTEXT, &key_material); let mut user_hash = Block::from([0u8; 16]); match self.method { CipherKind::AEAD2022_BLAKE3_AES_128_GCM => { let cipher = Aes128::new_from_slice(&identity_sub_key[0..16]).expect("AES-128"); cipher.decrypt_block_b2b(Block::from_slice(eih), &mut user_hash); } CipherKind::AEAD2022_BLAKE3_AES_256_GCM => { let cipher = Aes256::new_from_slice(&identity_sub_key[0..32]).expect("AES-256"); cipher.decrypt_block_b2b(Block::from_slice(eih), &mut user_hash); } _ => unreachable!("{} doesn't support EIH", self.method), } let user_hash = user_hash.as_slice(); trace!( "server EIH {:?}, hash: {:?}", ByteStr::new(eih), ByteStr::new(user_hash) ); match user_manager.get_user_by_hash(user_hash) { None => { return Err(ProtocolError::InvalidClientUser(Bytes::copy_from_slice(user_hash))).into(); } Some(user) => { trace!("{:?} chosen by EIH", user); self.user_key = Some(Bytes::copy_from_slice(user.key())); TcpCipher::new(self.method, user.key(), salt) } } } _ => { unreachable!("user_manager must not be None") } } } else { TcpCipher::new(self.method, key, salt) }; // Decrypt the header chunk if !cipher.decrypt_packet(header_chunk) { return Err(ProtocolError::DecryptHeaderChunkError).into(); } let mut header_reader = Cursor::new(header_chunk); let stream_ty = header_reader.get_u8(); let expected_stream_ty = match self.stream_ty { StreamType::Client => 1, // Receive from server, so type == SERVER (1) StreamType::Server => 0, }; if stream_ty != expected_stream_ty { return Err(ProtocolError::InvalidStreamType(expected_stream_ty, stream_ty)).into(); } let timestamp = header_reader.get_u64(); let now = get_now_timestamp(); if now.abs_diff(timestamp) > SERVER_STREAM_TIMESTAMP_MAX_DIFF { return Err(ProtocolError::InvalidTimestamp(timestamp, now)).into(); } // Server respond packet will contain a request salt if request_salt_len > 0 { let mut request_salt = BytesMut::with_capacity(salt_len); request_salt.resize(salt_len, 0); header_reader.read_exact(&mut request_salt)?; self.request_salt = Some(request_salt.freeze()); } let data_length = header_reader.get_u16(); trace!( "got AEAD header stream_type: {}, timestamp: {}, length: {}, request_salt: {:?}", stream_ty, timestamp, data_length, self.request_salt.as_deref().map(ByteStr::new) ); // Salt doesn't need to be checked in client, because it has request_salt in respond header if self.stream_ty == StreamType::Server { // Check repeated salt after first successful decryption #442 // // If we check salt right here will allow attacker to flood our filter and eventually block all of our legitimate clients' requests. context.check_nonce_replay(self.method, salt)?; } self.salt = Some(Bytes::copy_from_slice(salt)); self.cipher = Some(cipher); Ok(Some(data_length as usize)).into() } fn poll_read_length(&mut self, cx: &mut task::Context<'_>, stream: &mut S) -> Poll>> where S: AsyncRead + Unpin + ?Sized, { let length_len = 2 + self.method.tag_len(); let n = ready!(self.poll_read_exact(cx, stream, length_len))?; if n == 0 { return Ok(None).into(); } let cipher = self.cipher.as_mut().expect("cipher is None"); let m = &mut self.buffer[..length_len]; let length = Self::decrypt_length(cipher, m)?; Ok(Some(length)).into() } fn poll_read_data(&mut self, cx: &mut task::Context<'_>, stream: &mut S, size: usize) -> Poll> where S: AsyncRead + Unpin + ?Sized, { let data_len = size + self.method.tag_len(); let n = ready!(self.poll_read_exact(cx, stream, data_len))?; if n == 0 { return Err(io::Error::from(ErrorKind::UnexpectedEof).into()).into(); } let cipher = self.cipher.as_mut().expect("cipher is None"); let m = &mut self.buffer[..data_len]; if !cipher.decrypt_packet(m) { return Err(ProtocolError::DecryptDataError).into(); } // Remote TAG self.buffer.truncate(size); Ok(()).into() } fn poll_read_exact(&mut self, cx: &mut task::Context<'_>, stream: &mut S, size: usize) -> Poll> where S: AsyncRead + Unpin + ?Sized, { assert!(size != 0); while self.buffer.len() < size { let remaining = size - self.buffer.len(); let buffer = &mut self.buffer.chunk_mut()[..remaining]; let mut read_buf = ReadBuf::uninit(unsafe { slice::from_raw_parts_mut(buffer.as_mut_ptr() as *mut _, remaining) }); ready!(Pin::new(&mut *stream).poll_read(cx, &mut read_buf))?; let n = read_buf.filled().len(); if n == 0 { if !self.buffer.is_empty() { return Err(ErrorKind::UnexpectedEof.into()).into(); } else { return Ok(0).into(); } } unsafe { self.buffer.advance_mut(n); } } Ok(size).into() } fn decrypt_length(cipher: &mut TcpCipher, m: &mut [u8]) -> ProtocolResult { let plen = { if !cipher.decrypt_packet(m) { return Err(ProtocolError::DecryptLengthError); } u16::from_be_bytes([m[0], m[1]]) as usize }; Ok(plen) } /// Get remaining bytes in the current data chunk /// /// Returning (DataChunkCount, RemainingBytes) pub fn current_data_chunk_remaining(&self) -> (u64, usize) { match self.state { DecryptReadState::BufferedData { pos } => (self.data_chunk_count, self.buffer.len() - pos), _ => (self.data_chunk_count, 0), } } /// Get authenticated user key pub fn user_key(&self) -> Option<&[u8]> { self.user_key.as_deref() } /// Check if handshake finished pub fn handshaked(&self) -> bool { self.has_handshaked } } enum EncryptWriteState { AssembleHeader, AssemblePacket, Writing { pos: usize }, } /// Writer wrapper that will encrypt data automatically pub struct EncryptedWriter { stream_ty: StreamType, cipher: TcpCipher, method: CipherKind, buffer: BytesMut, state: EncryptWriteState, salt: Bytes, request_salt: Option, } impl EncryptedWriter { /// Creates a new EncryptedWriter pub fn new(stream_ty: StreamType, method: CipherKind, key: &[u8], nonce: &[u8]) -> Self { const EMPTY_IDENTITY: [Bytes; 0] = []; Self::with_identity(stream_ty, method, key, nonce, &EMPTY_IDENTITY) } /// Creates a new EncryptedWriter with identities pub fn with_identity( stream_ty: StreamType, method: CipherKind, key: &[u8], nonce: &[u8], identity_keys: &[Bytes], ) -> Self { // nonce should be sent with the first packet let mut buffer = BytesMut::with_capacity(nonce.len() + identity_keys.len() * 16); buffer.put(nonce); // Extensible Identity Headers // https://github.com/Shadowsocks-NET/shadowsocks-specs/blob/main/2022-2-shadowsocks-2022-extensible-identity-headers.md #[inline] fn make_eih(method: CipherKind, sub_key: &[u8], ipsk: &[u8], buffer: &mut BytesMut) { let ipsk_hash = blake3::hash(ipsk); let ipsk_plain_text = &ipsk_hash.as_bytes()[0..16]; match method { CipherKind::AEAD2022_BLAKE3_AES_128_GCM => { let enc_key = &sub_key[0..16]; let cipher = Aes128::new_from_slice(enc_key).expect("AES-128"); let ipsk_plain_text = Block::from_slice(ipsk_plain_text); let mut block = Block::from([0u8; 16]); cipher.encrypt_block_b2b(ipsk_plain_text, &mut block); trace!( "client EIH {:?}, hash: {:?}", ByteStr::new(block.as_slice()), ByteStr::new(ipsk_plain_text) ); buffer.put(block.as_slice()); } CipherKind::AEAD2022_BLAKE3_AES_256_GCM => { let enc_key = &sub_key[0..32]; let cipher = Aes256::new_from_slice(enc_key).expect("AES-256"); let ipsk_plain_text = Block::from_slice(ipsk_plain_text); let mut block = Block::from([0u8; 16]); cipher.encrypt_block_b2b(ipsk_plain_text, &mut block); trace!( "client EIH {:?}, hash: {:?}", ByteStr::new(block.as_slice()), ByteStr::new(ipsk_plain_text) ); buffer.put(block.as_slice()); } _ => unreachable!("{} doesn't support EIH", method), } } if stream_ty == StreamType::Client && method_support_eih(method) { let mut sub_key: Option<[u8; blake3::OUT_LEN]> = None; for ipsk in identity_keys { if let Some(ref sub_key) = sub_key { make_eih(method, sub_key, ipsk, &mut buffer); } let key_material = [ipsk, nonce].concat(); sub_key = Some(blake3::derive_key(AEAD2022_EIH_SUBKEY_CONTEXT, &key_material)); } if let Some(ref sub_key) = sub_key { make_eih(method, sub_key, key, &mut buffer); } } Self { stream_ty, cipher: TcpCipher::new(method, key, nonce), method, buffer, state: EncryptWriteState::AssembleHeader, salt: Bytes::copy_from_slice(nonce), request_salt: None, } } /// Salt (nonce) pub fn salt(&self) -> &[u8] { self.salt.as_ref() } /// Set request salt (for server stream type) pub fn set_request_salt(&mut self, request_salt: Bytes) { debug_assert!(self.stream_ty == StreamType::Server); self.request_salt = Some(request_salt); } /// Reset cipher with key pub fn reset_cipher_with_key(&mut self, key: &[u8]) { self.cipher = TcpCipher::new(self.method, key, &self.salt); } /// Attempt to write encrypted data into the writer pub fn poll_write_encrypted( &mut self, cx: &mut task::Context<'_>, stream: &mut S, mut buf: &[u8], ) -> Poll> where S: AsyncWrite + Unpin + ?Sized, { if buf.len() > MAX_PACKET_SIZE { buf = &buf[..MAX_PACKET_SIZE]; } loop { match self.state { EncryptWriteState::AssembleHeader => { // Step 1. AEAD(TYPE + TIMESTAMP [+ REQUEST_SALT] + LENGTH) let request_salt_len = match self.request_salt { None => 0, Some(ref salt) => salt.len(), }; let header_len = 1 + 8 + request_salt_len + 2 + self.cipher.tag_len(); self.buffer.reserve(header_len); let mbuf = &mut self.buffer.chunk_mut()[..header_len]; let mbuf = unsafe { slice::from_raw_parts_mut(mbuf.as_mut_ptr(), mbuf.len()) }; let stream_ty = match self.stream_ty { StreamType::Client => 0, StreamType::Server => 1, }; self.buffer.put_u8(stream_ty); self.buffer.put_u64(get_now_timestamp()); if let Some(ref salt) = self.request_salt { self.buffer.put_slice(salt); } self.buffer.put_u16(buf.len() as u16); self.cipher.encrypt_packet(mbuf); unsafe { self.buffer.advance_mut(self.cipher.tag_len()) }; // Step 2. Data Chunk let data_size = buf.len() + self.cipher.tag_len(); self.buffer.reserve(data_size); let mbuf = &mut self.buffer.chunk_mut()[..data_size]; let mbuf = unsafe { slice::from_raw_parts_mut(mbuf.as_mut_ptr(), mbuf.len()) }; self.buffer.put_slice(buf); self.cipher.encrypt_packet(mbuf); unsafe { self.buffer.advance_mut(self.cipher.tag_len()) }; // Step 3. Write all self.state = EncryptWriteState::Writing { pos: 0 }; } EncryptWriteState::AssemblePacket => { // Step 1. Append Length let length_size = 2 + self.cipher.tag_len(); self.buffer.reserve(length_size); let mbuf = &mut self.buffer.chunk_mut()[..length_size]; let mbuf = unsafe { slice::from_raw_parts_mut(mbuf.as_mut_ptr(), mbuf.len()) }; self.buffer.put_u16(buf.len() as u16); self.cipher.encrypt_packet(mbuf); unsafe { self.buffer.advance_mut(self.cipher.tag_len()) }; // Step 2. Append data let data_size = buf.len() + self.cipher.tag_len(); self.buffer.reserve(data_size); let mbuf = &mut self.buffer.chunk_mut()[..data_size]; let mbuf = unsafe { slice::from_raw_parts_mut(mbuf.as_mut_ptr(), mbuf.len()) }; self.buffer.put_slice(buf); self.cipher.encrypt_packet(mbuf); unsafe { self.buffer.advance_mut(self.cipher.tag_len()) }; // Step 3. Write all self.state = EncryptWriteState::Writing { pos: 0 }; } EncryptWriteState::Writing { ref mut pos } => { while *pos < self.buffer.len() { let n = ready!(Pin::new(&mut *stream).poll_write(cx, &self.buffer[*pos..]))?; if n == 0 { return Err(ErrorKind::UnexpectedEof.into()).into(); } *pos += n; } // Reset state self.state = EncryptWriteState::AssemblePacket; self.buffer.clear(); return Ok(buf.len()).into(); } } } } } ================================================ FILE: crates/shadowsocks/src/relay/tcprelay/crypto_io.rs ================================================ //! IO facilities for TCP relay use std::{ fmt, io, marker::Unpin, pin::Pin, sync::Arc, task::{self, Poll}, }; #[cfg(any(feature = "stream-cipher", feature = "aead-cipher", feature = "aead-cipher-2022"))] use byte_string::ByteStr; use bytes::Bytes; use futures::ready; #[cfg(any(feature = "stream-cipher", feature = "aead-cipher", feature = "aead-cipher-2022"))] use log::trace; use tokio::io::{AsyncRead, AsyncWrite, ReadBuf}; use crate::{ config::ServerUserManager, context::Context, crypto::{CipherCategory, CipherKind}, }; #[cfg(feature = "aead-cipher")] use super::aead::{DecryptedReader as AeadDecryptedReader, EncryptedWriter as AeadEncryptedWriter}; #[cfg(feature = "aead-cipher-2022")] use super::aead_2022::{DecryptedReader as Aead2022DecryptedReader, EncryptedWriter as Aead2022EncryptedWriter}; #[cfg(feature = "stream-cipher")] use super::stream::{DecryptedReader as StreamDecryptedReader, EncryptedWriter as StreamEncryptedWriter}; /// TCP shadowsocks protocol error #[derive(thiserror::Error, Debug)] pub enum ProtocolError { #[error(transparent)] IoError(#[from] io::Error), #[cfg(feature = "stream-cipher")] #[error(transparent)] StreamError(#[from] super::stream::ProtocolError), #[cfg(feature = "aead-cipher")] #[error(transparent)] AeadError(#[from] super::aead::ProtocolError), #[cfg(feature = "aead-cipher-2022")] #[error(transparent)] Aead2022Error(#[from] super::aead_2022::ProtocolError), } /// TCP shadowsocks protocol result pub type ProtocolResult = Result; impl From for io::Error { fn from(e: ProtocolError) -> Self { match e { ProtocolError::IoError(err) => err, #[cfg(feature = "stream-cipher")] ProtocolError::StreamError(err) => err.into(), #[cfg(feature = "aead-cipher")] ProtocolError::AeadError(err) => err.into(), #[cfg(feature = "aead-cipher-2022")] ProtocolError::Aead2022Error(err) => err.into(), } } } /// The type of TCP stream #[derive(Clone, Copy, Debug, Eq, PartialEq)] pub enum StreamType { /// Client -> Server Client, /// Server -> Client Server, } /// Reader for reading encrypted data stream from shadowsocks' tunnel #[allow(clippy::large_enum_variant)] pub enum DecryptedReader { None, #[cfg(feature = "aead-cipher")] Aead(AeadDecryptedReader), #[cfg(feature = "stream-cipher")] Stream(StreamDecryptedReader), #[cfg(feature = "aead-cipher-2022")] Aead2022(Aead2022DecryptedReader), } impl DecryptedReader { /// Create a new reader for reading encrypted data pub fn new(stream_ty: StreamType, method: CipherKind, key: &[u8]) -> Self { Self::with_user_manager(stream_ty, method, key, None) } /// Create a new reader for reading encrypted data pub fn with_user_manager( stream_ty: StreamType, method: CipherKind, key: &[u8], user_manager: Option>, ) -> Self { if cfg!(not(feature = "aead-cipher-2022")) { let _ = stream_ty; let _ = user_manager; } match method.category() { #[cfg(feature = "stream-cipher")] CipherCategory::Stream => Self::Stream(StreamDecryptedReader::new(method, key)), #[cfg(feature = "aead-cipher")] CipherCategory::Aead => Self::Aead(AeadDecryptedReader::new(method, key)), CipherCategory::None => { let _ = method; let _ = key; Self::None } #[cfg(feature = "aead-cipher-2022")] CipherCategory::Aead2022 => Self::Aead2022(Aead2022DecryptedReader::with_user_manager( stream_ty, method, key, user_manager, )), } } /// Attempt to read decrypted data from `stream` #[inline] pub fn poll_read_decrypted( &mut self, cx: &mut task::Context<'_>, context: &Context, stream: &mut S, buf: &mut ReadBuf<'_>, ) -> Poll> where S: AsyncRead + Unpin + ?Sized, { match *self { #[cfg(feature = "stream-cipher")] Self::Stream(ref mut reader) => reader.poll_read_decrypted(cx, context, stream, buf).map_err(Into::into), #[cfg(feature = "aead-cipher")] Self::Aead(ref mut reader) => reader.poll_read_decrypted(cx, context, stream, buf).map_err(Into::into), Self::None => { let _ = context; Pin::new(stream).poll_read(cx, buf).map_err(Into::into) } #[cfg(feature = "aead-cipher-2022")] Self::Aead2022(ref mut reader) => reader.poll_read_decrypted(cx, context, stream, buf).map_err(Into::into), } } /// Get received IV (Stream) or Salt (AEAD, AEAD2022) pub fn nonce(&self) -> Option<&[u8]> { match *self { #[cfg(feature = "stream-cipher")] Self::Stream(ref reader) => reader.iv(), #[cfg(feature = "aead-cipher")] Self::Aead(ref reader) => reader.salt(), Self::None => None, #[cfg(feature = "aead-cipher-2022")] Self::Aead2022(ref reader) => reader.salt(), } } /// Get received request Salt (AEAD2022) pub fn request_nonce(&self) -> Option<&[u8]> { match *self { #[cfg(feature = "stream-cipher")] Self::Stream(..) => None, #[cfg(feature = "aead-cipher")] Self::Aead(..) => None, Self::None => None, #[cfg(feature = "aead-cipher-2022")] Self::Aead2022(ref reader) => reader.request_salt(), } } /// Get authenticated user key (AEAD2022) pub fn user_key(&self) -> Option<&[u8]> { match *self { #[cfg(feature = "stream-cipher")] Self::Stream(..) => None, #[cfg(feature = "aead-cipher")] Self::Aead(..) => None, Self::None => None, #[cfg(feature = "aead-cipher-2022")] Self::Aead2022(ref reader) => reader.user_key(), } } pub fn handshaked(&self) -> bool { match *self { #[cfg(feature = "stream-cipher")] Self::Stream(ref reader) => reader.handshaked(), #[cfg(feature = "aead-cipher")] Self::Aead(ref reader) => reader.handshaked(), Self::None => true, #[cfg(feature = "aead-cipher-2022")] Self::Aead2022(ref reader) => reader.handshaked(), } } } /// Writer for writing encrypted data stream into shadowsocks' tunnel #[allow(clippy::large_enum_variant)] pub enum EncryptedWriter { None, #[cfg(feature = "aead-cipher")] Aead(AeadEncryptedWriter), #[cfg(feature = "stream-cipher")] Stream(StreamEncryptedWriter), #[cfg(feature = "aead-cipher-2022")] Aead2022(Aead2022EncryptedWriter), } impl EncryptedWriter { /// Create a new writer for writing encrypted data pub fn new(stream_ty: StreamType, method: CipherKind, key: &[u8], nonce: &[u8]) -> Self { if cfg!(not(feature = "aead-cipher-2022")) { let _ = stream_ty; } match method.category() { #[cfg(feature = "stream-cipher")] CipherCategory::Stream => Self::Stream(StreamEncryptedWriter::new(method, key, nonce)), #[cfg(feature = "aead-cipher")] CipherCategory::Aead => Self::Aead(AeadEncryptedWriter::new(method, key, nonce)), CipherCategory::None => { let _ = key; let _ = nonce; Self::None } #[cfg(feature = "aead-cipher-2022")] CipherCategory::Aead2022 => Self::Aead2022(Aead2022EncryptedWriter::new(stream_ty, method, key, nonce)), } } /// Create a new writer for writing encrypted data pub fn with_identity( stream_ty: StreamType, method: CipherKind, key: &[u8], nonce: &[u8], identity_keys: &[Bytes], ) -> Self { if cfg!(not(feature = "aead-cipher-2022")) { let _ = stream_ty; let _ = identity_keys; } match method.category() { #[cfg(feature = "stream-cipher")] CipherCategory::Stream => Self::Stream(StreamEncryptedWriter::new(method, key, nonce)), #[cfg(feature = "aead-cipher")] CipherCategory::Aead => Self::Aead(AeadEncryptedWriter::new(method, key, nonce)), CipherCategory::None => { let _ = key; let _ = nonce; Self::None } #[cfg(feature = "aead-cipher-2022")] CipherCategory::Aead2022 => Self::Aead2022(Aead2022EncryptedWriter::with_identity( stream_ty, method, key, nonce, identity_keys, )), } } /// Attempt to write encrypted data to `stream` #[inline] pub fn poll_write_encrypted( &mut self, cx: &mut task::Context<'_>, stream: &mut S, buf: &[u8], ) -> Poll> where S: AsyncWrite + Unpin + ?Sized, { match *self { #[cfg(feature = "stream-cipher")] Self::Stream(ref mut writer) => writer.poll_write_encrypted(cx, stream, buf).map_err(Into::into), #[cfg(feature = "aead-cipher")] Self::Aead(ref mut writer) => writer.poll_write_encrypted(cx, stream, buf).map_err(Into::into), Self::None => Pin::new(stream).poll_write(cx, buf).map_err(Into::into), #[cfg(feature = "aead-cipher-2022")] Self::Aead2022(ref mut writer) => writer.poll_write_encrypted(cx, stream, buf).map_err(Into::into), } } /// Get sent IV (Stream) or Salt (AEAD, AEAD2022) pub fn nonce(&self) -> &[u8] { match *self { #[cfg(feature = "stream-cipher")] Self::Stream(ref writer) => writer.iv(), #[cfg(feature = "aead-cipher")] Self::Aead(ref writer) => writer.salt(), Self::None => &[], #[cfg(feature = "aead-cipher-2022")] Self::Aead2022(ref writer) => writer.salt(), } } /// Set request nonce (for server stream of AEAD2022) pub fn set_request_nonce(&mut self, request_nonce: Bytes) { match *self { #[cfg(feature = "aead-cipher-2022")] Self::Aead2022(ref mut writer) => writer.set_request_salt(request_nonce), _ => { let _ = request_nonce; panic!("only AEAD-2022 cipher could send request salt"); } } } /// Reset cipher with authenticated user key pub fn reset_cipher_with_key(&mut self, key: &[u8]) { match *self { #[cfg(feature = "aead-cipher-2022")] Self::Aead2022(ref mut writer) => writer.reset_cipher_with_key(key), _ => { let _ = key; panic!("only AEAD-2022 cipher could authenticate with multiple users"); } } } } /// A bidirectional stream for read/write encrypted data in shadowsocks' tunnel pub struct CryptoStream { stream: S, dec: DecryptedReader, enc: EncryptedWriter, method: CipherKind, has_handshaked: bool, } impl fmt::Debug for CryptoStream { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("CryptoStream") .field("method", &self.method) .field("has_handshaked", &self.has_handshaked) .finish() } } impl CryptoStream { /// Create a new CryptoStream with the underlying stream connection pub fn from_stream(context: &Context, stream: S, stream_ty: StreamType, method: CipherKind, key: &[u8]) -> Self { const EMPTY_IDENTITY: [Bytes; 0] = []; Self::from_stream_with_identity(context, stream, stream_ty, method, key, &EMPTY_IDENTITY, None) } /// Create a new CryptoStream with the underlying stream connection pub fn from_stream_with_identity( context: &Context, stream: S, stream_ty: StreamType, method: CipherKind, key: &[u8], identity_keys: &[Bytes], user_manager: Option>, ) -> Self { let category = method.category(); if category == CipherCategory::None { // Fast-path for none cipher return Self::new_none(stream, method); } let prev_len = match category { #[cfg(feature = "stream-cipher")] CipherCategory::Stream => method.iv_len(), #[cfg(feature = "aead-cipher")] CipherCategory::Aead => method.salt_len(), CipherCategory::None => 0, #[cfg(feature = "aead-cipher-2022")] CipherCategory::Aead2022 => method.salt_len(), }; let iv = match category { #[cfg(feature = "stream-cipher")] CipherCategory::Stream => { let mut local_iv = vec![0u8; prev_len]; context.generate_nonce(method, &mut local_iv, true); trace!("generated Stream cipher IV {:?}", ByteStr::new(&local_iv)); local_iv } #[cfg(feature = "aead-cipher")] CipherCategory::Aead => { let mut local_salt = vec![0u8; prev_len]; context.generate_nonce(method, &mut local_salt, true); trace!("generated AEAD cipher salt {:?}", ByteStr::new(&local_salt)); local_salt } CipherCategory::None => { debug_assert_eq!(prev_len, 0); let _ = context; Vec::new() } #[cfg(feature = "aead-cipher-2022")] CipherCategory::Aead2022 => { // AEAD-2022 has a request-salt in respond header, so the generated salt doesn't need to be remembered. let mut local_salt = vec![0u8; prev_len]; context.generate_nonce(method, &mut local_salt, false); trace!("generated AEAD cipher salt {:?}", ByteStr::new(&local_salt)); local_salt } }; Self { stream, dec: DecryptedReader::with_user_manager(stream_ty, method, key, user_manager), enc: EncryptedWriter::with_identity(stream_ty, method, key, &iv, identity_keys), method, has_handshaked: false, } } fn new_none(stream: S, method: CipherKind) -> Self { Self { stream, dec: DecryptedReader::None, enc: EncryptedWriter::None, method, has_handshaked: false, } } /// Return a reference to the underlying stream pub fn get_ref(&self) -> &S { &self.stream } /// Return a mutable reference to the underlying stream pub fn get_mut(&mut self) -> &mut S { &mut self.stream } /// Consume the CryptoStream and return the internal stream instance pub fn into_inner(self) -> S { self.stream } /// Get received IV (Stream) or Salt (AEAD, AEAD2022) #[inline] pub fn received_nonce(&self) -> Option<&[u8]> { self.dec.nonce() } /// Get sent IV (Stream) or Salt (AEAD, AEAD2022) #[inline] pub fn sent_nonce(&self) -> &[u8] { self.enc.nonce() } /// Received request salt from server (AEAD2022) #[inline] pub fn received_request_nonce(&self) -> Option<&[u8]> { self.dec.request_nonce() } /// Set request nonce (for server stream of AEAD2022) #[inline] pub fn set_request_nonce(&mut self, request_nonce: &[u8]) { self.enc.set_request_nonce(Bytes::copy_from_slice(request_nonce)) } #[cfg(feature = "aead-cipher-2022")] pub(crate) fn set_request_nonce_with_received(&mut self) -> bool { match self.dec.nonce() { None => false, Some(nonce) => { self.enc.set_request_nonce(Bytes::copy_from_slice(nonce)); true } } } /// Get remaining bytes in the current data chunk /// /// Returning (DataChunkCount, RemainingBytes) #[cfg(feature = "aead-cipher-2022")] pub(crate) fn current_data_chunk_remaining(&self) -> (u64, usize) { match self.dec { DecryptedReader::Aead2022(ref dec) => dec.current_data_chunk_remaining(), _ => { panic!("only AEAD-2022 protocol has data chunk counter"); } } } } /// Cryptographic reader trait pub trait CryptoRead { fn poll_read_decrypted( self: Pin<&mut Self>, cx: &mut task::Context<'_>, context: &Context, buf: &mut ReadBuf<'_>, ) -> Poll>; } /// Cryptographic writer trait pub trait CryptoWrite { fn poll_write_encrypted( self: Pin<&mut Self>, cx: &mut task::Context<'_>, buf: &[u8], ) -> Poll>; } impl CryptoStream { /// Get encryption method pub fn method(&self) -> CipherKind { self.method } } impl CryptoRead for CryptoStream where S: AsyncRead + AsyncWrite + Unpin, { /// Attempt to read decrypted data from `stream` #[inline] fn poll_read_decrypted( mut self: Pin<&mut Self>, cx: &mut task::Context<'_>, context: &Context, buf: &mut ReadBuf<'_>, ) -> Poll> { let Self { ref mut dec, ref mut enc, ref mut stream, ref mut has_handshaked, .. } = *self; ready!(dec.poll_read_decrypted(cx, context, stream, buf))?; if !*has_handshaked && dec.handshaked() { *has_handshaked = true; // Reset writer cipher with authenticated user key if let Some(user_key) = dec.user_key() { enc.reset_cipher_with_key(user_key); } } Ok(()).into() } } impl CryptoWrite for CryptoStream where S: AsyncRead + AsyncWrite + Unpin, { /// Attempt to write encrypted data to `stream` #[inline] fn poll_write_encrypted( mut self: Pin<&mut Self>, cx: &mut task::Context<'_>, buf: &[u8], ) -> Poll> { let Self { ref mut enc, ref mut stream, .. } = *self; enc.poll_write_encrypted(cx, stream, buf) } } impl CryptoStream where S: AsyncRead + AsyncWrite + Unpin, { /// Polls `flush` on the underlying stream #[inline] pub fn poll_flush(&mut self, cx: &mut task::Context<'_>) -> Poll> { Pin::new(&mut self.stream).poll_flush(cx).map_err(Into::into) } /// Polls `shutdown` on the underlying stream #[inline] pub fn poll_shutdown(&mut self, cx: &mut task::Context<'_>) -> Poll> { Pin::new(&mut self.stream).poll_shutdown(cx).map_err(Into::into) } } ================================================ FILE: crates/shadowsocks/src/relay/tcprelay/mod.rs ================================================ //! TCP relay pub use self::{ proxy_listener::ProxyListener, proxy_stream::{ProxyClientStream, ProxyServerStream}, }; #[cfg(feature = "aead-cipher")] mod aead; #[cfg(feature = "aead-cipher-2022")] mod aead_2022; pub mod crypto_io; pub mod proxy_listener; pub mod proxy_stream; #[cfg(feature = "stream-cipher")] mod stream; pub mod utils; /// Connection direction type #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum StreamType { /// Connection initiated from client to server Client, /// Connection initiated from server to client Server, } ================================================ FILE: crates/shadowsocks/src/relay/tcprelay/proxy_listener.rs ================================================ //! A TCP listener for accepting shadowsocks' client connection use std::{ io, net::SocketAddr, sync::{Arc, LazyLock}, }; use tokio::{ io::{AsyncRead, AsyncWrite}, net::TcpStream, }; use crate::{ config::{ServerAddr, ServerConfig, ServerUserManager}, context::SharedContext, crypto::CipherKind, net::{AcceptOpts, TcpListener}, relay::tcprelay::proxy_stream::server::ProxyServerStream, }; /// A TCP listener for accepting shadowsocks' client connection #[derive(Debug)] pub struct ProxyListener { listener: TcpListener, method: CipherKind, key: Box<[u8]>, context: SharedContext, user_manager: Option>, } static DEFAULT_ACCEPT_OPTS: LazyLock = LazyLock::new(Default::default); impl ProxyListener { /// Create a `ProxyListener` binding to a specific address pub async fn bind(context: SharedContext, svr_cfg: &ServerConfig) -> io::Result { Self::bind_with_opts(context, svr_cfg, DEFAULT_ACCEPT_OPTS.clone()).await } /// Create a `ProxyListener` binding to a specific address with opts pub async fn bind_with_opts( context: SharedContext, svr_cfg: &ServerConfig, accept_opts: AcceptOpts, ) -> io::Result { let listener = match svr_cfg.tcp_external_addr() { ServerAddr::SocketAddr(sa) => TcpListener::bind_with_opts(sa, accept_opts).await?, ServerAddr::DomainName(domain, port) => { lookup_then!(&context, domain, *port, |addr| { TcpListener::bind_with_opts(&addr, accept_opts.clone()).await })? .1 } }; Ok(Self::from_listener(context, listener, svr_cfg)) } /// Create a `ProxyListener` from a `TcpListener` pub fn from_listener(context: SharedContext, listener: TcpListener, svr_cfg: &ServerConfig) -> Self { Self { listener, method: svr_cfg.method(), key: svr_cfg.key().to_vec().into_boxed_slice(), context, user_manager: svr_cfg.clone_user_manager(), } } /// Accepts a shadowsocks' client connection #[inline] pub async fn accept(&self) -> io::Result<(ProxyServerStream, SocketAddr)> { self.accept_map(|s| s).await } /// Accepts a shadowsocks' client connection and maps the accepted `TcpStream` to another stream type pub async fn accept_map(&self, map_fn: F) -> io::Result<(ProxyServerStream, SocketAddr)> where F: FnOnce(TcpStream) -> S, S: AsyncRead + AsyncWrite + Unpin, { let (stream, peer_addr) = self.listener.accept().await?; let stream = map_fn(stream); // Create a ProxyServerStream and read the target address from it let stream = ProxyServerStream::from_stream_with_user_manager( self.context.clone(), stream, self.method, &self.key, self.user_manager.clone(), ); Ok((stream, peer_addr)) } /// Get local binded address pub fn local_addr(&self) -> io::Result { self.listener.local_addr() } /// Get reference to the internal listener pub fn get_ref(&self) -> &TcpListener { &self.listener } /// Consumes the `ProxyListener` and return the internal listener pub fn into_inner(self) -> TcpListener { self.listener } } ================================================ FILE: crates/shadowsocks/src/relay/tcprelay/proxy_stream/client.rs ================================================ //! TCP stream for communicating with shadowsocks' proxy server use std::{ io::{self, ErrorKind}, pin::Pin, sync::LazyLock, task::{self, Poll}, }; use bytes::{BufMut, BytesMut}; use cfg_if::cfg_if; use futures::ready; use log::trace; use pin_project::pin_project; use tokio::{ io::{AsyncRead, AsyncWrite, ReadBuf}, time, }; #[cfg(feature = "aead-cipher-2022")] use crate::relay::get_aead_2022_padding_size; use crate::{ config::ServerConfig, context::SharedContext, crypto::CipherKind, net::{ConnectOpts, TcpStream as OutboundTcpStream}, relay::{ socks5::Address, tcprelay::crypto_io::{CryptoRead, CryptoStream, CryptoWrite, StreamType}, }, }; #[derive(Debug)] enum ProxyClientStreamWriteState { Connect(Address), Connecting(BytesMut), Connected, } #[derive(Debug)] enum ProxyClientStreamReadState { #[cfg(feature = "aead-cipher-2022")] CheckRequestNonce, Established, } /// A stream for sending / receiving data stream from remote server via shadowsocks' proxy server #[derive(Debug)] #[pin_project] pub struct ProxyClientStream { #[pin] stream: CryptoStream, writer_state: ProxyClientStreamWriteState, reader_state: ProxyClientStreamReadState, context: SharedContext, } static DEFAULT_CONNECT_OPTS: LazyLock = LazyLock::new(Default::default); impl ProxyClientStream { /// Connect to target `addr` via shadowsocks' server configured by `svr_cfg` pub async fn connect(context: SharedContext, svr_cfg: &ServerConfig, addr: A) -> io::Result where A: Into
, { Self::connect_with_opts(context, svr_cfg, addr, &DEFAULT_CONNECT_OPTS).await } /// Connect to target `addr` via shadowsocks' server configured by `svr_cfg` pub async fn connect_with_opts( context: SharedContext, svr_cfg: &ServerConfig, addr: A, opts: &ConnectOpts, ) -> io::Result where A: Into
, { Self::connect_with_opts_map(context, svr_cfg, addr, opts, |s| s).await } } impl ProxyClientStream where S: AsyncRead + AsyncWrite + Unpin, { /// Connect to target `addr` via shadowsocks' server configured by `svr_cfg`, maps `TcpStream` to customized stream with `map_fn` pub async fn connect_map( context: SharedContext, svr_cfg: &ServerConfig, addr: A, map_fn: F, ) -> io::Result where A: Into
, F: FnOnce(OutboundTcpStream) -> S, { Self::connect_with_opts_map(context, svr_cfg, addr, &DEFAULT_CONNECT_OPTS, map_fn).await } /// Connect to target `addr` via shadowsocks' server configured by `svr_cfg`, maps `TcpStream` to customized stream with `map_fn` pub async fn connect_with_opts_map( context: SharedContext, svr_cfg: &ServerConfig, addr: A, opts: &ConnectOpts, map_fn: F, ) -> io::Result where A: Into
, F: FnOnce(OutboundTcpStream) -> S, { let stream = match svr_cfg.timeout() { Some(d) => { match time::timeout( d, OutboundTcpStream::connect_server_with_opts(&context, svr_cfg.tcp_external_addr(), opts), ) .await { Ok(Ok(s)) => s, Ok(Err(e)) => return Err(e), Err(..) => { return Err(io::Error::new( ErrorKind::TimedOut, format!("connect {} timeout", svr_cfg.addr()), )); } } } None => OutboundTcpStream::connect_server_with_opts(&context, svr_cfg.tcp_external_addr(), opts).await?, }; trace!( "connected tcp remote {} (outbound: {}) with {:?}", svr_cfg.addr(), svr_cfg.tcp_external_addr(), opts ); Ok(Self::from_stream(context, map_fn(stream), svr_cfg, addr)) } /// Create a `ProxyClientStream` with a connected `stream` to a shadowsocks' server /// /// NOTE: `stream` must be connected to the server with the same configuration as `svr_cfg`, otherwise strange errors would occurs pub fn from_stream(context: SharedContext, stream: S, svr_cfg: &ServerConfig, addr: A) -> Self where A: Into
, { let addr = addr.into(); let stream = CryptoStream::from_stream_with_identity( &context, stream, StreamType::Client, svr_cfg.method(), svr_cfg.key(), svr_cfg.identity_keys(), None, ); #[cfg(not(feature = "aead-cipher-2022"))] let reader_state = ProxyClientStreamReadState::Established; #[cfg(feature = "aead-cipher-2022")] let reader_state = if svr_cfg.method().is_aead_2022() { // AEAD 2022 has a respond header ProxyClientStreamReadState::CheckRequestNonce } else { ProxyClientStreamReadState::Established }; Self { stream, writer_state: ProxyClientStreamWriteState::Connect(addr), reader_state, context, } } /// Get reference to the underlying stream pub fn get_ref(&self) -> &S { self.stream.get_ref() } /// Get mutable reference to the underlying stream pub fn get_mut(&mut self) -> &mut S { self.stream.get_mut() } /// Consumes the `ProxyClientStream` and return the underlying stream pub fn into_inner(self) -> S { self.stream.into_inner() } } impl AsyncRead for ProxyClientStream where S: AsyncRead + AsyncWrite + Unpin, { #[inline] fn poll_read(self: Pin<&mut Self>, cx: &mut task::Context<'_>, buf: &mut ReadBuf<'_>) -> Poll> { #[allow(unused_mut)] let mut this = self.project(); #[allow(clippy::never_loop)] loop { match this.reader_state { ProxyClientStreamReadState::Established => { return this .stream .poll_read_decrypted(cx, this.context, buf) .map_err(Into::into); } #[cfg(feature = "aead-cipher-2022")] ProxyClientStreamReadState::CheckRequestNonce => { ready!(this.stream.as_mut().poll_read_decrypted(cx, this.context, buf))?; // REQUEST_NONCE should be in the respond packet (header) of AEAD-2022. // // If received_request_nonce() is None, then: // 1. method.salt_len() == 0, no checking required. // 2. TCP stream read() returns EOF before receiving the header, no checking required. // // poll_read_decrypted will wait until the first non-zero size data chunk. let (data_chunk_count, _) = this.stream.current_data_chunk_remaining(); if data_chunk_count > 0 { // data_chunk_count > 0, so the reader received at least 1 data chunk. let sent_nonce = this.stream.sent_nonce(); let sent_nonce = if sent_nonce.is_empty() { None } else { Some(sent_nonce) }; if sent_nonce != this.stream.received_request_nonce() { return Err(io::Error::other("received TCP response header with unmatched salt")).into(); } *(this.reader_state) = ProxyClientStreamReadState::Established; } return Ok(()).into(); } } } } } #[inline] fn make_first_packet_buffer(method: CipherKind, addr: &Address, buf: &[u8]) -> BytesMut { // Target Address should be sent with the first packet together, // which would prevent from being detected. let addr_length = addr.serialized_len(); let mut buffer = BytesMut::new(); cfg_if! { if #[cfg(feature = "aead-cipher-2022")] { let padding_size = get_aead_2022_padding_size(buf); let header_length = if method.is_aead_2022() { addr_length + 2 + padding_size + buf.len() } else { addr_length + buf.len() }; } else { let _ = method; let header_length = addr_length + buf.len(); } } buffer.reserve(header_length); // STREAM / AEAD / AEAD2022 protocol, append the Address before payload addr.write_to_buf(&mut buffer); #[cfg(feature = "aead-cipher-2022")] if method.is_aead_2022() { buffer.put_u16(padding_size as u16); if padding_size > 0 { unsafe { buffer.advance_mut(padding_size); } } } buffer.put_slice(buf); buffer } impl AsyncWrite for ProxyClientStream where S: AsyncRead + AsyncWrite + Unpin, { fn poll_write(self: Pin<&mut Self>, cx: &mut task::Context<'_>, buf: &[u8]) -> Poll> { let this = self.project(); loop { match this.writer_state { &mut ProxyClientStreamWriteState::Connect(ref addr) => { let buffer = make_first_packet_buffer(this.stream.method(), addr, buf); // Save the concatenated buffer before it is written successfully. // APIs require buffer to be kept alive before Poll::Ready // // Proactor APIs like IOCP on Windows, pointers of buffers have to be kept alive // before IO completion. *(this.writer_state) = ProxyClientStreamWriteState::Connecting(buffer); } &mut ProxyClientStreamWriteState::Connecting(ref buffer) => { let n = ready!(this.stream.poll_write_encrypted(cx, buffer))?; // In general, poll_write_encrypted should perform like write_all. debug_assert!(n == buffer.len()); *(this.writer_state) = ProxyClientStreamWriteState::Connected; // NOTE: // poll_write will return Ok(0) if buf.len() == 0 // But for the first call, this function will eventually send the handshake packet (IV/Salt + ADDR) to the remote address. // // https://github.com/shadowsocks/shadowsocks-rust/issues/232 // // For protocols that requires *Server Hello* message, like FTP, clients won't send anything to the server until server sends handshake messages. // This could be achieved by calling poll_write with an empty input buffer. return Ok(buf.len()).into(); } ProxyClientStreamWriteState::Connected => { return this.stream.poll_write_encrypted(cx, buf).map_err(Into::into); } } } } #[inline] fn poll_flush(self: Pin<&mut Self>, cx: &mut task::Context<'_>) -> Poll> { self.project().stream.poll_flush(cx).map_err(Into::into) } #[inline] fn poll_shutdown(self: Pin<&mut Self>, cx: &mut task::Context<'_>) -> Poll> { self.project().stream.poll_shutdown(cx).map_err(Into::into) } } ================================================ FILE: crates/shadowsocks/src/relay/tcprelay/proxy_stream/mod.rs ================================================ //! Stream interface for communicating with shadowsocks proxy servers // pub use self::{ // client::{ProxyClientStream, ProxyClientStreamReadHalf, ProxyClientStreamWriteHalf}, // server::{ProxyServerStream, ProxyServerStreamReadHalf, ProxyServerStreamWriteHalf}, // }; pub use self::{client::ProxyClientStream, server::ProxyServerStream}; pub mod client; pub mod protocol; pub mod server; ================================================ FILE: crates/shadowsocks/src/relay/tcprelay/proxy_stream/protocol/mod.rs ================================================ //! Shadowsocks TCP protocol use std::io; use bytes::BufMut; use tokio::io::AsyncRead; use crate::{ crypto::{CipherCategory, CipherKind}, relay::socks5::Address, }; pub use self::v1::{StreamTcpRequestHeader, StreamTcpRequestHeaderRef}; #[cfg(feature = "aead-cipher-2022")] pub use self::v2::{Aead2022TcpRequestHeader, Aead2022TcpRequestHeaderRef}; pub mod v1; #[cfg(feature = "aead-cipher-2022")] pub mod v2; #[derive(Debug)] pub enum TcpRequestHeader { Stream(StreamTcpRequestHeader), #[cfg(feature = "aead-cipher-2022")] Aead2022(Aead2022TcpRequestHeader), } impl TcpRequestHeader { pub async fn read_from(method: CipherKind, reader: &mut R) -> io::Result { match method.category() { CipherCategory::None => Ok(Self::Stream(StreamTcpRequestHeader::read_from(reader).await?)), #[cfg(feature = "aead-cipher")] CipherCategory::Aead => Ok(Self::Stream(StreamTcpRequestHeader::read_from(reader).await?)), #[cfg(feature = "stream-cipher")] CipherCategory::Stream => Ok(Self::Stream(StreamTcpRequestHeader::read_from(reader).await?)), #[cfg(feature = "aead-cipher-2022")] CipherCategory::Aead2022 => Ok(Self::Aead2022(Aead2022TcpRequestHeader::read_from(reader).await?)), } } pub fn write_to_buf(&self, buf: &mut B) { match *self { Self::Stream(ref h) => h.write_to_buf(buf), #[cfg(feature = "aead-cipher-2022")] Self::Aead2022(ref h) => h.write_to_buf(buf), } } pub fn addr(self) -> Address { match self { Self::Stream(h) => h.addr, #[cfg(feature = "aead-cipher-2022")] Self::Aead2022(h) => h.addr, } } pub fn addr_ref(&self) -> &Address { match *self { Self::Stream(ref h) => &h.addr, #[cfg(feature = "aead-cipher-2022")] Self::Aead2022(ref h) => &h.addr, } } pub fn serialized_len(&self) -> usize { match *self { Self::Stream(ref h) => h.serialized_len(), #[cfg(feature = "aead-cipher-2022")] Self::Aead2022(ref h) => h.serialized_len(), } } } #[derive(Debug)] pub enum TcpRequestHeaderRef<'a> { Stream(StreamTcpRequestHeaderRef<'a>), #[cfg(feature = "aead-cipher-2022")] Aead2022(Aead2022TcpRequestHeaderRef<'a>), } impl TcpRequestHeaderRef<'_> { pub fn write_to_buf(&self, buf: &mut B) { match *self { TcpRequestHeaderRef::Stream(ref h) => h.write_to_buf(buf), #[cfg(feature = "aead-cipher-2022")] TcpRequestHeaderRef::Aead2022(ref h) => h.write_to_buf(buf), } } pub fn serialized_len(&self) -> usize { match *self { TcpRequestHeaderRef::Stream(ref h) => h.serialized_len(), #[cfg(feature = "aead-cipher-2022")] TcpRequestHeaderRef::Aead2022(ref h) => h.serialized_len(), } } } ================================================ FILE: crates/shadowsocks/src/relay/tcprelay/proxy_stream/protocol/v1.rs ================================================ //! Shadowsocks Stream / AEAD header protocol use std::io; use bytes::BufMut; use tokio::io::AsyncRead; use crate::relay::socks5::Address; #[derive(Debug)] pub struct StreamTcpRequestHeader { pub addr: Address, } impl StreamTcpRequestHeader { pub async fn read_from(reader: &mut R) -> io::Result { Ok(Self { addr: Address::read_from(reader).await?, }) } pub fn write_to_buf(&self, buf: &mut B) { StreamTcpRequestHeaderRef { addr: &self.addr }.write_to_buf(buf) } pub fn serialized_len(&self) -> usize { StreamTcpRequestHeaderRef { addr: &self.addr }.serialized_len() } } #[derive(Debug)] pub struct StreamTcpRequestHeaderRef<'a> { pub addr: &'a Address, } impl StreamTcpRequestHeaderRef<'_> { pub fn write_to_buf(&self, buf: &mut B) { self.addr.write_to_buf(buf); } pub fn serialized_len(&self) -> usize { self.addr.serialized_len() } } ================================================ FILE: crates/shadowsocks/src/relay/tcprelay/proxy_stream/protocol/v2.rs ================================================ //! Shadowsocks AEAD 2022 header protocol use std::io; use bytes::BufMut; use tokio::io::{AsyncRead, AsyncReadExt}; use crate::relay::Address; /// Maximum padding length pub const MAX_PADDING_SIZE: usize = 900; /// Stream (Client & Server) timestamp max differences (ABS) pub const SERVER_STREAM_TIMESTAMP_MAX_DIFF: u64 = 30; /// TCP Request Header /// /// +-------+-------+-------+-------+-------+-------+-------+-------+-------+ /// | ADDR (Variable ...) /// +-------+-------+-------+-------+-------+-------+-------+-------+-------+ /// | PADDING SIZE | PADDING (Variable ...) /// +-------+-------+-------+-------+-------+-------+-------+-------+-------+ #[derive(Debug, Clone)] pub struct Aead2022TcpRequestHeader { pub addr: Address, pub padding_size: u16, } impl Aead2022TcpRequestHeader { pub async fn read_from(reader: &mut R) -> io::Result { let addr = Address::read_from(reader).await?; let mut padding_size_buffer = [0u8; 2]; reader.read_exact(&mut padding_size_buffer).await?; let padding_size = u16::from_be_bytes(padding_size_buffer); if padding_size > 0 { let mut take_reader = reader.take(padding_size as u64); let mut buffer = [0u8; 64]; loop { match take_reader.read(&mut buffer).await { Ok(0) => break, Ok(..) => continue, Err(err) => return Err(err), } } } Ok(Self { addr, padding_size }) } pub fn write_to_buf(&self, buf: &mut B) { Aead2022TcpRequestHeaderRef { addr: &self.addr, padding_size: self.padding_size, } .write_to_buf(buf) } pub fn serialized_len(&self) -> usize { Aead2022TcpRequestHeaderRef { addr: &self.addr, padding_size: self.padding_size, } .serialized_len() } } #[derive(Debug)] pub struct Aead2022TcpRequestHeaderRef<'a> { pub addr: &'a Address, pub padding_size: u16, } impl Aead2022TcpRequestHeaderRef<'_> { pub fn write_to_buf(&self, buf: &mut B) { assert!( self.padding_size as usize <= MAX_PADDING_SIZE, "padding length must be in [0, {MAX_PADDING_SIZE}]" ); buf.put_u16(self.padding_size); if self.padding_size > 0 { unsafe { buf.advance_mut(self.padding_size as usize); } } } pub fn serialized_len(&self) -> usize { self.addr.serialized_len() + 2 + self.padding_size as usize } } ================================================ FILE: crates/shadowsocks/src/relay/tcprelay/proxy_stream/server.rs ================================================ //! A TCP stream for communicating with shadowsocks' proxy client use std::{ io, pin::Pin, sync::Arc, task::{self, Poll}, }; use bytes::Bytes; use futures::ready; use pin_project::pin_project; use tokio::io::{AsyncRead, AsyncWrite, ReadBuf}; use crate::{ config::ServerUserManager, context::SharedContext, crypto::CipherKind, relay::{ socks5::Address, tcprelay::{ crypto_io::{CryptoRead, CryptoStream, CryptoWrite, StreamType}, proxy_stream::protocol::TcpRequestHeader, }, }, }; #[derive(Debug)] enum ProxyServerStreamWriteState { #[cfg(feature = "aead-cipher-2022")] PrepareHeader(Option), Established, } /// A stream for communicating with shadowsocks' proxy client #[derive(Debug)] #[pin_project] pub struct ProxyServerStream { #[pin] stream: CryptoStream, context: SharedContext, writer_state: ProxyServerStreamWriteState, has_handshaked: bool, } impl ProxyServerStream { /// Create a `ProxyServerStream` from a connection stream pub fn from_stream(context: SharedContext, stream: S, method: CipherKind, key: &[u8]) -> Self { Self::from_stream_with_user_manager(context, stream, method, key, None) } /// Create a `ProxyServerStream` from a connection stream /// /// Set `user_manager` to enable support of verifying EIH users. pub fn from_stream_with_user_manager( context: SharedContext, stream: S, method: CipherKind, key: &[u8], user_manager: Option>, ) -> Self { #[cfg(feature = "aead-cipher-2022")] let writer_state = if method.is_aead_2022() { ProxyServerStreamWriteState::PrepareHeader(None) } else { ProxyServerStreamWriteState::Established }; #[cfg(not(feature = "aead-cipher-2022"))] let writer_state = ProxyServerStreamWriteState::Established; const EMPTY_IDENTITY: [Bytes; 0] = []; Self { stream: CryptoStream::from_stream_with_identity( &context, stream, StreamType::Server, method, key, &EMPTY_IDENTITY, user_manager, ), context, writer_state, has_handshaked: false, } } /// Get reference of the internal stream pub fn get_ref(&self) -> &S { self.stream.get_ref() } /// Get mutable reference of the internal stream pub fn get_mut(&mut self) -> &mut S { self.stream.get_mut() } /// Consumes the object and return the internal stream pub fn into_inner(self) -> S { self.stream.into_inner() } } impl ProxyServerStream where S: AsyncRead + AsyncWrite + Unpin, { /// Handshaking. Getting the destination address from client /// /// This method should be called only once after accepted. pub async fn handshake(&mut self) -> io::Result
{ if self.has_handshaked { return Err(io::Error::other("stream is already handshaked")); } self.has_handshaked = true; let header = TcpRequestHeader::read_from(self.stream.method(), self).await?; #[cfg(feature = "aead-cipher-2022")] if let TcpRequestHeader::Aead2022(ref header) = header { use log::warn; // AEAD-2022 SPEC // // Padding: If the client is not sending payload along with the header, a random padding MUST be added. // // Check here preventing security risk causing by misimplementation clients. if header.padding_size == 0 { let (chunk_count, chunk_remaining) = self.stream.current_data_chunk_remaining(); if chunk_count == 1 && chunk_remaining == 0 { // Header is the end of the data chunk, so no payload is in the first chunk, and padding == 0. // REJECT insecure clients. return Err(io::Error::other("no payload in first data chunk, and padding is 0")); } else if chunk_count > 1 { warn!( "tcp header is separated in {} chunks, client is not following the AEAD-2022 spec", chunk_count, ); } } } Ok(header.addr()) } } impl AsyncRead for ProxyServerStream where S: AsyncRead + AsyncWrite + Unpin, { #[inline] fn poll_read(self: Pin<&mut Self>, cx: &mut task::Context<'_>, buf: &mut ReadBuf<'_>) -> Poll> { if !self.has_handshaked { return Err(io::Error::other("stream is not handshaked yet")).into(); } let this = self.project(); ready!(this.stream.poll_read_decrypted(cx, this.context, buf))?; // Wakeup writer task because we have already received the salt #[cfg(feature = "aead-cipher-2022")] if let ProxyServerStreamWriteState::PrepareHeader(waker) = this.writer_state && let Some(waker) = waker.take() { waker.wake(); } Ok(()).into() } } impl AsyncWrite for ProxyServerStream where S: AsyncRead + AsyncWrite + Unpin, { #[inline] fn poll_write(self: Pin<&mut Self>, cx: &mut task::Context<'_>, buf: &[u8]) -> Poll> { #[allow(unused_mut)] let mut this = self.project(); #[allow(clippy::never_loop)] loop { match *this.writer_state { ProxyServerStreamWriteState::Established => { return this.stream.poll_write_encrypted(cx, buf).map_err(Into::into); } #[cfg(feature = "aead-cipher-2022")] ProxyServerStreamWriteState::PrepareHeader(ref mut waker) => { if this.stream.set_request_nonce_with_received() { *(this.writer_state) = ProxyServerStreamWriteState::Established; } else { // Reader didn't receive the salt from client yet. if let Some(waker) = waker.take() && !waker.will_wake(cx.waker()) { waker.wake(); } *waker = Some(cx.waker().clone()); return Poll::Pending; } } } } } #[inline] fn poll_flush(self: Pin<&mut Self>, cx: &mut task::Context<'_>) -> Poll> { self.project().stream.poll_flush(cx).map_err(Into::into) } #[inline] fn poll_shutdown(self: Pin<&mut Self>, cx: &mut task::Context<'_>) -> Poll> { self.project().stream.poll_shutdown(cx).map_err(Into::into) } } ================================================ FILE: crates/shadowsocks/src/relay/tcprelay/stream.rs ================================================ //! Stream protocol implementation use std::{ io::{self, ErrorKind}, marker::Unpin, pin::Pin, slice, task::{self, Poll}, }; use byte_string::ByteStr; use bytes::{BufMut, Bytes, BytesMut}; use futures::ready; use log::trace; use tokio::io::{AsyncRead, AsyncWrite, ReadBuf}; use crate::{ context::Context, crypto::{CipherKind, v1::Cipher}, }; /// Stream protocol error #[derive(thiserror::Error, Debug)] pub enum ProtocolError { #[error(transparent)] IoError(#[from] io::Error), #[error("decrypt failed")] DecryptError, } /// Stream protocol result pub type ProtocolResult = Result; impl From for io::Error { fn from(e: ProtocolError) -> Self { match e { ProtocolError::IoError(err) => err, _ => Self::other(e), } } } enum DecryptReadState { WaitIv { key: Bytes }, Read, } /// Reader wrapper that will decrypt data automatically pub struct DecryptedReader { state: DecryptReadState, cipher: Option, buffer: BytesMut, method: CipherKind, iv: Option, has_handshaked: bool, } impl DecryptedReader { pub fn new(method: CipherKind, key: &[u8]) -> Self { if method.iv_len() > 0 { Self { state: DecryptReadState::WaitIv { key: Bytes::copy_from_slice(key), }, cipher: None, buffer: BytesMut::with_capacity(method.iv_len()), method, iv: None, has_handshaked: false, } } else { Self { state: DecryptReadState::Read, cipher: Some(Cipher::new(method, key, &[])), buffer: BytesMut::new(), method, iv: Some(Bytes::new()), has_handshaked: false, } } } pub fn iv(&self) -> Option<&[u8]> { self.iv.as_deref() } /// Attempt to read decrypted data from reader pub fn poll_read_decrypted( &mut self, cx: &mut task::Context<'_>, context: &Context, stream: &mut S, buf: &mut ReadBuf<'_>, ) -> Poll> where S: AsyncRead + Unpin + ?Sized, { loop { match self.state { DecryptReadState::WaitIv { ref key } => { let key = unsafe { &*(key.as_ref() as *const _) }; ready!(self.poll_read_iv(cx, context, stream, key))?; self.buffer.clear(); self.buffer.truncate(0); self.state = DecryptReadState::Read; self.has_handshaked = true; } DecryptReadState::Read => { let before_n = buf.filled().len(); ready!(Pin::new(stream).poll_read(cx, buf))?; let after_n = buf.filled().len(); if before_n == after_n { return Ok(()).into(); } let m = &mut buf.filled_mut()[before_n..]; let cipher = self.cipher.as_mut().expect("cipher is None"); if !cipher.decrypt_packet(m) { return Err(ProtocolError::DecryptError).into(); } return Ok(()).into(); } } } } fn poll_read_iv( &mut self, cx: &mut task::Context<'_>, context: &Context, stream: &mut S, key: &[u8], ) -> Poll> where S: AsyncRead + Unpin + ?Sized, { let iv_len = self.method.iv_len(); let n = ready!(self.poll_read_exact(cx, stream, iv_len))?; if n < iv_len { return Err(io::Error::from(ErrorKind::UnexpectedEof).into()).into(); } let iv = &self.buffer[..iv_len]; context.check_nonce_replay(self.method, iv)?; trace!("got stream iv {:?}", ByteStr::new(iv)); // Stores IV self.iv = Some(Bytes::copy_from_slice(iv)); let cipher = Cipher::new(self.method, key, iv); self.cipher = Some(cipher); Ok(()).into() } fn poll_read_exact(&mut self, cx: &mut task::Context<'_>, stream: &mut S, size: usize) -> Poll> where S: AsyncRead + Unpin + ?Sized, { assert!(size != 0); while self.buffer.len() < size { let remaining = size - self.buffer.len(); let buffer = &mut self.buffer.chunk_mut()[..remaining]; let mut read_buf = ReadBuf::uninit(unsafe { slice::from_raw_parts_mut(buffer.as_mut_ptr() as *mut _, remaining) }); ready!(Pin::new(&mut *stream).poll_read(cx, &mut read_buf))?; let n = read_buf.filled().len(); if n == 0 { if !self.buffer.is_empty() { return Err(ErrorKind::UnexpectedEof.into()).into(); } else { return Ok(0).into(); } } unsafe { self.buffer.advance_mut(n); } } Ok(size).into() } /// Check if handshake finished pub fn handshaked(&self) -> bool { self.has_handshaked } } enum EncryptWriteState { AssemblePacket, Writing { pos: usize }, } /// Writer wrapper that will encrypt data automatically pub struct EncryptedWriter { cipher: Cipher, buffer: BytesMut, state: EncryptWriteState, iv: Bytes, } impl EncryptedWriter { /// Creates a new EncryptedWriter pub fn new(method: CipherKind, key: &[u8], nonce: &[u8]) -> Self { // nonce should be sent with the first packet let mut buffer = BytesMut::with_capacity(nonce.len()); buffer.put(nonce); Self { cipher: Cipher::new(method, key, nonce), buffer, state: EncryptWriteState::AssemblePacket, iv: Bytes::copy_from_slice(nonce), } } /// IV pub fn iv(&self) -> &[u8] { self.iv.as_ref() } /// Attempt to write encrypted data into the writer pub fn poll_write_encrypted( &mut self, cx: &mut task::Context<'_>, stream: &mut S, buf: &[u8], ) -> Poll> where S: AsyncWrite + Unpin + ?Sized, { loop { match self.state { EncryptWriteState::AssemblePacket => { let n = self.buffer.len(); self.buffer.put_slice(buf); self.cipher.encrypt_packet(&mut self.buffer[n..]); self.state = EncryptWriteState::Writing { pos: 0 }; } EncryptWriteState::Writing { ref mut pos } => { while *pos < self.buffer.len() { let n = ready!(Pin::new(&mut *stream).poll_write(cx, &self.buffer[*pos..]))?; if n == 0 { return Err(io::Error::from(ErrorKind::UnexpectedEof).into()).into(); } *pos += n; } // Reset state self.state = EncryptWriteState::AssemblePacket; self.buffer.clear(); return Ok(buf.len()).into(); } } } } } ================================================ FILE: crates/shadowsocks/src/relay/tcprelay/utils.rs ================================================ //! Utilities for TCP relay //! //! The `CopyBuffer`, `Copy` and `CopyBidirection` are borrowed from the [tokio](https://github.com/tokio-rs/tokio) project. //! LICENSE MIT use std::{ fmt::{self, Debug}, future::Future, io, pin::Pin, task::{Context, Poll}, }; use futures::ready; use log::{debug, trace}; use pin_project::pin_project; use tokio::io::{AsyncRead, AsyncWrite, ReadBuf}; use crate::crypto::{CipherCategory, CipherKind}; struct CopyBuffer { read_done: bool, pos: usize, cap: usize, amt: u64, buf: Box<[u8]>, } impl Debug for CopyBuffer { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("CopyBuffer") .field("read_done", &self.read_done) .field("pos", &self.pos) .field("cap", &self.cap) .field("amt", &self.amt) .finish_non_exhaustive() } } impl CopyBuffer { fn new(buffer_size: usize) -> Self { Self { read_done: false, pos: 0, cap: 0, amt: 0, buf: vec![0; buffer_size].into_boxed_slice(), } } fn poll_copy( &mut self, cx: &mut Context<'_>, mut reader: Pin<&mut R>, mut writer: Pin<&mut W>, ) -> Poll> where R: AsyncRead + Unpin + ?Sized, W: AsyncWrite + Unpin + ?Sized, { loop { // If our buffer is empty, then we need to read some data to // continue. if self.pos == self.cap && !self.read_done { let me = &mut *self; let mut buf = ReadBuf::new(&mut me.buf); ready!(reader.as_mut().poll_read(cx, &mut buf))?; let n = buf.filled().len(); if n == 0 { self.read_done = true; } else { self.pos = 0; self.cap = n; } } // If our buffer has some data, let's write it out! while self.pos < self.cap { let me = &mut *self; let i = ready!(writer.as_mut().poll_write(cx, &me.buf[me.pos..me.cap]))?; if i == 0 { return Poll::Ready(Err(io::Error::new( io::ErrorKind::WriteZero, "write zero byte into writer", ))); } else { self.pos += i; self.amt += i as u64; } } // If we've written all the data and we've seen EOF, flush out the // data and finish the transfer. if self.pos == self.cap && self.read_done { ready!(writer.as_mut().poll_flush(cx))?; return Poll::Ready(Ok(self.amt)); } } } } /// A future that asynchronously copies the entire contents of a reader into a /// writer. #[derive(Debug)] #[pin_project] #[must_use = "futures do nothing unless you `.await` or poll them"] struct Copy<'a, R: ?Sized, W: ?Sized> { #[pin] reader: &'a mut R, #[pin] writer: &'a mut W, buf: CopyBuffer, } impl Future for Copy<'_, R, W> where R: AsyncRead + Unpin + ?Sized, W: AsyncWrite + Unpin + ?Sized, { type Output = io::Result; fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { let this = self.project(); this.buf.poll_copy(cx, this.reader, this.writer) } } /// Copy data from encrypted reader to plain writer pub async fn copy_from_encrypted(method: CipherKind, reader: &mut ER, writer: &mut PW) -> io::Result where ER: AsyncRead + Unpin + ?Sized, PW: AsyncWrite + Unpin + ?Sized, { Copy { reader, writer, buf: CopyBuffer::new(plain_read_buffer_size(method)), } .await } /// Copy data from plain reader to encrypted writer pub async fn copy_to_encrypted(method: CipherKind, reader: &mut PR, writer: &mut EW) -> io::Result where PR: AsyncRead + Unpin + ?Sized, EW: AsyncWrite + Unpin + ?Sized, { Copy { reader, writer, buf: CopyBuffer::new(plain_read_buffer_size(method)), } .await } fn plain_read_buffer_size(method: CipherKind) -> usize { match method.category() { #[cfg(feature = "aead-cipher")] CipherCategory::Aead => super::aead::MAX_PACKET_SIZE, #[cfg(feature = "stream-cipher")] CipherCategory::Stream => 1 << 14, CipherCategory::None => 1 << 14, #[cfg(feature = "aead-cipher-2022")] CipherCategory::Aead2022 => super::aead_2022::MAX_PACKET_SIZE, } } /// Create a buffer for reading from plain channel (not encrypted), for copying data into encrypted channel #[inline] pub fn alloc_plain_read_buffer(method: CipherKind) -> Box<[u8]> { vec![0u8; plain_read_buffer_size(method)].into_boxed_slice() } #[derive(Debug)] enum TransferState { Running(CopyBuffer), ShuttingDown(u64), Done(u64), } #[pin_project(project = CopyBidirectionalProj)] struct CopyBidirectional<'a, A: ?Sized, B: ?Sized> { #[pin] a: &'a mut A, #[pin] b: &'a mut B, a_to_b: TransferState, b_to_a: TransferState, } fn transfer_one_direction( cx: &mut Context<'_>, state: &mut TransferState, mut r: Pin<&mut A>, mut w: Pin<&mut B>, ) -> Poll> where A: AsyncRead + AsyncWrite + Unpin + ?Sized, B: AsyncRead + AsyncWrite + Unpin + ?Sized, { loop { match state { TransferState::Running(buf) => { let count = ready!(buf.poll_copy(cx, r.as_mut(), w.as_mut()))?; *state = TransferState::ShuttingDown(count); } TransferState::ShuttingDown(count) => { ready!(w.as_mut().poll_shutdown(cx))?; *state = TransferState::Done(*count); } TransferState::Done(count) => return Poll::Ready(Ok(*count)), } } } impl CopyBidirectional<'_, A, B> where A: AsyncRead + AsyncWrite + Unpin + ?Sized, B: AsyncRead + AsyncWrite + Unpin + ?Sized, { #[inline(always)] fn poll_impl(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { // Unpack self into mut refs to each field to avoid borrow check issues. let CopyBidirectionalProj { mut a, mut b, a_to_b, b_to_a, } = self.project(); let poll_a_to_b = transfer_one_direction(cx, a_to_b, a.as_mut(), b.as_mut())?; let poll_b_to_a = transfer_one_direction(cx, b_to_a, b.as_mut(), a.as_mut())?; // It is not a problem if ready! returns early because transfer_one_direction for the // other direction will keep returning TransferState::Done(count) in future calls to poll let a_to_b = ready!(poll_a_to_b); let b_to_a = ready!(poll_b_to_a); Poll::Ready(Ok((a_to_b, b_to_a))) } } impl Future for CopyBidirectional<'_, A, B> where A: AsyncRead + AsyncWrite + Unpin + ?Sized, B: AsyncRead + AsyncWrite + Unpin + ?Sized, { type Output = io::Result<(u64, u64)>; fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { match self.as_mut().poll_impl(cx) { Poll::Pending => Poll::Pending, Poll::Ready(r) => { match r { Ok(..) => { trace!( "copy bidirection ends, a_to_b: {:?}, b_to_a: {:?}", self.a_to_b, self.b_to_a ); } Err(ref err) => { debug!( "copy bidirection ends with error: {}, a_to_b: {:?}, b_to_a: {:?}", err, self.a_to_b, self.b_to_a ); } } Poll::Ready(r) } } } } /// Copies data in both directions between `encrypted` stream and `plain` stream. /// /// This function returns a future that will read from both streams, /// writing any data read to the opposing stream. /// This happens in both directions concurrently. /// /// If an EOF is observed on one stream, [`shutdown()`] will be invoked on /// the other, and reading from that stream will stop. Copying of data in /// the other direction will continue. /// /// The future will complete successfully once both directions of communication has been shut down. /// A direction is shut down when the reader reports EOF, /// at which point [`shutdown()`] is called on the corresponding writer. When finished, /// it will return a tuple of the number of bytes copied from encrypted to plain /// and the number of bytes copied from plain to encrypted, in that order. /// /// [`shutdown()`]: tokio::io::AsyncWriteExt::shutdown /// /// # Errors /// /// The future will immediately return an error if any IO operation on `encrypted` /// or `plain` returns an error. Some data read from either stream may be lost (not /// written to the other stream) in this case. /// /// # Return value /// /// Returns a tuple of bytes copied `encrypted` to `plain` and bytes copied `plain` to `encrypted`. pub async fn copy_encrypted_bidirectional( method: CipherKind, encrypted: &mut E, plain: &mut P, ) -> io::Result<(u64, u64)> where E: AsyncRead + AsyncWrite + Unpin + ?Sized, P: AsyncRead + AsyncWrite + Unpin + ?Sized, { CopyBidirectional { a: encrypted, b: plain, a_to_b: TransferState::Running(CopyBuffer::new(plain_read_buffer_size(method))), b_to_a: TransferState::Running(CopyBuffer::new(plain_read_buffer_size(method))), } .await } /// Copies data in both directions /// /// This function returns a future that will read from both streams, /// writing any data read to the opposing stream. /// This happens in both directions concurrently. /// /// If an EOF is observed on one stream, [`shutdown()`] will be invoked on /// the other, and reading from that stream will stop. Copying of data in /// the other direction will continue. /// /// The future will complete successfully once both directions of communication has been shut down. /// A direction is shut down when the reader reports EOF, /// at which point [`shutdown()`] is called on the corresponding writer. When finished, /// it will return a tuple of the number of bytes copied from encrypted to plain /// and the number of bytes copied from plain to encrypted, in that order. /// /// [`shutdown()`]: tokio::io::AsyncWriteExt::shutdown /// /// # Errors /// /// The future will immediately return an error if any IO operation any of the streams /// returns an error. Some data read from either stream may be lost (not /// written to the other stream) in this case. /// /// # Return value /// /// Returns a tuple of bytes copied on both directions pub async fn copy_bidirectional(a: &mut A, b: &mut B) -> io::Result<(u64, u64)> where A: AsyncRead + AsyncWrite + Unpin + ?Sized, B: AsyncRead + AsyncWrite + Unpin + ?Sized, { CopyBidirectional { a, b, a_to_b: TransferState::Running(CopyBuffer::new(8192)), b_to_a: TransferState::Running(CopyBuffer::new(8192)), } .await } ================================================ FILE: crates/shadowsocks/src/relay/udprelay/aead.rs ================================================ //! Shadowsocks UDP AEAD protocol //! //! Payload with AEAD cipher //! //! ```plain //! UDP (after encryption, *ciphertext*) //! +--------+-----------+-----------+ //! | NONCE | *Data* | Data_TAG | //! +--------+-----------+-----------+ //! | Fixed | Variable | Fixed | //! +--------+-----------+-----------+ //! ``` use std::io::Cursor; use byte_string::ByteStr; use bytes::{BufMut, BytesMut}; use log::trace; use crate::{ context::Context, crypto::{CipherKind, v1::Cipher}, relay::socks5::{Address, Error as Socks5Error}, }; /// AEAD protocol error #[derive(thiserror::Error, Debug)] pub enum ProtocolError { #[error("packet too short for salt, at least {0} bytes, but only {1} bytes")] PacketTooShortForSalt(usize, usize), #[error("packet too short for tag, at least {0} bytes, but only {1} bytes")] PacketTooShortForTag(usize, usize), #[error("invalid address in packet, {0}")] InvalidAddress(Socks5Error), #[error("decrypt payload failed")] DecryptPayloadError, } /// AEAD protocol result pub type ProtocolResult = Result; /// Encrypt UDP AEAD protocol packet pub fn encrypt_payload_aead( context: &Context, method: CipherKind, key: &[u8], addr: &Address, payload: &[u8], dst: &mut BytesMut, ) { let salt_len = method.salt_len(); let addr_len = addr.serialized_len(); // Packet = IV + ADDRESS + PAYLOAD + TAG dst.reserve(salt_len + addr_len + payload.len() + method.tag_len()); // Generate IV dst.resize(salt_len, 0); let salt = &mut dst[..salt_len]; if salt_len > 0 { context.generate_nonce(method, salt, false); trace!("UDP packet generated aead salt {:?}", ByteStr::new(salt)); } let mut cipher = Cipher::new(method, key, salt); addr.write_to_buf(dst); dst.put_slice(payload); unsafe { dst.advance_mut(method.tag_len()); } let m = &mut dst[salt_len..]; cipher.encrypt_packet(m); } /// Decrypt UDP AEAD protocol packet pub fn decrypt_payload_aead( _context: &Context, method: CipherKind, key: &[u8], payload: &mut [u8], ) -> ProtocolResult<(usize, Address)> { let plen = payload.len(); let salt_len = method.salt_len(); if plen < salt_len { return Err(ProtocolError::PacketTooShortForSalt(salt_len, plen)); } let (salt, data) = payload.split_at_mut(salt_len); // context.check_nonce_replay(salt)?; trace!("UDP packet got AEAD salt {:?}", ByteStr::new(salt)); let mut cipher = Cipher::new(method, key, salt); let tag_len = cipher.tag_len(); if data.len() < tag_len { return Err(ProtocolError::PacketTooShortForTag(tag_len, data.len())); } if !cipher.decrypt_packet(data) { return Err(ProtocolError::DecryptPayloadError); } // Truncate TAG let data_len = data.len() - tag_len; let data = &mut data[..data_len]; let (dn, addr) = parse_packet(data)?; let data_length = data_len - dn; let data_start_idx = salt_len + dn; let data_end_idx = data_start_idx + data_length; payload.copy_within(data_start_idx..data_end_idx, 0); Ok((data_length, addr)) } #[inline] fn parse_packet(buf: &[u8]) -> ProtocolResult<(usize, Address)> { let mut cur = Cursor::new(buf); match Address::read_cursor(&mut cur) { Ok(address) => { let pos = cur.position() as usize; Ok((pos, address)) } Err(err) => Err(ProtocolError::InvalidAddress(err)), } } ================================================ FILE: crates/shadowsocks/src/relay/udprelay/aead_2022.rs ================================================ //! Shadowsocks UDP AEAD 2022 protocol //! //! Payload with AEAD 2022 cipher //! //! Client -> Server //! //! ```plain //! +-------+-------+-------+-------+-------+-------+-------+-------+ //! | Client Session ID | //! +-------+-------+-------+-------+-------+-------+-------+-------+ //! | Packet ID | //! +-------+-------+-------+-------+-------+-------+-------+-------+ //! | TYPE | //! +-------+-------+-------+-------+-------+-------+-------+-------+ //! | UNIX Epoch Timestamp | //! +-------+-------+-------+-------+-------+-------+-------+-------+ //! | PADDING SIZE | Padding (Variable ...) //! +-------+-------+-------+-------+-------+-------+-------+-------+ //! | Address (Variable ...) //! +-------+-------+-------+-------+-------+-------+-------+-------+ //! | Payload (Variable ...) //! +-------+-------+-------+-------+-------+-------+-------+-------+ //! ``` //! //! Server -> Client //! //! ```plain //! +-------+-------+-------+-------+-------+-------+-------+-------+ //! | Server Session ID | //! +-------+-------+-------+-------+-------+-------+-------+-------+ //! | Packet ID | //! +-------+-------+-------+-------+-------+-------+-------+-------+ //! | TYPE | //! +-------+-------+-------+-------+-------+-------+-------+-------+ //! | UNIX Epoch Timestamp | //! +-------+-------+-------+-------+-------+-------+-------+-------+ //! | Client Session ID | //! +-------+-------+-------+-------+-------+-------+-------+-------+ //! | PADDING SIZE | Padding (Variable ...) //! +-------+-------+-------+-------+-------+-------+-------+-------+ //! | Address (Variable ...) //! +-------+-------+-------+-------+-------+-------+-------+-------+ //! | Payload (Variable ...) //! +-------+-------+-------+-------+-------+-------+-------+-------+ //! ``` use std::{ cell::RefCell, cmp::Ordering, collections::hash_map::DefaultHasher, hash::{Hash, Hasher}, io::{self, Cursor, Seek, SeekFrom}, rc::Rc, slice, sync::Arc, time::{Duration, SystemTime}, }; use aes::{ Aes128, Aes256, Block, cipher::{BlockDecrypt, BlockEncrypt, KeyInit}, }; use byte_string::ByteStr; use bytes::{Buf, BufMut, Bytes, BytesMut}; use log::{error, trace}; use lru_time_cache::LruCache; #[cfg(feature = "aead-cipher-2022-extra")] use crate::crypto::v2::udp::ChaCha8Poly1305Cipher; use crate::{ config::{ServerUser, ServerUserManager, method_support_eih}, context::Context, crypto::{ CipherKind, v2::udp::{ChaCha20Poly1305Cipher, UdpCipher}, }, relay::{ get_aead_2022_padding_size, socks5::{Address, Error as Socks5Error}, }, }; use super::options::UdpSocketControlData; const CLIENT_SOCKET_TYPE: u8 = 0; const SERVER_SOCKET_TYPE: u8 = 1; const SERVER_PACKET_TIMESTAMP_MAX_DIFF: u64 = 30; /// AEAD 2022 protocol error #[derive(thiserror::Error, Debug)] pub enum ProtocolError { #[error("packet too short, at least {0} bytes, but found {1} bytes")] PacketTooShort(usize, usize), #[error("invalid address in packet, {0}")] InvalidAddress(Socks5Error), #[error("decrypt payload error")] DecryptPayloadError, #[error("invalid client user identity {:?}", ByteStr::new(.0))] InvalidClientUser(Bytes), #[error("invalid socket type, expecting {0:#x}, but found {1:#x}")] InvalidSocketType(u8, u8), #[error("invalid timestamp {0} - now {1} = {ts_diff}", ts_diff = *.0 as i64 - *.1 as i64)] InvalidTimestamp(u64, u64), #[error(transparent)] IoError(#[from] io::Error), } /// AEAD 2022 protocol result pub type ProtocolResult = Result; #[derive(PartialEq, Eq, Hash, Clone, Debug)] struct CipherKey { method: CipherKind, key: usize, session_id: u64, } impl PartialOrd for CipherKey { fn partial_cmp(&self, other: &Self) -> Option { Some(self.cmp(other)) } } impl Ord for CipherKey { fn cmp(&self, other: &Self) -> Ordering { let hash1 = { let mut hasher = DefaultHasher::new(); self.hash(&mut hasher); hasher.finish() }; let hash2 = { let mut hasher = DefaultHasher::new(); other.hash(&mut hasher); hasher.finish() }; hash1.cmp(&hash2) } } const CIPHER_CACHE_DURATION: Duration = Duration::from_secs(30); const CIPHER_CACHE_LIMIT: usize = 102400; thread_local! { static CIPHER_CACHE: RefCell>> = RefCell::new(LruCache::with_expiry_duration_and_capacity(CIPHER_CACHE_DURATION, CIPHER_CACHE_LIMIT)); } #[inline] pub fn get_now_timestamp() -> u64 { match SystemTime::now().duration_since(SystemTime::UNIX_EPOCH) { Ok(n) => n.as_secs(), Err(_) => panic!("SystemTime::now() is before UNIX Epoch!"), } } fn get_cipher(method: CipherKind, key: &[u8], session_id: u64) -> Rc { CIPHER_CACHE.with(|cache| { let mut cache = cache.borrow_mut(); let cache_key = CipherKey { method, // The key is stored in ServerConfig structure, so the address of it won't change. key: key.as_ptr() as usize, session_id, }; cache .entry(cache_key) .or_insert_with(|| Rc::new(UdpCipher::new(method, key, session_id))) .clone() }) } fn encrypt_message( _context: &Context, method: CipherKind, ipsk: &[u8], key: &[u8], packet: &mut BytesMut, session_id: u64, eih_len: usize, ) { unsafe { packet.advance_mut(method.tag_len()); } match method { CipherKind::AEAD2022_BLAKE3_CHACHA20_POLY1305 => { // ChaCha20-Poly1305 uses PSK as key, prepended nonce in packet let nonce_size = ChaCha20Poly1305Cipher::nonce_size(); let cipher = get_cipher(method, key, session_id); let (nonce, message) = packet.split_at_mut(nonce_size); cipher.encrypt_packet(nonce, message); } #[cfg(feature = "aead-cipher-2022-extra")] CipherKind::AEAD2022_BLAKE3_CHACHA8_POLY1305 => { // ChaCha8-Poly1305 uses PSK as key, prepended nonce in packet let nonce_size = ChaCha8Poly1305Cipher::nonce_size(); let cipher = get_cipher(method, key, session_id); let (nonce, message) = packet.split_at_mut(nonce_size); cipher.encrypt_packet(nonce, message); } CipherKind::AEAD2022_BLAKE3_AES_128_GCM | CipherKind::AEAD2022_BLAKE3_AES_256_GCM => { // AES-*-GCM uses derived key, and part of the packet header as nonce let cipher = get_cipher(method, key, session_id); // Encrypt the rest of the packet with AEAD cipher (AES-*-GCM) let (packet_header, mut message) = packet.split_at_mut(16); let nonce = &packet_header[4..16]; if eih_len > 0 { message = &mut message[eih_len..]; } cipher.encrypt_packet(nonce, message); // [SessionID + PacketID] is encrypted with AES-ECB with PSK // No padding is required because these 2 fields are 128-bits, which is exactly the same as AES's block size match method { CipherKind::AEAD2022_BLAKE3_AES_128_GCM => { let cipher = Aes128::new_from_slice(ipsk).expect("AES-128 init"); let block = Block::from_mut_slice(packet_header); cipher.encrypt_block(block); } CipherKind::AEAD2022_BLAKE3_AES_256_GCM => { let cipher = Aes256::new_from_slice(ipsk).expect("AES-256 init"); let block = Block::from_mut_slice(packet_header); cipher.encrypt_block(block); } _ => unreachable!("{} is not an AES-*-GCM cipher", method), } } _ => unreachable!("{} is not an AEAD 2022 cipher", method), } } fn decrypt_message( _context: &Context, method: CipherKind, key: &[u8], packet: &mut [u8], user_manager: Option<&ServerUserManager>, ) -> ProtocolResult>> { let mut client_user = None; match method { CipherKind::AEAD2022_BLAKE3_CHACHA20_POLY1305 => { // ChaCha20-Poly1305 uses PSK as key, prepended nonce in packet let nonce_size = ChaCha20Poly1305Cipher::nonce_size(); let (nonce, message) = packet.split_at_mut(nonce_size); // NOTE: ChaCha20-Poly1305's session_id is not required because it uses PSK directly // // But still, we get the session_id for cache let session_id = { let session_id_buf = &message[0..8]; let session_id_slice: &[u64] = unsafe { slice::from_raw_parts(session_id_buf.as_ptr() as *const _, 1) }; u64::from_be(session_id_slice[0]) }; let cipher = get_cipher(method, key, session_id); if !cipher.decrypt_packet(nonce, message) { return Err(ProtocolError::DecryptPayloadError); } } #[cfg(feature = "aead-cipher-2022-extra")] CipherKind::AEAD2022_BLAKE3_CHACHA8_POLY1305 => { // ChaCha8-Poly1305 uses PSK as key, prepended nonce in packet let nonce_size = ChaCha8Poly1305Cipher::nonce_size(); let (nonce, message) = packet.split_at_mut(nonce_size); // NOTE: ChaCha20-Poly1305's session_id is not required because it uses PSK directly // // But still, we get the session_id for cache let session_id = { let session_id_buf = &message[0..8]; let session_id_slice: &[u64] = unsafe { slice::from_raw_parts(session_id_buf.as_ptr() as *const _, 1) }; u64::from_be(session_id_slice[0]) }; let cipher = get_cipher(method, key, session_id); if !cipher.decrypt_packet(nonce, message) { return Err(ProtocolError::DecryptPayloadError); } } CipherKind::AEAD2022_BLAKE3_AES_128_GCM | CipherKind::AEAD2022_BLAKE3_AES_256_GCM => { // AES-*-GCM uses derived key, and part of the packet header as nonce // // Decrypt the header block first // [SessionID + PacketID] is encrypted with AES-ECB with PSK // No padding is required because these 2 fields are 128-bits, which is exactly the same as AES's block size let (packet_header, mut message) = packet.split_at_mut(16); match method { CipherKind::AEAD2022_BLAKE3_AES_128_GCM => { let cipher = Aes128::new_from_slice(key).expect("AES-128 init"); let block = Block::from_mut_slice(packet_header); cipher.decrypt_block(block); } CipherKind::AEAD2022_BLAKE3_AES_256_GCM => { let cipher = Aes256::new_from_slice(key).expect("AES-256 init"); let block = Block::from_mut_slice(packet_header); cipher.decrypt_block(block); } _ => unreachable!("{} is not an AES-*-GCM cipher", method), } // Session ID is the first 64-bits let session_id = { let session_id_buf = &packet_header[0..8]; let session_id_slice: &[u64] = unsafe { slice::from_raw_parts(session_id_buf.as_ptr() as *const _, 1) }; u64::from_be(session_id_slice[0]) }; let cipher = if method_support_eih(method) { if let Some(user_manager) = user_manager { // Extensible Identity Header // https://github.com/Shadowsocks-NET/shadowsocks-specs/blob/main/2022-2-shadowsocks-2022-extensible-identity-headers.md let (eih, remain_message) = message.split_at_mut(16); message = remain_message; let session_id_packet_id = &packet_header[0..16]; trace!( "server EIH {:?}, session_id_packet_id: {:?}", ByteStr::new(eih), ByteStr::new(session_id_packet_id) ); match method { CipherKind::AEAD2022_BLAKE3_AES_128_GCM => { let cipher = Aes128::new_from_slice(key).expect("AES-128 init"); cipher.decrypt_block(Block::from_mut_slice(eih)); } CipherKind::AEAD2022_BLAKE3_AES_256_GCM => { let cipher = Aes256::new_from_slice(key).expect("AES-256 init"); cipher.decrypt_block(Block::from_mut_slice(eih)) } _ => unreachable!("{} doesn't support EIH", method), } for i in 0..16 { eih[i] ^= session_id_packet_id[i]; } match user_manager.clone_user_by_hash(eih) { None => { error!("user with identity {:?} not found", ByteStr::new(eih)); return Err(ProtocolError::InvalidClientUser(Bytes::copy_from_slice(eih))); } Some(user) => { trace!("{:?} chosen by EIH", user); let cipher = get_cipher(method, user.key(), session_id); client_user = Some(user); cipher } } } else { get_cipher(method, key, session_id) } } else { get_cipher(method, key, session_id) }; let nonce = &packet_header[4..16]; if !cipher.decrypt_packet(nonce, message) { return Err(ProtocolError::DecryptPayloadError); } } _ => unreachable!("{} is not an AEAD 2022 cipher", method), } Ok(client_user) } #[inline] fn get_nonce_len(method: CipherKind) -> usize { match method { CipherKind::AEAD2022_BLAKE3_AES_128_GCM | CipherKind::AEAD2022_BLAKE3_AES_256_GCM => 0, CipherKind::AEAD2022_BLAKE3_CHACHA20_POLY1305 => method.nonce_len(), #[cfg(feature = "aead-cipher-2022-extra")] CipherKind::AEAD2022_BLAKE3_CHACHA8_POLY1305 => method.nonce_len(), _ => unreachable!("{} is not an AEAD 2022 cipher", method), } } /// Encrypt `Client -> Server` UDP AEAD protocol packet #[allow(clippy::too_many_arguments)] pub fn encrypt_client_payload_aead_2022( context: &Context, method: CipherKind, key: &[u8], addr: &Address, control: &UdpSocketControlData, identity_keys: &[Bytes], payload: &[u8], dst: &mut BytesMut, ) { let padding_size = get_aead_2022_padding_size(payload); let nonce_size = get_nonce_len(method); let require_eih = method_support_eih(method) && !identity_keys.is_empty(); let eih_size = if require_eih { identity_keys.len() * 16 } else { 0 }; dst.reserve( nonce_size + 8 + 8 + eih_size + 1 + 8 + 2 + padding_size + addr.serialized_len() + payload.len() + method.tag_len(), ); // Generate IV if nonce_size > 0 { unsafe { dst.advance_mut(nonce_size); } let nonce = &mut dst[..nonce_size]; context.generate_nonce(method, nonce, false); trace!("UDP packet generated aead nonce {:?}", ByteStr::new(nonce)); } // Add header fields dst.put_u64(control.client_session_id); dst.put_u64(control.packet_id); // Extensible Identity Header // https://github.com/Shadowsocks-NET/shadowsocks-specs/blob/main/2022-2-shadowsocks-2022-extensible-identity-headers.md if require_eih { #[inline] fn make_eih( method: CipherKind, ipsk: &[u8], ipskn: &[u8], session_id_packet_id: &[u8], identity_header: &mut [u8; 16], ) { let ipskn_hash = blake3::hash(ipskn); let plain_text = &ipskn_hash.as_bytes()[0..16]; identity_header.copy_from_slice(plain_text); for i in 0..16 { identity_header[i] ^= session_id_packet_id[i]; } match method { CipherKind::AEAD2022_BLAKE3_AES_128_GCM => { let cipher = Aes128::new_from_slice(ipsk).expect("AES-128 init"); cipher.encrypt_block(Block::from_mut_slice(identity_header)); } CipherKind::AEAD2022_BLAKE3_AES_256_GCM => { let cipher = Aes256::new_from_slice(ipsk).expect("AES-256 init"); cipher.encrypt_block(Block::from_mut_slice(identity_header)); } _ => unreachable!("{} doesn't support EIH", method), } trace!( "client EIH {:?}, hash: {:?}", ByteStr::new(identity_header), ByteStr::new(plain_text) ); } for (ipsk, ipskn) in identity_keys .iter() .map(AsRef::as_ref) .zip(identity_keys.iter().map(AsRef::as_ref).skip(1).chain(Some(key))) { let session_id_packet_id = &dst[nonce_size..nonce_size + 16]; let mut identity_header = [0u8; 16]; make_eih(method, ipsk, ipskn, session_id_packet_id, &mut identity_header); dst.put(identity_header.as_slice()); } } dst.put_u8(CLIENT_SOCKET_TYPE); dst.put_u64(get_now_timestamp()); dst.put_u16(padding_size as u16); if padding_size > 0 { unsafe { dst.advance_mut(padding_size); } } addr.write_to_buf(dst); dst.put_slice(payload); let ipsk = if identity_keys.is_empty() { key } else { &identity_keys[0] }; encrypt_message(context, method, ipsk, key, dst, control.client_session_id, eih_size); } /// Decrypt `Client -> Server` UDP AEAD protocol packet pub fn decrypt_client_payload_aead_2022( context: &Context, method: CipherKind, key: &[u8], payload: &mut [u8], user_manager: Option<&ServerUserManager>, ) -> ProtocolResult<(usize, Address, UdpSocketControlData)> { let nonce_len = get_nonce_len(method); let tag_len = method.tag_len(); let require_eih = method_support_eih(method) && user_manager.is_some(); let eih_len = if require_eih { 16 } else { 0 }; let header_len = nonce_len + tag_len + 8 + 8 + eih_len + 1 + 8 + 2; if payload.len() < header_len { return Err(ProtocolError::PacketTooShort(header_len, payload.len())); } let user = decrypt_message(context, method, key, payload, user_manager)?; let data = &payload[nonce_len..payload.len() - tag_len]; let mut cursor = Cursor::new(data); let client_session_id = cursor.get_u64(); let packet_id = cursor.get_u64(); if require_eih { cursor.advance(16); } let socket_type = cursor.get_u8(); if socket_type != CLIENT_SOCKET_TYPE { return Err(ProtocolError::InvalidSocketType(CLIENT_SOCKET_TYPE, socket_type)); } let timestamp = cursor.get_u64(); let now = get_now_timestamp(); if now.abs_diff(timestamp) > SERVER_PACKET_TIMESTAMP_MAX_DIFF { return Err(ProtocolError::InvalidTimestamp(timestamp, now)); } let padding_size = cursor.get_u16() as usize; if padding_size > 0 { cursor.seek(SeekFrom::Current(padding_size as i64))?; } let control = UdpSocketControlData { client_session_id, server_session_id: 0, packet_id, user, }; let addr = match Address::read_cursor(&mut cursor) { Ok(a) => a, Err(err) => return Err(ProtocolError::InvalidAddress(err)), }; let payload_start = cursor.position() as usize; let payload_len = data.len() - payload_start; payload.copy_within(nonce_len + payload_start..nonce_len + payload_start + payload_len, 0); Ok((payload_len, addr, control)) } /// Encrypt `Server -> Client` UDP AEAD protocol packet pub fn encrypt_server_payload_aead_2022( context: &Context, method: CipherKind, key: &[u8], addr: &Address, control: &UdpSocketControlData, payload: &[u8], dst: &mut BytesMut, ) { let padding_size = get_aead_2022_padding_size(payload); let nonce_size = get_nonce_len(method); dst.reserve( nonce_size + 8 + 8 + 1 + 8 + 8 + 2 + padding_size + addr.serialized_len() + payload.len() + method.tag_len(), ); // Generate IV if nonce_size > 0 { unsafe { dst.advance_mut(nonce_size); } let nonce = &mut dst[..nonce_size]; context.generate_nonce(method, nonce, false); trace!("UDP packet generated aead nonce {:?}", ByteStr::new(nonce)); } // Add header fields dst.put_u64(control.server_session_id); dst.put_u64(control.packet_id); dst.put_u8(SERVER_SOCKET_TYPE); dst.put_u64(get_now_timestamp()); dst.put_u64(control.client_session_id); dst.put_u16(padding_size as u16); if padding_size > 0 { unsafe { dst.advance_mut(padding_size); } } addr.write_to_buf(dst); dst.put_slice(payload); encrypt_message(context, method, key, key, dst, control.server_session_id, 0); } /// Decrypt `Server -> Client` UDP AEAD protocol packet pub fn decrypt_server_payload_aead_2022( context: &Context, method: CipherKind, key: &[u8], payload: &mut [u8], ) -> ProtocolResult<(usize, Address, UdpSocketControlData)> { let nonce_len = get_nonce_len(method); let tag_len = method.tag_len(); let header_len = nonce_len + tag_len + 8 + 8 + 1 + 8 + 2; if payload.len() < header_len { return Err(ProtocolError::PacketTooShort(header_len, payload.len())); } let user = decrypt_message(context, method, key, payload, None)?; debug_assert!(user.is_none(), "server respond packet shouldn't have EIH"); let data = &payload[nonce_len..payload.len() - tag_len]; let mut cursor = Cursor::new(data); let server_session_id = cursor.get_u64(); let packet_id = cursor.get_u64(); let socket_type = cursor.get_u8(); if socket_type != SERVER_SOCKET_TYPE { return Err(ProtocolError::InvalidSocketType(SERVER_SOCKET_TYPE, socket_type)); } let timestamp = cursor.get_u64(); let now = get_now_timestamp(); if now.abs_diff(timestamp) > SERVER_PACKET_TIMESTAMP_MAX_DIFF { return Err(ProtocolError::InvalidTimestamp(timestamp, now)); } let client_session_id = cursor.get_u64(); let padding_size = cursor.get_u16() as usize; if padding_size > 0 { cursor.seek(SeekFrom::Current(padding_size as i64))?; } let control = UdpSocketControlData { client_session_id, server_session_id, packet_id, user: None, }; let addr = match Address::read_cursor(&mut cursor) { Ok(a) => a, Err(err) => return Err(ProtocolError::InvalidAddress(err)), }; let payload_start = cursor.position() as usize; let payload_len = data.len() - payload_start; payload.copy_within(nonce_len + payload_start..nonce_len + payload_start + payload_len, 0); Ok((payload_len, addr, control)) } ================================================ FILE: crates/shadowsocks/src/relay/udprelay/compat.rs ================================================ use std::{ future::Future, io, net::SocketAddr, ops::Deref, pin::Pin, task::{Context, Poll}, }; use futures::ready; use pin_project::pin_project; use tokio::io::ReadBuf; use crate::net::UdpSocket; /// A socket I/O object that can transport datagram pub trait DatagramSocket { /// Local binded address fn local_addr(&self) -> io::Result; } /// A socket I/O object that can receive datagram pub trait DatagramReceive { /// `recv` data into `buf` fn poll_recv(&self, cx: &mut Context<'_>, buf: &mut ReadBuf<'_>) -> Poll>; /// `recv` data into `buf` with source address fn poll_recv_from(&self, cx: &mut Context<'_>, buf: &mut ReadBuf<'_>) -> Poll>; /// Check if the underlying I/O object is ready for `recv` fn poll_recv_ready(&self, cx: &mut Context<'_>) -> Poll>; } /// A socket I/O object that can send datagram pub trait DatagramSend { /// `send` data with `buf`, returning the sent bytes fn poll_send(&self, cx: &mut Context<'_>, buf: &[u8]) -> Poll>; /// `send` data with `buf` to `target`, returning the sent bytes fn poll_send_to(&self, cx: &mut Context<'_>, buf: &[u8], target: SocketAddr) -> Poll>; /// Check if the underlying I/O object is ready for `send` fn poll_send_ready(&self, cx: &mut Context<'_>) -> Poll>; } impl DatagramSocket for UdpSocket { fn local_addr(&self) -> io::Result { self.deref().local_addr() } } impl DatagramReceive for UdpSocket { fn poll_recv(&self, cx: &mut Context<'_>, buf: &mut ReadBuf<'_>) -> Poll> { Self::poll_recv(self, cx, buf) } fn poll_recv_from(&self, cx: &mut Context<'_>, buf: &mut ReadBuf<'_>) -> Poll> { Self::poll_recv_from(self, cx, buf) } fn poll_recv_ready(&self, cx: &mut Context<'_>) -> Poll> { self.deref().poll_recv_ready(cx) } } impl DatagramSend for UdpSocket { fn poll_send(&self, cx: &mut Context<'_>, buf: &[u8]) -> Poll> { Self::poll_send(self, cx, buf) } fn poll_send_to(&self, cx: &mut Context<'_>, buf: &[u8], target: SocketAddr) -> Poll> { Self::poll_send_to(self, cx, buf, target) } fn poll_send_ready(&self, cx: &mut Context<'_>) -> Poll> { self.deref().poll_send_ready(cx) } } /// Future for `recv` #[pin_project] pub struct RecvFut<'a, S: DatagramReceive + ?Sized> { #[pin] io: &'a S, buf: &'a mut [u8], } impl Future for RecvFut<'_, S> { type Output = io::Result; fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { let this = self.project(); let mut read_buf = ReadBuf::new(this.buf); ready!(this.io.poll_recv(cx, &mut read_buf))?; Ok(read_buf.filled().len()).into() } } /// Future for `recv_from` #[pin_project] pub struct RecvFromFut<'a, S: DatagramReceive + ?Sized> { #[pin] io: &'a S, buf: &'a mut [u8], } impl Future for RecvFromFut<'_, S> { type Output = io::Result<(usize, SocketAddr)>; fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { let this = self.project(); let mut read_buf = ReadBuf::new(this.buf); let src_addr = ready!(this.io.poll_recv_from(cx, &mut read_buf))?; Ok((read_buf.filled().len(), src_addr)).into() } } /// Future for `recv_ready` pub struct RecvReadyFut<'a, S: DatagramReceive + ?Sized> { io: &'a S, } impl Future for RecvReadyFut<'_, S> { type Output = io::Result<()>; fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { self.io.poll_recv_ready(cx) } } /// Future for `send` pub struct SendFut<'a, S: DatagramSend + ?Sized> { io: &'a S, buf: &'a [u8], } impl Future for SendFut<'_, S> { type Output = io::Result; fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { self.io.poll_send(cx, self.buf) } } /// Future for `send_to` pub struct SendToFut<'a, S: DatagramSend + ?Sized> { io: &'a S, target: SocketAddr, buf: &'a [u8], } impl Future for SendToFut<'_, S> { type Output = io::Result; fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { self.io.poll_send_to(cx, self.buf, self.target) } } /// Future for `recv_ready` pub struct SendReadyFut<'a, S: DatagramSend + ?Sized> { io: &'a S, } impl Future for SendReadyFut<'_, S> { type Output = io::Result<()>; fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { self.io.poll_send_ready(cx) } } /// Extension methods for `DatagramReceive` pub trait DatagramReceiveExt: DatagramReceive { /// Async method for `poll_recv` fn recv<'a>(&'a self, buf: &'a mut [u8]) -> RecvFut<'a, Self> { RecvFut { io: self, buf } } /// Async method for `poll_recv_from` fn recv_from<'a>(&'a self, buf: &'a mut [u8]) -> RecvFromFut<'a, Self> { RecvFromFut { io: self, buf } } /// Async method for `poll_recv_ready` fn recv_ready(&self) -> RecvReadyFut<'_, Self> { RecvReadyFut { io: self } } } impl DatagramReceiveExt for S {} /// Extension methods for `DatagramSend` pub trait DatagramSendExt: DatagramSend { /// Async method for `poll_send` fn send<'a>(&'a self, buf: &'a [u8]) -> SendFut<'a, Self> { SendFut { io: self, buf } } /// Async method for `poll_send_to` fn send_to<'a>(&'a self, buf: &'a [u8], target: SocketAddr) -> SendToFut<'a, Self> { SendToFut { io: self, target, buf } } /// Async method for `poll_send_ready` fn send_ready(&self) -> SendReadyFut<'_, Self> { SendReadyFut { io: self } } } impl DatagramSendExt for S {} ================================================ FILE: crates/shadowsocks/src/relay/udprelay/crypto_io.rs ================================================ //! Crypto protocol for ShadowSocks UDP //! //! Payload with stream cipher //! ```plain //! +-------+----------+ //! | IV | Payload | //! +-------+----------+ //! | Fixed | Variable | //! +-------+----------+ //! ``` //! //! Payload with AEAD cipher //! //! ```plain //! UDP (after encryption, *ciphertext*) //! +--------+-----------+-----------+ //! | NONCE | *Data* | Data_TAG | //! +--------+-----------+-----------+ //! | Fixed | Variable | Fixed | //! +--------+-----------+-----------+ //! ``` use std::io::Cursor; use bytes::{BufMut, Bytes, BytesMut}; use crate::{ config::ServerUserManager, context::Context, crypto::{CipherCategory, CipherKind}, relay::socks5::{Address, Error as Socks5Error}, }; #[cfg(feature = "aead-cipher")] use super::aead::{decrypt_payload_aead, encrypt_payload_aead}; #[cfg(feature = "aead-cipher-2022")] use super::aead_2022::{ decrypt_client_payload_aead_2022, decrypt_server_payload_aead_2022, encrypt_client_payload_aead_2022, encrypt_server_payload_aead_2022, }; use super::options::UdpSocketControlData; #[cfg(feature = "stream-cipher")] use super::stream::{decrypt_payload_stream, encrypt_payload_stream}; /// UDP shadowsocks protocol errors #[derive(thiserror::Error, Debug)] pub enum ProtocolError { #[error("invalid address in packet, {0}")] InvalidAddress(Socks5Error), #[cfg(feature = "stream-cipher")] #[error(transparent)] StreamError(#[from] super::stream::ProtocolError), #[cfg(feature = "aead-cipher")] #[error(transparent)] AeadError(#[from] super::aead::ProtocolError), #[cfg(feature = "aead-cipher-2022")] #[error(transparent)] Aead2022Error(#[from] super::aead_2022::ProtocolError), } /// UDP shadowsocks protocol errors pub type ProtocolResult = Result; /// Encrypt `Client -> Server` payload into ShadowSocks UDP encrypted packet #[allow(clippy::too_many_arguments)] pub fn encrypt_client_payload( context: &Context, method: CipherKind, key: &[u8], addr: &Address, control: &UdpSocketControlData, identity_keys: &[Bytes], payload: &[u8], dst: &mut BytesMut, ) { match method.category() { CipherCategory::None => { let _ = context; let _ = key; let _ = control; let _ = identity_keys; dst.reserve(addr.serialized_len() + payload.len()); addr.write_to_buf(dst); dst.put_slice(payload); } #[cfg(feature = "stream-cipher")] CipherCategory::Stream => { let _ = control; let _ = identity_keys; encrypt_payload_stream(context, method, key, addr, payload, dst) } #[cfg(feature = "aead-cipher")] CipherCategory::Aead => { let _ = control; let _ = identity_keys; encrypt_payload_aead(context, method, key, addr, payload, dst) } #[cfg(feature = "aead-cipher-2022")] CipherCategory::Aead2022 => { encrypt_client_payload_aead_2022(context, method, key, addr, control, identity_keys, payload, dst) } } } /// Encrypt `Server -> Client` payload into ShadowSocks UDP encrypted packet pub fn encrypt_server_payload( context: &Context, method: CipherKind, key: &[u8], addr: &Address, control: &UdpSocketControlData, payload: &[u8], dst: &mut BytesMut, ) { match method.category() { CipherCategory::None => { let _ = context; let _ = key; let _ = control; dst.reserve(addr.serialized_len() + payload.len()); addr.write_to_buf(dst); dst.put_slice(payload); } #[cfg(feature = "stream-cipher")] CipherCategory::Stream => { let _ = control; encrypt_payload_stream(context, method, key, addr, payload, dst) } #[cfg(feature = "aead-cipher")] CipherCategory::Aead => { let _ = control; encrypt_payload_aead(context, method, key, addr, payload, dst) } #[cfg(feature = "aead-cipher-2022")] CipherCategory::Aead2022 => encrypt_server_payload_aead_2022(context, method, key, addr, control, payload, dst), } } /// Decrypt `Client -> Server` payload from ShadowSocks UDP encrypted packet pub fn decrypt_client_payload( context: &Context, method: CipherKind, key: &[u8], payload: &mut [u8], user_manager: Option<&ServerUserManager>, ) -> ProtocolResult<(usize, Address, Option)> { match method.category() { CipherCategory::None => { let _ = context; let _ = key; let _ = user_manager; let mut cur = Cursor::new(payload); match Address::read_cursor(&mut cur) { Ok(address) => { let pos = cur.position() as usize; let payload = cur.into_inner(); payload.copy_within(pos.., 0); Ok((payload.len() - pos, address, None)) } Err(err) => Err(ProtocolError::InvalidAddress(err)), } } #[cfg(feature = "stream-cipher")] CipherCategory::Stream => { let _ = user_manager; decrypt_payload_stream(context, method, key, payload) .map(|(n, a)| (n, a, None)) .map_err(Into::into) } #[cfg(feature = "aead-cipher")] CipherCategory::Aead => { let _ = user_manager; decrypt_payload_aead(context, method, key, payload) .map(|(n, a)| (n, a, None)) .map_err(Into::into) } #[cfg(feature = "aead-cipher-2022")] CipherCategory::Aead2022 => decrypt_client_payload_aead_2022(context, method, key, payload, user_manager) .map(|(n, a, c)| (n, a, Some(c))) .map_err(Into::into), } } /// Decrypt `Server -> Client` payload from ShadowSocks UDP encrypted packet pub fn decrypt_server_payload( context: &Context, method: CipherKind, key: &[u8], payload: &mut [u8], ) -> ProtocolResult<(usize, Address, Option)> { match method.category() { CipherCategory::None => { let _ = context; let _ = key; let mut cur = Cursor::new(payload); match Address::read_cursor(&mut cur) { Ok(address) => { let pos = cur.position() as usize; let payload = cur.into_inner(); payload.copy_within(pos.., 0); Ok((payload.len() - pos, address, None)) } Err(err) => Err(ProtocolError::InvalidAddress(err)), } } #[cfg(feature = "stream-cipher")] CipherCategory::Stream => decrypt_payload_stream(context, method, key, payload) .map(|(n, a)| (n, a, None)) .map_err(Into::into), #[cfg(feature = "aead-cipher")] CipherCategory::Aead => decrypt_payload_aead(context, method, key, payload) .map(|(n, a)| (n, a, None)) .map_err(Into::into), #[cfg(feature = "aead-cipher-2022")] CipherCategory::Aead2022 => decrypt_server_payload_aead_2022(context, method, key, payload) .map(|(n, a, c)| (n, a, Some(c))) .map_err(Into::into), } } ================================================ FILE: crates/shadowsocks/src/relay/udprelay/mod.rs ================================================ //! Relay for UDP implementation //! //! ## ShadowSocks UDP protocol //! //! SOCKS5 UDP Request //! ```ignore //! +----+------+------+----------+----------+----------+ //! |RSV | FRAG | ATYP | DST.ADDR | DST.PORT | DATA | //! +----+------+------+----------+----------+----------+ //! | 2 | 1 | 1 | Variable | 2 | Variable | //! +----+------+------+----------+----------+----------+ //! ``` //! //! SOCKS5 UDP Response //! ```ignore //! +----+------+------+----------+----------+----------+ //! |RSV | FRAG | ATYP | DST.ADDR | DST.PORT | DATA | //! +----+------+------+----------+----------+----------+ //! | 2 | 1 | 1 | Variable | 2 | Variable | //! +----+------+------+----------+----------+----------+ //! ``` //! //! shadowsocks UDP Request (before encrypted) //! ```ignore //! +------+----------+----------+----------+ //! | ATYP | DST.ADDR | DST.PORT | DATA | //! +------+----------+----------+----------+ //! | 1 | Variable | 2 | Variable | //! +------+----------+----------+----------+ //! ``` //! //! shadowsocks UDP Response (before encrypted) //! ```ignore //! +------+----------+----------+----------+ //! | ATYP | DST.ADDR | DST.PORT | DATA | //! +------+----------+----------+----------+ //! | 1 | Variable | 2 | Variable | //! +------+----------+----------+----------+ //! ``` //! //! shadowsocks UDP Request and Response (after encrypted) //! ```ignore //! +-------+--------------+ //! | IV | PAYLOAD | //! +-------+--------------+ //! | Fixed | Variable | //! +-------+--------------+ //! ``` use std::time::Duration; pub use self::proxy_socket::ProxySocket; pub use compat::{DatagramReceive, DatagramReceiveExt, DatagramSend, DatagramSendExt, DatagramSocket}; #[cfg(feature = "aead-cipher")] mod aead; #[cfg(feature = "aead-cipher-2022")] mod aead_2022; mod compat; pub mod crypto_io; pub mod options; pub mod proxy_socket; #[cfg(feature = "stream-cipher")] mod stream; /// The maximum UDP payload size (defined in the original shadowsocks Python) /// /// *I cannot find any references about why clowwindy used this value as the maximum /// Socks5 UDP ASSOCIATE packet size. The only thing I can find is /// [here](http://support.microsoft.com/kb/822061/)* pub const MAXIMUM_UDP_PAYLOAD_SIZE: usize = 65536; /// Default association expire time pub const DEFAULT_TIMEOUT: Duration = Duration::from_secs(5 * 60); ================================================ FILE: crates/shadowsocks/src/relay/udprelay/options.rs ================================================ //! UDP Socket options and extra data use std::sync::Arc; use crate::config::ServerUser; #[derive(Debug, Clone, Default)] #[non_exhaustive] pub struct UdpSocketControlData { /// Session ID in client. /// /// For identifying an unique association in client pub client_session_id: u64, /// Session ID in server. /// /// For identifying an unique association in server pub server_session_id: u64, /// Packet counter pub packet_id: u64, /// Server user instance pub user: Option>, } ================================================ FILE: crates/shadowsocks/src/relay/udprelay/proxy_socket.rs ================================================ //! UDP socket for communicating with shadowsocks' proxy server #[cfg(unix)] use std::os::fd::{AsFd, AsRawFd, BorrowedFd, IntoRawFd, RawFd}; #[cfg(windows)] use std::os::windows::io::{AsRawSocket, AsSocket, BorrowedSocket, IntoRawSocket, RawSocket}; use std::{ io::{self, ErrorKind}, net::SocketAddr, sync::{Arc, LazyLock}, task::{Context, Poll, ready}, time::Duration, }; use byte_string::ByteStr; use bytes::{Bytes, BytesMut}; use log::{info, trace, warn}; use tokio::{io::ReadBuf, time}; use crate::{ config::{ServerAddr, ServerConfig, ServerUserManager}, context::SharedContext, crypto::CipherKind, net::{AcceptOpts, ConnectOpts, UdpSocket as ShadowUdpSocket}, relay::{socks5::Address, udprelay::options::UdpSocketControlData}, }; use super::{ compat::{DatagramReceive, DatagramReceiveExt, DatagramSend, DatagramSendExt, DatagramSocket}, crypto_io::{ ProtocolError, ProtocolResult, decrypt_client_payload, decrypt_server_payload, encrypt_client_payload, encrypt_server_payload, }, }; static DEFAULT_CONNECT_OPTS: LazyLock = LazyLock::new(Default::default); static DEFAULT_SOCKET_CONTROL: LazyLock = LazyLock::new(UdpSocketControlData::default); /// UDP socket type, defining whether the socket is used in Client or Server #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum UdpSocketType { /// Socket used for `Client -> Server` Client, /// Socket used for `Server -> Client` Server, } /// `ProxySocket` error type #[derive(thiserror::Error, Debug)] pub enum ProxySocketError { /// std::io::Error #[error(transparent)] IoError(#[from] io::Error), #[error(transparent)] ProtocolError(ProtocolError), #[error("peer: {0}, {1}")] ProtocolErrorWithPeer(SocketAddr, ProtocolError), #[error("invalid server user identity {:?}", ByteStr::new(.0))] InvalidServerUser(Bytes), } impl From for io::Error { fn from(e: ProxySocketError) -> Self { match e { ProxySocketError::IoError(e) => e, _ => Self::other(e), } } } /// `ProxySocket` result type pub type ProxySocketResult = Result; /// UDP client for communicating with ShadowSocks' server #[derive(Debug)] pub struct ProxySocket { socket_type: UdpSocketType, io: S, method: CipherKind, key: Box<[u8]>, send_timeout: Option, recv_timeout: Option, context: SharedContext, identity_keys: Arc>, user_manager: Option>, } impl ProxySocket { /// Create a client to communicate with Shadowsocks' UDP server (outbound) pub async fn connect(context: SharedContext, svr_cfg: &ServerConfig) -> ProxySocketResult { Self::connect_with_opts(context, svr_cfg, &DEFAULT_CONNECT_OPTS).await } /// Create a client to communicate with Shadowsocks' UDP server (outbound) pub async fn connect_with_opts( context: SharedContext, svr_cfg: &ServerConfig, opts: &ConnectOpts, ) -> ProxySocketResult { // Note: Plugins doesn't support UDP relay let socket = ShadowUdpSocket::connect_server_with_opts(&context, svr_cfg.udp_external_addr(), opts).await?; trace!( "connected udp remote {} (outbound: {}) with {:?}", svr_cfg.addr(), svr_cfg.udp_external_addr(), opts ); Ok(Self::from_socket(UdpSocketType::Client, context, svr_cfg, socket)) } /// Create a `ProxySocket` binding to a specific address (inbound) pub async fn bind(context: SharedContext, svr_cfg: &ServerConfig) -> ProxySocketResult { Self::bind_with_opts(context, svr_cfg, AcceptOpts::default()).await } /// Create a `ProxySocket` binding to a specific address (inbound) pub async fn bind_with_opts( context: SharedContext, svr_cfg: &ServerConfig, opts: AcceptOpts, ) -> ProxySocketResult { // Plugins doesn't support UDP let socket = match svr_cfg.udp_external_addr() { ServerAddr::SocketAddr(sa) => ShadowUdpSocket::listen_with_opts(sa, opts).await?, ServerAddr::DomainName(domain, port) => { lookup_then!(&context, domain, *port, |addr| { ShadowUdpSocket::listen_with_opts(&addr, opts.clone()).await })? .1 } }; Ok(Self::from_socket(UdpSocketType::Server, context, svr_cfg, socket)) } } impl ProxySocket { /// Create a `ProxySocket` from a I/O object that impls `DatagramTransport` pub fn from_socket(socket_type: UdpSocketType, context: SharedContext, svr_cfg: &ServerConfig, socket: S) -> Self { let key = svr_cfg.key().to_vec().into_boxed_slice(); let method = svr_cfg.method(); // NOTE: svr_cfg.timeout() is not for this socket, but for associations. Self { socket_type, io: socket, method, key, send_timeout: None, recv_timeout: None, context, identity_keys: match socket_type { UdpSocketType::Client => svr_cfg.clone_identity_keys(), UdpSocketType::Server => Arc::new(Vec::new()), }, user_manager: match socket_type { UdpSocketType::Client => None, UdpSocketType::Server => svr_cfg.clone_user_manager(), }, } } /// Set `send` timeout, `None` will clear timeout pub fn set_send_timeout(&mut self, t: Option) { self.send_timeout = t; } /// Set `recv` timeout, `None` will clear timeout pub fn set_recv_timeout(&mut self, t: Option) { self.recv_timeout = t; } } impl ProxySocket where S: DatagramSend, { fn encrypt_send_buffer( &self, addr: &Address, control: &UdpSocketControlData, identity_keys: &[Bytes], payload: &[u8], send_buf: &mut BytesMut, ) -> ProxySocketResult<()> { match self.socket_type { UdpSocketType::Client => encrypt_client_payload( &self.context, self.method, &self.key, addr, control, identity_keys, payload, send_buf, ), UdpSocketType::Server => { let mut key = self.key.as_ref(); if let Some(ref user) = control.user { trace!("udp encrypt with {:?} identity", user); key = user.key(); } encrypt_server_payload(&self.context, self.method, key, addr, control, payload, send_buf) } } Ok(()) } /// Send a UDP packet to addr through proxy #[inline] pub async fn send(&self, addr: &Address, payload: &[u8]) -> ProxySocketResult { self.send_with_ctrl(addr, &DEFAULT_SOCKET_CONTROL, payload).await } /// Send a UDP packet to addr through proxy with `ControlData` pub async fn send_with_ctrl( &self, addr: &Address, control: &UdpSocketControlData, payload: &[u8], ) -> ProxySocketResult { let mut send_buf = BytesMut::new(); self.encrypt_send_buffer(addr, control, &self.identity_keys, payload, &mut send_buf)?; trace!( "UDP server client send to {}, control: {:?}, payload length {} bytes, packet length {} bytes", addr, control, payload.len(), send_buf.len() ); let send_len = match self.send_timeout { None => self.io.send(&send_buf).await?, Some(d) => match time::timeout(d, self.io.send(&send_buf)).await { Ok(Ok(l)) => l, Ok(Err(err)) => return Err(err.into()), Err(..) => return Err(io::Error::from(ErrorKind::TimedOut).into()), }, }; if send_buf.len() != send_len { warn!( "UDP server client send {} bytes, but actually sent {} bytes", send_buf.len(), send_len ); } Ok(send_len) } /// poll family functions /// /// Send a UDP packet to addr through proxy /// /// NOTE: the `send_timeout` is ignored. pub fn poll_send(&self, addr: &Address, payload: &[u8], cx: &mut Context<'_>) -> Poll> { self.poll_send_with_ctrl(addr, &DEFAULT_SOCKET_CONTROL, payload, cx) } /// poll family functions /// /// Send a UDP packet to addr through proxy with `ControlData` /// /// NOTE: the `send_timeout` is ignored. pub fn poll_send_with_ctrl( &self, addr: &Address, control: &UdpSocketControlData, payload: &[u8], cx: &mut Context<'_>, ) -> Poll> { let mut send_buf = BytesMut::with_capacity(payload.len() + 256); self.encrypt_send_buffer(addr, control, &self.identity_keys, payload, &mut send_buf)?; trace!( "UDP server client send to {}, control: {:?}, payload length {} bytes, packet length {} bytes", addr, control, payload.len(), send_buf.len() ); let n_send_buf = send_buf.len(); match self.io.poll_send(cx, &send_buf).map_err(|x| x.into()) { Poll::Ready(Ok(l)) => { if l == n_send_buf { Poll::Ready(Ok(payload.len())) } else { Poll::Ready(Err(io::Error::from(ErrorKind::WriteZero).into())) } } x => x, } } /// poll family functions /// /// Send a UDP packet to addr through proxy `target` /// /// NOTE: the `send_timeout` is ignored. pub fn poll_send_to( &self, target: SocketAddr, addr: &Address, payload: &[u8], cx: &mut Context<'_>, ) -> Poll> { self.poll_send_to_with_ctrl(target, addr, &DEFAULT_SOCKET_CONTROL, payload, cx) } /// poll family functions /// /// Send a UDP packet to addr through proxy `target` with `ControlData` /// /// NOTE: the `send_timeout` is ignored. pub fn poll_send_to_with_ctrl( &self, target: SocketAddr, addr: &Address, control: &UdpSocketControlData, payload: &[u8], cx: &mut Context<'_>, ) -> Poll> { let mut send_buf = BytesMut::with_capacity(payload.len() + 256); self.encrypt_send_buffer(addr, control, &self.identity_keys, payload, &mut send_buf)?; info!( "UDP server client poll_send_to to {}, payload length {} bytes, packet length {} bytes", target, payload.len(), send_buf.len() ); let n_send_buf = send_buf.len(); match self.io.poll_send_to(cx, &send_buf, target).map_err(|x| x.into()) { Poll::Ready(Ok(l)) => { if l == n_send_buf { Poll::Ready(Ok(payload.len())) } else { Poll::Ready(Err(io::Error::from(ErrorKind::WriteZero).into())) } } x => x, } } /// poll family functions /// /// Check if socket is ready to `send`, or writable. pub fn poll_send_ready(&self, cx: &mut Context<'_>) -> Poll> { self.io.poll_send_ready(cx).map_err(|x| x.into()) } /// Send a UDP packet to target through proxy `target` pub async fn send_to(&self, target: SocketAddr, addr: &Address, payload: &[u8]) -> ProxySocketResult { self.send_to_with_ctrl(target, addr, &DEFAULT_SOCKET_CONTROL, payload) .await } /// Send a UDP packet to target through proxy `target` pub async fn send_to_with_ctrl( &self, target: SocketAddr, addr: &Address, control: &UdpSocketControlData, payload: &[u8], ) -> ProxySocketResult { let mut send_buf = BytesMut::new(); self.encrypt_send_buffer(addr, control, &self.identity_keys, payload, &mut send_buf)?; trace!( "UDP server client send_to to, addr {}, control: {:?}, payload length {} bytes, packet length {} bytes", addr, control, payload.len(), send_buf.len() ); let send_len = match self.send_timeout { None => self.io.send_to(&send_buf, target).await?, Some(d) => match time::timeout(d, self.io.send_to(&send_buf, target)).await { Ok(Ok(l)) => l, Ok(Err(err)) => return Err(err.into()), Err(..) => return Err(io::Error::from(ErrorKind::TimedOut).into()), }, }; if send_buf.len() != send_len { warn!( "UDP server client send_to {} bytes, but actually sent {} bytes", send_buf.len(), send_len ); } Ok(send_len) } } impl ProxySocket where S: DatagramReceive, { fn decrypt_recv_buffer( &self, recv_buf: &mut [u8], user_manager: Option<&ServerUserManager>, ) -> ProtocolResult<(usize, Address, Option)> { match self.socket_type { UdpSocketType::Client => decrypt_server_payload(&self.context, self.method, &self.key, recv_buf), UdpSocketType::Server => { decrypt_client_payload(&self.context, self.method, &self.key, recv_buf, user_manager) } } } /// Receive packet from Shadowsocks' UDP server /// /// This function will use `recv_buf` to store intermediate data, so it has to be big enough to store the whole shadowsocks' packet /// /// It is recommended to allocate a buffer to have at least 65536 bytes. pub async fn recv(&self, recv_buf: &mut [u8]) -> ProxySocketResult<(usize, Address, usize)> { self.recv_with_ctrl(recv_buf).await.map(|(n, a, rn, _)| (n, a, rn)) } /// Receive packet from Shadowsocks' UDP server /// /// This function will use `recv_buf` to store intermediate data, so it has to be big enough to store the whole shadowsocks' packet /// /// It is recommended to allocate a buffer to have at least 65536 bytes. pub async fn recv_with_ctrl( &self, recv_buf: &mut [u8], ) -> ProxySocketResult<(usize, Address, usize, Option)> { let recv_n = match self.recv_timeout { None => self.io.recv(recv_buf).await?, Some(d) => match time::timeout(d, self.io.recv(recv_buf)).await { Ok(Ok(l)) => l, Ok(Err(err)) => return Err(err.into()), Err(..) => return Err(io::Error::from(ErrorKind::TimedOut).into()), }, }; let (n, addr, control) = match self.decrypt_recv_buffer(&mut recv_buf[..recv_n], self.user_manager.as_deref()) { Ok(x) => x, Err(err) => return Err(ProxySocketError::ProtocolError(err)), }; trace!( "UDP server client receive from {}, control: {:?}, packet length {} bytes, payload length {} bytes", addr, control, recv_n, n ); Ok((n, addr, recv_n, control)) } /// Receive packet from Shadowsocks' UDP server /// /// This function will use `recv_buf` to store intermediate data, so it has to be big enough to store the whole shadowsocks' packet /// /// It is recommended to allocate a buffer to have at least 65536 bytes. #[allow(clippy::type_complexity)] pub async fn recv_from(&self, recv_buf: &mut [u8]) -> ProxySocketResult<(usize, SocketAddr, Address, usize)> { self.recv_from_with_ctrl(recv_buf) .await .map(|(n, sa, a, rn, _)| (n, sa, a, rn)) } /// Receive packet from Shadowsocks' UDP server /// /// This function will use `recv_buf` to store intermediate data, so it has to be big enough to store the whole shadowsocks' packet /// /// It is recommended to allocate a buffer to have at least 65536 bytes. #[allow(clippy::type_complexity)] pub async fn recv_from_with_ctrl( &self, recv_buf: &mut [u8], ) -> ProxySocketResult<(usize, SocketAddr, Address, usize, Option)> { // Waiting for response from server SERVER -> CLIENT let (recv_n, target_addr) = match self.recv_timeout { None => self.io.recv_from(recv_buf).await?, Some(d) => match time::timeout(d, self.io.recv_from(recv_buf)).await { Ok(Ok(l)) => l, Ok(Err(err)) => return Err(err.into()), Err(..) => return Err(io::Error::from(ErrorKind::TimedOut).into()), }, }; let (n, addr, control) = match self.decrypt_recv_buffer(&mut recv_buf[..recv_n], self.user_manager.as_deref()) { Ok(x) => x, Err(err) => return Err(ProxySocketError::ProtocolErrorWithPeer(target_addr, err)), }; trace!( "UDP server client receive from {}, addr {}, control: {:?}, packet length {} bytes, payload length {} bytes", target_addr, addr, control, recv_n, n, ); Ok((n, target_addr, addr, recv_n, control)) } /// poll family functions. /// the recv_timeout is ignored. #[allow(clippy::type_complexity)] pub fn poll_recv( &self, cx: &mut Context<'_>, recv_buf: &mut ReadBuf, ) -> Poll> { self.poll_recv_with_ctrl(cx, recv_buf) .map(|r| r.map(|(n, a, rn, _)| (n, a, rn))) } /// poll family functions #[allow(clippy::type_complexity)] pub fn poll_recv_with_ctrl( &self, cx: &mut Context<'_>, recv_buf: &mut ReadBuf, ) -> Poll)>> { ready!(self.io.poll_recv(cx, recv_buf))?; let n_recv = recv_buf.filled().len(); match self.decrypt_recv_buffer(recv_buf.filled_mut(), self.user_manager.as_deref()) { Ok(x) => Poll::Ready(Ok((x.0, x.1, n_recv, x.2))), Err(err) => Poll::Ready(Err(ProxySocketError::ProtocolError(err))), } } /// poll family functions #[allow(clippy::type_complexity)] pub fn poll_recv_from( &self, cx: &mut Context<'_>, recv_buf: &mut ReadBuf, ) -> Poll> { self.poll_recv_from_with_ctrl(cx, recv_buf) .map(|r| r.map(|(n, sa, a, rn, _)| (n, sa, a, rn))) } /// poll family functions #[allow(clippy::type_complexity)] pub fn poll_recv_from_with_ctrl( &self, cx: &mut Context<'_>, recv_buf: &mut ReadBuf, ) -> Poll)>> { let src = ready!(self.io.poll_recv_from(cx, recv_buf))?; let n_recv = recv_buf.filled().len(); match self.decrypt_recv_buffer(recv_buf.filled_mut(), self.user_manager.as_deref()) { Ok(x) => Poll::Ready(Ok((x.0, src, x.1, n_recv, x.2))), Err(err) => Poll::Ready(Err(ProxySocketError::ProtocolError(err))), } } /// poll family functions pub fn poll_recv_ready(&self, cx: &mut Context<'_>) -> Poll> { self.io.poll_recv_ready(cx).map_err(|x| x.into()) } } impl ProxySocket where S: DatagramSocket, { /// Get local addr of socket pub fn local_addr(&self) -> io::Result { self.io.local_addr() } } #[cfg(unix)] impl AsRawFd for ProxySocket where S: AsRawFd, { /// Retrieve raw fd of the outbound socket fn as_raw_fd(&self) -> RawFd { self.io.as_raw_fd() } } #[cfg(unix)] impl AsFd for ProxySocket where S: AsFd, { fn as_fd(&self) -> BorrowedFd<'_> { self.io.as_fd() } } #[cfg(unix)] impl IntoRawFd for ProxySocket where S: IntoRawFd, { fn into_raw_fd(self) -> RawFd { self.io.into_raw_fd() } } #[cfg(windows)] impl AsRawSocket for ProxySocket where S: AsRawSocket, { fn as_raw_socket(&self) -> RawSocket { self.io.as_raw_socket() } } #[cfg(windows)] impl AsSocket for ProxySocket where S: AsSocket, { fn as_socket(&self) -> BorrowedSocket<'_> { self.io.as_socket() } } #[cfg(windows)] impl IntoRawSocket for ProxySocket where S: IntoRawSocket, { fn into_raw_socket(self) -> RawSocket { self.io.into_raw_socket() } } ================================================ FILE: crates/shadowsocks/src/relay/udprelay/stream.rs ================================================ //! Shadowsocks UDP Stream Protocol //! //! Payload with stream cipher //! ```plain //! +-------+----------+ //! | IV | Payload | //! +-------+----------+ //! | Fixed | Variable | //! +-------+----------+ //! ``` use std::io::Cursor; use byte_string::ByteStr; use bytes::{BufMut, BytesMut}; use log::trace; use crate::{ context::Context, crypto::{CipherKind, v1::Cipher}, relay::socks5::{Address, Error as Socks5Error}, }; /// Stream protocol error #[derive(thiserror::Error, Debug)] pub enum ProtocolError { #[error("packet too short, at least {0} bytes, but only {1} bytes")] PacketTooShort(usize, usize), #[error("invalid address in packet, {0}")] InvalidAddress(Socks5Error), } /// Stream protocol result pub type ProtocolResult = Result; /// Encrypt UDP stream protocol packet pub fn encrypt_payload_stream( context: &Context, method: CipherKind, key: &[u8], addr: &Address, payload: &[u8], dst: &mut BytesMut, ) { let iv_len = method.iv_len(); let addr_len = addr.serialized_len(); // Packet = IV + ADDRESS + PAYLOAD dst.reserve(iv_len + addr_len + payload.len()); // Generate IV dst.resize(iv_len, 0); let iv = &mut dst[..iv_len]; if iv_len > 0 { context.generate_nonce(method, iv, false); trace!("UDP packet generated stream iv {:?}", ByteStr::new(iv)); } let mut cipher = Cipher::new(method, key, iv); addr.write_to_buf(dst); dst.put_slice(payload); let m = &mut dst[iv_len..]; cipher.encrypt_packet(m); } /// Decrypt UDP stream protocol packet pub fn decrypt_payload_stream( _context: &Context, method: CipherKind, key: &[u8], payload: &mut [u8], ) -> ProtocolResult<(usize, Address)> { let plen = payload.len(); let iv_len = method.iv_len(); if plen < iv_len { return Err(ProtocolError::PacketTooShort(iv_len, plen)); } let (iv, data) = payload.split_at_mut(iv_len); // context.check_nonce_replay(iv)?; trace!("UDP packet got stream IV {:?}", ByteStr::new(iv)); let mut cipher = Cipher::new(method, key, iv); assert!(cipher.decrypt_packet(data)); let (dn, addr) = parse_packet(data)?; let data_start_idx = iv_len + dn; let data_length = payload.len() - data_start_idx; payload.copy_within(data_start_idx.., 0); Ok((data_length, addr)) } #[inline] fn parse_packet(buf: &[u8]) -> ProtocolResult<(usize, Address)> { let mut cur = Cursor::new(buf); match Address::read_cursor(&mut cur) { Ok(address) => { let pos = cur.position() as usize; Ok((pos, address)) } Err(err) => Err(ProtocolError::InvalidAddress(err)), } } ================================================ FILE: crates/shadowsocks/src/security/mod.rs ================================================ pub mod replay; ================================================ FILE: crates/shadowsocks/src/security/replay/mod.rs ================================================ use std::fmt; #[cfg(feature = "aead-cipher-2022")] use std::time::Duration; use cfg_if::cfg_if; #[cfg(feature = "aead-cipher-2022")] use lru_time_cache::LruCache; #[cfg(feature = "aead-cipher-2022")] use crate::relay::tcprelay::proxy_stream::protocol::v2::SERVER_STREAM_TIMESTAMP_MAX_DIFF; use crate::{config::ServerType, crypto::CipherKind}; #[cfg(feature = "security-replay-attack-detect")] use self::ppbloom::PingPongBloom; #[cfg(feature = "security-replay-attack-detect")] mod ppbloom; /// A Bloom Filter based protector against replay attack pub struct ReplayProtector { // Check for duplicated IV/Nonce, for prevent replay attack // https://github.com/shadowsocks/shadowsocks-org/issues/44 #[cfg(feature = "security-replay-attack-detect")] nonce_ppbloom: spin::Mutex, // AEAD 2022 specific filter. // AEAD 2022 TCP protocol has a timestamp, which can already reject most of the replay requests, // so we only need to remember nonce that are in the valid time range #[cfg(feature = "aead-cipher-2022")] nonce_set: spin::Mutex, ()>>, } impl fmt::Debug for ReplayProtector { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("ReplayProtector").finish() } } impl ReplayProtector { /// Create a new ReplayProtector #[allow(unused_variables)] pub fn new(config_type: ServerType) -> Self { Self { #[cfg(feature = "security-replay-attack-detect")] nonce_ppbloom: spin::Mutex::new(PingPongBloom::new(config_type)), #[cfg(feature = "aead-cipher-2022")] nonce_set: spin::Mutex::new(LruCache::with_expiry_duration(Duration::from_secs( SERVER_STREAM_TIMESTAMP_MAX_DIFF * 2, ))), } } /// Check if nonce exist or not #[inline(always)] pub fn check_nonce_and_set(&self, method: CipherKind, nonce: &[u8]) -> bool { // Plain cipher doesn't have a nonce // Always treated as non-duplicated if nonce.is_empty() { return false; } #[cfg(feature = "aead-cipher-2022")] if method.is_aead_2022() { let mut set = self.nonce_set.lock(); if set.get(nonce).is_some() { return true; } set.insert(nonce.to_vec(), ()); return false; } let _ = method; cfg_if! { if #[cfg(feature = "security-replay-attack-detect")] { let mut ppbloom = self.nonce_ppbloom.lock(); ppbloom.check_and_set(nonce) } else { false } } } } ================================================ FILE: crates/shadowsocks/src/security/replay/ppbloom.rs ================================================ use bloomfilter::Bloom; use log::debug; use crate::config::ServerType; // Entries for server's bloom filter // // Borrowed from shadowsocks-libev's default value const BF_NUM_ENTRIES_FOR_SERVER: usize = 1_000_000; // Entries for client's bloom filter // // Borrowed from shadowsocks-libev's default value const BF_NUM_ENTRIES_FOR_CLIENT: usize = 10_000; // Error rate for server's bloom filter // // Borrowed from shadowsocks-libev's default value const BF_ERROR_RATE_FOR_SERVER: f64 = 1e-6; // Error rate for client's bloom filter // // Borrowed from shadowsocks-libev's default value const BF_ERROR_RATE_FOR_CLIENT: f64 = 1e-15; // A bloom filter borrowed from shadowsocks-libev's `ppbloom` // // It contains 2 bloom filters and each one holds 1/2 entries. // Use them as a ring buffer. #[derive(Debug)] pub struct PingPongBloom { blooms: [Bloom<[u8]>; 2], bloom_count: [usize; 2], item_count: usize, current: usize, } impl PingPongBloom { pub fn new(ty: ServerType) -> Self { let (mut item_count, fp_p) = if ty.is_local() { (BF_NUM_ENTRIES_FOR_CLIENT, BF_ERROR_RATE_FOR_CLIENT) } else { (BF_NUM_ENTRIES_FOR_SERVER, BF_ERROR_RATE_FOR_SERVER) }; item_count /= 2; Self { blooms: [ Bloom::new_for_fp_rate(item_count, fp_p).expect("BloomFilter1"), Bloom::new_for_fp_rate(item_count, fp_p).expect("BloomFilter2"), ], bloom_count: [0, 0], item_count, current: 0, } } // Check if data in `buf` exist. // // Set into the current bloom filter if not exist. // // Return `true` if data exist in bloom filter. pub fn check_and_set(&mut self, buf: &[u8]) -> bool { for bloom in &self.blooms { if bloom.check(buf) { return true; } } if self.bloom_count[self.current] >= self.item_count { // Current bloom filter is full, // Create a new one and use that one as current. self.current = (self.current + 1) % 2; self.bloom_count[self.current] = 0; self.blooms[self.current].clear(); debug!( "bloom filter based replay protector full, each capacity: {}, total filters: {}", self.item_count, self.blooms.len(), ); } // Cannot be optimized by `check_and_set` // Because we have to check every filters in `blooms` before `set` self.blooms[self.current].set(buf); self.bloom_count[self.current] += 1; false } } ================================================ FILE: crates/shadowsocks/tests/tcp.rs ================================================ use std::{io, net::SocketAddr, sync::Arc}; use byte_string::ByteStr; use futures::future; use log::info; use tokio::{ io::{AsyncBufReadExt, AsyncWriteExt, BufReader}, net::{TcpListener, TcpStream}, sync::Barrier, }; use shadowsocks::{ ProxyClientStream, ProxyListener, config::{ServerConfig, ServerType}, context::Context, crypto::CipherKind, relay::{ socks5::Address, tcprelay::{ proxy_stream::ProxyServerStream, utils::{copy_from_encrypted, copy_to_encrypted}, }, }, }; async fn handle_tcp_tunnel_server_client( method: CipherKind, mut stream: ProxyServerStream, ) -> io::Result<()> { let addr = stream.handshake().await?; let mut remote = { let remote = match addr { Address::SocketAddress(ref sa) => TcpStream::connect(sa).await?, Address::DomainNameAddress(ref dname, port) => TcpStream::connect((dname.as_str(), port)).await?, }; info!("connected to remote {}", addr); remote }; let (mut sr, mut sw) = tokio::io::split(stream); let (mut mr, mut mw) = remote.split(); let l2r = copy_from_encrypted(method, &mut sr, &mut mw); let r2l = copy_to_encrypted(method, &mut mr, &mut sw); tokio::pin!(l2r); tokio::pin!(r2l); let _ = future::select(l2r, r2l).await; info!("TCP tunnel server finished"); Ok(()) } async fn handle_tcp_tunnel_local_client( context: Arc, svr_cfg: Arc, mut stream: TcpStream, ) -> io::Result<()> { let target_addr = Address::from(("www.example.com".to_owned(), 80)); let remote = ProxyClientStream::connect(context, &svr_cfg, target_addr).await?; let (mut lr, mut lw) = stream.split(); let (mut sr, mut sw) = tokio::io::split(remote); let l2s = copy_to_encrypted(svr_cfg.method(), &mut lr, &mut sw); let s2l = copy_from_encrypted(svr_cfg.method(), &mut sr, &mut lw); tokio::pin!(l2s); tokio::pin!(s2l); let _ = future::select(l2s, s2l).await; info!("TCP tunnel client finished"); Ok(()) } async fn tcp_tunnel_example( server_addr: SocketAddr, local_addr: SocketAddr, password: &str, method: CipherKind, ) -> io::Result<()> { let svr_cfg_server = ServerConfig::new(server_addr, password, method).unwrap(); let svr_cfg_local = svr_cfg_server.clone(); let ctx_server = Context::new_shared(ServerType::Server); let ctx_local = Context::new_shared(ServerType::Local); let barrier_server = Arc::new(Barrier::new(3)); let barrier_local = barrier_server.clone(); let barrier = barrier_local.clone(); tokio::spawn(async move { let svr_cfg_server = Arc::new(svr_cfg_server); let listener = ProxyListener::bind(ctx_server, &svr_cfg_server).await.unwrap(); info!("server listening on {}", listener.local_addr().unwrap()); barrier_server.wait().await; while let Ok((stream, peer_addr)) = listener.accept().await { info!("server accepted stream {}", peer_addr); tokio::spawn(handle_tcp_tunnel_server_client(svr_cfg_server.method(), stream)); } }); tokio::spawn(async move { let svr_cfg_local = Arc::new(svr_cfg_local); let listener = TcpListener::bind(local_addr).await.unwrap(); info!("local listening on {}", listener.local_addr().unwrap()); barrier_local.wait().await; while let Ok((stream, peer_addr)) = listener.accept().await { info!("local accepted stream {}", peer_addr); let context = ctx_local.clone(); let svr_cfg = svr_cfg_local.clone(); tokio::spawn(handle_tcp_tunnel_local_client(context, svr_cfg, stream)); } }); barrier.wait().await; let mut client = TcpStream::connect(local_addr).await?; const HTTP_REQUEST: &[u8] = b"GET / HTTP/1.1\r\nHost: www.example.com\r\nAccept: */*\r\nConnection: close\r\n\r\n"; client.write_all(HTTP_REQUEST).await?; let mut reader = BufReader::new(client); let mut buffer = Vec::new(); reader.read_until(b'\n', &mut buffer).await?; println!("{:?}", ByteStr::new(&buffer)); const HTTP_RESPONSE_STATUS: &[u8] = b"HTTP/1.1 200 OK\r\n"; assert!(buffer.starts_with(HTTP_RESPONSE_STATUS)); Ok(()) } #[cfg(feature = "aead-cipher")] #[tokio::test] async fn tcp_tunnel_aead() { let _ = env_logger::try_init(); let server_addr = "127.0.0.1:31001".parse::().unwrap(); let local_addr = "127.0.0.1:31101".parse::().unwrap(); tcp_tunnel_example(server_addr, local_addr, "p$p", CipherKind::AES_128_GCM) .await .unwrap(); } #[cfg(feature = "stream-cipher")] #[tokio::test] async fn tcp_tunnel_stream() { let _ = env_logger::try_init(); let server_addr = "127.0.0.1:32001".parse::().unwrap(); let local_addr = "127.0.0.1:32101".parse::().unwrap(); tcp_tunnel_example(server_addr, local_addr, "p$p", CipherKind::AES_128_CFB128) .await .unwrap(); } #[tokio::test] async fn tcp_tunnel_none() { let _ = env_logger::try_init(); let server_addr = "127.0.0.1:33001".parse::().unwrap(); let local_addr = "127.0.0.1:33101".parse::().unwrap(); tcp_tunnel_example(server_addr, local_addr, "", CipherKind::NONE) .await .unwrap(); } #[cfg(feature = "aead-cipher-2022")] #[tokio::test] async fn tcp_tunnel_aead_2022_aes() { let _ = env_logger::try_init(); let server_addr = "127.0.0.1:34001".parse::().unwrap(); let local_addr = "127.0.0.1:34101".parse::().unwrap(); tcp_tunnel_example( server_addr, local_addr, "3L69X4PF2eSL/JSLkoWnXg==", CipherKind::AEAD2022_BLAKE3_AES_128_GCM, ) .await .unwrap(); } #[cfg(feature = "aead-cipher-2022")] #[tokio::test] async fn tcp_tunnel_aead_2022_chacha20() { let _ = env_logger::try_init(); let server_addr = "127.0.0.1:35001".parse::().unwrap(); let local_addr = "127.0.0.1:35101".parse::().unwrap(); tcp_tunnel_example( server_addr, local_addr, "VUw3mGWIpil2z2DKiyauE2Sp9KyE2ab8dulciawe74o", CipherKind::AEAD2022_BLAKE3_CHACHA20_POLY1305, ) .await .unwrap(); } ================================================ FILE: crates/shadowsocks/tests/tcp_tfo.rs ================================================ #![cfg(any( windows, target_os = "linux", target_os = "android", target_os = "macos", target_os = "ios", target_os = "tvos", target_os = "watchos", target_os = "freebsd" ))] use byte_string::ByteStr; use futures::future; use log::debug; use shadowsocks::{ ProxyClientStream, ProxyListener, ServerConfig, config::ServerType, context::Context, crypto::CipherKind, net::{AcceptOpts, ConnectOpts}, relay::{ socks5::Address, tcprelay::utils::{copy_from_encrypted, copy_to_encrypted}, }, }; use tokio::{ io::{AsyncBufReadExt, AsyncWriteExt, BufReader}, net::TcpStream, }; #[tokio::test] async fn tcp_tunnel_tfo() { let _ = env_logger::try_init(); let svr_cfg = ServerConfig::new(("127.0.0.1", 41000), "", CipherKind::NONE).unwrap(); let svr_cfg_client = svr_cfg.clone(); tokio::spawn(async move { let context = Context::new_shared(ServerType::Server); let mut accept_opts = AcceptOpts::default(); accept_opts.tcp.fastopen = true; let listener = ProxyListener::bind_with_opts(context, &svr_cfg, accept_opts) .await .unwrap(); while let Ok((mut stream, peer_addr)) = listener.accept().await { debug!("accepted {}", peer_addr); tokio::spawn(async move { let addr = stream.handshake().await.unwrap(); let remote = match addr { Address::SocketAddress(a) => TcpStream::connect(a).await.unwrap(), Address::DomainNameAddress(name, port) => TcpStream::connect((name.as_str(), port)).await.unwrap(), }; let (mut lr, mut lw) = tokio::io::split(stream); let (mut rr, mut rw) = remote.into_split(); let l2r = copy_from_encrypted(CipherKind::NONE, &mut lr, &mut rw); let r2l = copy_to_encrypted(CipherKind::NONE, &mut rr, &mut lw); tokio::pin!(l2r); tokio::pin!(r2l); let _ = future::select(l2r, r2l).await; }); } }); tokio::task::yield_now().await; let context = Context::new_shared(ServerType::Local); let mut connect_opts = ConnectOpts::default(); connect_opts.tcp.fastopen = true; let mut client = ProxyClientStream::connect_with_opts( context, &svr_cfg_client, ("www.example.com".to_owned(), 80), &connect_opts, ) .await .unwrap(); client .write_all(b"GET / HTTP/1.1\r\nHost: www.example.com\r\nAccept: */*\r\nConnection: close\r\n\r\n") .await .unwrap(); let mut reader = BufReader::new(client); let mut buffer = Vec::new(); reader.read_until(b'\n', &mut buffer).await.unwrap(); println!("{:?}", ByteStr::new(&buffer)); const HTTP_RESPONSE_STATUS: &[u8] = b"HTTP/1.1 200 OK\r\n"; assert!(buffer.starts_with(HTTP_RESPONSE_STATUS)); } ================================================ FILE: crates/shadowsocks/tests/udp.rs ================================================ use std::{io, net::SocketAddr, sync::Arc}; use byte_string::ByteStr; use log::info; use tokio::{net::UdpSocket, sync::Barrier}; use shadowsocks::{ config::{ServerConfig, ServerType}, context::{Context, SharedContext}, crypto::CipherKind, net::UdpSocket as ShadowUdpSocket, relay::{socks5::Address, udprelay::ProxySocket}, }; async fn handle_udp_server_client( peer_addr: SocketAddr, remote_addr: Address, payload: &[u8], socket: &ProxySocket, ) -> io::Result<()> { let remote_socket = UdpSocket::bind("0.0.0.0:0").await?; match remote_addr { Address::SocketAddress(sa) => remote_socket.connect(sa).await?, Address::DomainNameAddress(ref domain, port) => remote_socket.connect((domain.as_str(), port)).await?, } remote_socket.send(payload).await?; let mut buf = [0u8; 65536]; let n = remote_socket.recv(&mut buf).await?; socket.send_to(peer_addr, &remote_addr, &buf[..n]).await?; Ok(()) } async fn handle_udp_local_client( context: SharedContext, svr_cfg: &ServerConfig, peer_addr: SocketAddr, remote_addr: Address, payload: &[u8], socket: &UdpSocket, ) -> io::Result<()> { let server_socket = ProxySocket::connect(context, svr_cfg).await?; server_socket.send(&remote_addr, payload).await?; let mut recv_buf = [0u8; 65536]; let (n, ..) = server_socket.recv(&mut recv_buf).await?; socket.send_to(&recv_buf[..n], peer_addr).await?; Ok(()) } async fn udp_tunnel_echo( server_addr: SocketAddr, local_addr: SocketAddr, target_addr: SocketAddr, password: &str, method: CipherKind, ) -> io::Result<()> { let svr_cfg_server = ServerConfig::new(server_addr, password, method).unwrap(); let svr_cfg_local = svr_cfg_server.clone(); let ctx_server = Context::new_shared(ServerType::Server); let ctx_local = Context::new_shared(ServerType::Local); let barrier_server = Arc::new(Barrier::new(4)); let barrier_local = barrier_server.clone(); let barrier_target = barrier_server.clone(); let barrier = barrier_server.clone(); tokio::spawn(async move { let socket = UdpSocket::bind(target_addr).await.unwrap(); barrier_target.wait().await; let mut buffer = vec![0u8; 65536]; loop { let (n, peer_addr) = socket.recv_from(&mut buffer).await.unwrap(); info!("echo packet: {:?}", ByteStr::new(&buffer[..n])); let _ = socket.send_to(&buffer[..n], peer_addr).await; } }); tokio::spawn(async move { let svr_cfg_server = Arc::new(svr_cfg_server); let context = ctx_server; let socket = ProxySocket::bind(context.clone(), &svr_cfg_server).await.unwrap(); barrier_server.wait().await; let mut recv_buf = vec![0u8; 65536]; loop { let (n, peer_addr, remote_addr, ..) = socket.recv_from(&mut recv_buf).await.unwrap(); let _ = handle_udp_server_client(peer_addr, remote_addr, &recv_buf[..n], &socket).await; } }); tokio::spawn(async move { let svr_cfg_local = Arc::new(svr_cfg_local); let socket = UdpSocket::bind(local_addr).await.unwrap(); barrier_local.wait().await; let context = ctx_local; let mut buffer = vec![0u8; 65536]; loop { let (n, peer_addr) = socket.recv_from(&mut buffer).await.unwrap(); let _ = handle_udp_local_client( context.clone(), &svr_cfg_local, peer_addr, target_addr.into(), &buffer[..n], &socket, ) .await; } }); barrier.wait().await; let socket = UdpSocket::bind("0.0.0.0:0").await?; socket.connect(local_addr).await?; const SEND_PAYLOAD: &[u8] = b"HELLO WORLD. \x0012345"; socket.send(SEND_PAYLOAD).await?; let mut buffer = [0u8; 65536]; let n = socket.recv(&mut buffer).await?; assert_eq!(&buffer[..n], SEND_PAYLOAD); Ok(()) } #[cfg(feature = "aead-cipher")] #[tokio::test] async fn udp_tunnel_aead() { let _ = env_logger::try_init(); let server_addr = "127.0.0.1:21001".parse::().unwrap(); let local_addr = "127.0.0.1:21101".parse::().unwrap(); let target_addr = "127.0.0.1:21201".parse::().unwrap(); udp_tunnel_echo(server_addr, local_addr, target_addr, "pas$$", CipherKind::AES_128_GCM) .await .unwrap(); } #[cfg(feature = "stream-cipher")] #[tokio::test] async fn udp_tunnel_stream() { let _ = env_logger::try_init(); let server_addr = "127.0.0.1:22001".parse::().unwrap(); let local_addr = "127.0.0.1:22101".parse::().unwrap(); let target_addr = "127.0.0.1:22201".parse::().unwrap(); udp_tunnel_echo( server_addr, local_addr, target_addr, "pas$$", CipherKind::AES_128_CFB128, ) .await .unwrap(); } #[tokio::test] async fn udp_tunnel_none() { let _ = env_logger::try_init(); let server_addr = "127.0.0.1:23001".parse::().unwrap(); let local_addr = "127.0.0.1:23101".parse::().unwrap(); let target_addr = "127.0.0.1:23201".parse::().unwrap(); udp_tunnel_echo(server_addr, local_addr, target_addr, "pas$$", CipherKind::NONE) .await .unwrap(); } #[cfg(feature = "aead-cipher-2022")] #[tokio::test] async fn udp_tunnel_aead_2022_aes() { let _ = env_logger::try_init(); let server_addr = "127.0.0.1:24001".parse::().unwrap(); let local_addr = "127.0.0.1:24101".parse::().unwrap(); let target_addr = "127.0.0.1:24201".parse::().unwrap(); udp_tunnel_echo( server_addr, local_addr, target_addr, "D1HJFfvRIxpklHLeKvjCDQ==", CipherKind::AEAD2022_BLAKE3_AES_128_GCM, ) .await .unwrap(); } #[cfg(feature = "aead-cipher-2022")] #[tokio::test] async fn udp_tunnel_aead_2022_chacha20() { let _ = env_logger::try_init(); let server_addr = "127.0.0.1:25001".parse::().unwrap(); let local_addr = "127.0.0.1:25101".parse::().unwrap(); let target_addr = "127.0.0.1:25201".parse::().unwrap(); udp_tunnel_echo( server_addr, local_addr, target_addr, "4wYfDniq4N6kMqFajRO03PPZLfPkl469eNYY9Wz0E78=", CipherKind::AEAD2022_BLAKE3_CHACHA20_POLY1305, ) .await .unwrap(); } ================================================ FILE: crates/shadowsocks-service/Cargo.toml ================================================ [package] name = "shadowsocks-service" version = "1.24.0" authors = ["Shadowsocks Contributors"] description = "shadowsocks is a fast tunnel proxy that helps you bypass firewalls." repository = "https://github.com/shadowsocks/shadowsocks-rust" readme = "README.md" documentation = "https://docs.rs/shadowsocks-service" keywords = ["shadowsocks", "proxy", "socks", "socks5", "firewall"] license = "MIT" edition = "2024" rust-version = "1.88" [badges] maintenance = { status = "passively-maintained" } [features] default = ["hickory-dns", "aead-cipher"] full = [ "local", "server", "manager", "hickory-dns", "local-http", "local-redir", "local-tunnel", "local-socks4", "aead-cipher", ] # Enable local server local = ["httparse"] # Enable remote server server = [] # Enable manager server manager = ["server"] # Enables Hickory-DNS for replacing tokio's builtin DNS resolver hickory-dns = ["hickory-resolver", "shadowsocks/trust-dns"] # Hickory-DNS was renamed from Trust-DNS, keep compatibility. trust-dns = ["hickory-dns"] dns-over-tls = [ "hickory-dns", "hickory-resolver/tls-ring", "hickory-resolver/webpki-roots", ] dns-over-https = [ "hickory-dns", "hickory-resolver/https-ring", "hickory-resolver/webpki-roots", ] dns-over-h3 = ["hickory-dns", "hickory-resolver/h3-ring"] # Enable DNS-relay local-dns = ["local", "hickory-dns"] # Backward compatibility, DO NOT USE local-dns-relay = ["local-dns"] # Enable client flow statistic report # Currently is only used in Android local-flow-stat = ["local"] # Enable HTTP protocol for sslocal local-http = ["local", "hyper", "http", "http-body-util", "base64"] local-http-native-tls = ["local-http", "tokio-native-tls", "native-tls"] local-http-native-tls-vendored = [ "local-http-native-tls", "tokio-native-tls/vendored", "native-tls/vendored", ] local-http-rustls = [ "local-http", "tokio-rustls", "webpki-roots", "rustls-native-certs", ] # Enable REDIR protocol for sslocal # (transparent proxy) local-redir = ["local"] # Enable tunnel protocol for sslocal local-tunnel = ["local"] # Enable socks4 protocol for sslocal local-socks4 = ["local"] # Enable Tun interface protocol for sslocal local-tun = ["local", "etherparse", "tun", "smoltcp"] # Enable Fake DNS local-fake-dns = ["local", "trust-dns", "rocksdb", "bson"] # sslocal support online URL (SIP008 Online Configuration Delivery) # https://shadowsocks.org/doc/sip008.html local-online-config = [ "local", "local-http", "mime", "http", "flate2", "brotli", "zstd", ] # Enable Stream Cipher Protocol # WARN: Stream Cipher Protocol is proved to be insecure # https://github.com/shadowsocks/shadowsocks-rust/issues/373 # Users should always avoid using these ciphers in practice stream-cipher = ["shadowsocks/stream-cipher"] # Enable AEAD ciphers aead-cipher = ["shadowsocks/aead-cipher"] # Enable extra AEAD ciphers # WARN: These non-standard AEAD ciphers are not officially supported by shadowsocks community aead-cipher-extra = ["aead-cipher", "shadowsocks/aead-cipher-extra"] # Enable AEAD 2022 aead-cipher-2022 = ["shadowsocks/aead-cipher-2022"] # Enable AEAD 2022 with extra ciphers aead-cipher-2022-extra = [ "aead-cipher-2022", "shadowsocks/aead-cipher-2022-extra", ] # Enable detection against replay attack security-replay-attack-detect = ["shadowsocks/security-replay-attack-detect"] [dependencies] log = "0.4" cfg-if = "1" pin-project = "1.1" thiserror = "2.0" arc-swap = "1.7" spin = { version = "0.10" } lru_time_cache = "0.11" bytes = "1.7" byte_string = "1.0" byteorder = "1.5" rand = "0.10" rocksdb = { version = "0.24", optional = true } futures = "0.3" tokio = { version = "1.38", features = [ "io-util", "macros", "net", "parking_lot", "rt", "sync", "time", ] } tokio-native-tls = { version = "0.3", optional = true } native-tls = { version = "0.2.8", optional = true, features = ["alpn"] } webpki-roots = { version = "1.0", optional = true } tokio-rustls = { version = "0.26", optional = true, default-features = false, features = [ "logging", "tls12", "ring", ] } rustls-native-certs = { version = "0.8", optional = true } trait-variant = "0.1" socket2 = { version = "0.6", features = ["all"] } libc = "~0.2.141" hyper = { version = "1.4", optional = true, features = ["full"] } http-body-util = { version = "0.1", optional = true } http = { version = "1.1", optional = true } httparse = { version = "1.9", optional = true } hickory-resolver = { version = "0.25", optional = true, features = ["serde"] } idna = "1.0" ipnet = "2.10" iprange = "0.6" regex = { version = "1.4", default-features = false, features = [ "std", "perf", ] } mime = { version = "0.3", optional = true } flate2 = { version = "1.0", optional = true } brotli = { version = "8.0", optional = true } zstd = { version = "0.13", optional = true } base64 = { version = "0.22", optional = true } etherparse = { version = "0.19", optional = true } smoltcp = { version = "0.12", optional = true, default-features = false, features = [ "std", "log", "medium-ip", "proto-ipv4", "proto-ipv4-fragmentation", "proto-ipv6", "socket-icmp", "socket-udp", "socket-tcp", "socket-tcp-cubic", ] } serde = { version = "1.0", features = ["derive"] } json5 = "1.3" serde_json = "1.0" bson = { version = "3.0.0", features = ["serde"], optional = true } shadowsocks = { version = "1.24.0", path = "../shadowsocks", default-features = false } # Just for the ioctl call macro [target.'cfg(any(target_os = "macos", target_os = "ios", target_os = "freebsd", target_os = "openbsd"))'.dependencies] nix = { version = "0.31", features = ["ioctl"] } [target.'cfg(windows)'.dependencies] windows-sys = { version = "0.61", features = ["Win32_Networking_WinSock"] } [target.'cfg(any(target_os = "ios", target_os = "macos", target_os = "linux", target_os = "android", target_os = "windows", target_os = "freebsd"))'.dependencies] tun = { version = "0.8", optional = true, features = ["async"] } [dev-dependencies] byteorder = "1.5" env_logger = "0.11" [package.metadata.docs.rs] features = [ "full", "local-http-rustls", "local-dns", "dns-over-tls", "dns-over-https", ] [lints.clippy] uninlined_format_args = "allow" ================================================ FILE: crates/shadowsocks-service/README.md ================================================ # shadowsocks-service [![License](https://img.shields.io/github/license/zonyitoo/shadowsocks-rust.svg)](https://github.com/zonyitoo/shadowsocks-rust) [![crates.io](https://img.shields.io/crates/v/shadowsocks-service.svg)](https://crates.io/crates/shadowsocks-service) [![docs.rs](https://img.shields.io/docsrs/shadowsocks-service)](https://docs.rs/shadowsocks-service) This is a port of [shadowsocks](https://github.com/shadowsocks/shadowsocks). shadowsocks is a fast tunnel proxy that helps you bypass firewalls. ## Features * Local Server * SOCKS 5 * SOCKS 4/4a (`local-socks4`) * HTTP (`local-http`) * Tunnel (`local-tunnel`) * Redir, aka Transparent Proxy (`local-redir`) * DNS (`local-dns`) * Tun (`local-tun`) * FakeDNS (`local-fake-dns`) * SIP008 Online Config (`local-online-config`) * Server * Manager * API References: [Manage Multiple Users](https://github.com/shadowsocks/shadowsocks/wiki/Manage-Multiple-Users) ================================================ FILE: crates/shadowsocks-service/src/acl/mod.rs ================================================ //! Access Control List (ACL) for shadowsocks //! //! This is for advance controlling server behaviors in both local and proxy servers. use std::{ borrow::Cow, collections::HashSet, fmt, fs::File, io::{self, BufRead, BufReader, Error}, net::{IpAddr, SocketAddr}, path::{Path, PathBuf}, str, sync::LazyLock, }; use ipnet::{IpNet, Ipv4Net, Ipv6Net}; use iprange::IpRange; use log::{trace, warn}; use regex::bytes::{Regex, RegexBuilder, RegexSet, RegexSetBuilder}; use shadowsocks::{context::Context, relay::socks5::Address}; use self::sub_domains_tree::SubDomainsTree; mod sub_domains_tree; /// Strategy mode that ACL is running #[derive(Debug, Copy, Clone, Eq, PartialEq)] pub enum Mode { /// BlackList mode, rejects or bypasses all requests by default BlackList, /// WhiteList mode, accepts or proxies all requests by default WhiteList, } #[derive(Clone)] struct Rules { ipv4: IpRange, ipv6: IpRange, rule_regex: RegexSet, rule_set: HashSet, rule_tree: SubDomainsTree, } impl fmt::Debug for Rules { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!( f, "Rules {{ ipv4: {:?}, ipv6: {:?}, rule_regex: [", self.ipv4, self.ipv6 )?; let max_len = 2; let has_more = self.rule_regex.len() > max_len; for (idx, r) in self.rule_regex.patterns().iter().take(max_len).enumerate() { if idx > 0 { f.write_str(", ")?; } f.write_str(r)?; } if has_more { f.write_str(", ...")?; } write!(f, "], rule_set: [")?; let has_more = self.rule_set.len() > max_len; for (idx, r) in self.rule_set.iter().take(max_len).enumerate() { if idx > 0 { f.write_str(", ")?; } f.write_str(r)?; } if has_more { f.write_str(", ...")?; } write!(f, "], rule_tree: {:?} }}", self.rule_tree) } } impl Rules { /// Create a new rule fn new( mut ipv4: IpRange, mut ipv6: IpRange, rule_regex: RegexSet, rule_set: HashSet, rule_tree: SubDomainsTree, ) -> Self { // Optimization, merging networks ipv4.simplify(); ipv6.simplify(); Self { ipv4, ipv6, rule_regex, rule_set, rule_tree, } } /// Check if the specified address matches these rules #[allow(dead_code)] fn check_address_matched(&self, addr: &Address) -> bool { match *addr { Address::SocketAddress(ref saddr) => self.check_ip_matched(&saddr.ip()), Address::DomainNameAddress(ref domain, ..) => self.check_host_matched(domain), } } /// Check if the specified address matches any rules fn check_ip_matched(&self, addr: &IpAddr) -> bool { match addr { IpAddr::V4(v4) => { if self.ipv4.contains(v4) { return true; } let mapped_ipv6 = v4.to_ipv6_mapped(); self.ipv6.contains(&mapped_ipv6) } IpAddr::V6(v6) => { if self.ipv6.contains(v6) { return true; } if let Some(mapped_ipv4) = v6.to_ipv4_mapped() { return self.ipv4.contains(&mapped_ipv4); } false } } } /// Check if the specified ASCII host matches any rules fn check_host_matched(&self, host: &str) -> bool { let host = host.trim_end_matches('.'); // FQDN, removes the last `.` self.rule_set.contains(host) || self.rule_tree.contains(host) || self.rule_regex.is_match(host.as_bytes()) } /// Check if there are no rules for IP addresses fn is_ip_empty(&self) -> bool { self.ipv4.is_empty() && self.ipv6.is_empty() } /// Check if there are no rules for domain names fn is_host_empty(&self) -> bool { self.rule_set.is_empty() && self.rule_tree.is_empty() && self.rule_regex.is_empty() } } struct ParsingRules { name: &'static str, ipv4: IpRange, ipv6: IpRange, rules_regex: Vec, rules_set: HashSet, rules_tree: SubDomainsTree, } impl ParsingRules { fn new(name: &'static str) -> Self { Self { name, ipv4: IpRange::new(), ipv6: IpRange::new(), rules_regex: Vec::new(), rules_set: HashSet::new(), rules_tree: SubDomainsTree::new(), } } fn add_ipv4_rule(&mut self, rule: impl Into) { let rule = rule.into(); trace!("IPV4-RULE {}", rule); self.ipv4.add(rule); } fn add_ipv6_rule(&mut self, rule: impl Into) { let rule = rule.into(); trace!("IPV6-RULE {}", rule); self.ipv6.add(rule); } fn add_regex_rule(&mut self, mut rule: String) { static TREE_SET_RULE_EQUIV: LazyLock = LazyLock::new(|| { RegexBuilder::new( r#"^(?:(?:\((?:\?:)?\^\|\\\.\)|(?:\^\.(?:\+|\*))?\\\.)((?:[\w-]+(?:\\\.)?)+)|\^((?:[\w-]+(?:\\\.)?)+))\$?$"#, ) .unicode(false) .build() .unwrap() }); if let Some(caps) = TREE_SET_RULE_EQUIV.captures(rule.as_bytes()) { if let Some(tree_rule) = caps.get(1) { if let Ok(tree_rule) = str::from_utf8(tree_rule.as_bytes()) { let tree_rule = tree_rule.replace("\\.", "."); if self.add_tree_rule_inner(&tree_rule).is_ok() { trace!("REGEX-RULE {} => TREE-RULE {}", rule, tree_rule); return; } } } else if let Some(set_rule) = caps.get(2) && let Ok(set_rule) = str::from_utf8(set_rule.as_bytes()) { let set_rule = set_rule.replace("\\.", "."); if self.add_set_rule_inner(&set_rule).is_ok() { trace!("REGEX-RULE {} => SET-RULE {}", rule, set_rule); return; } } } trace!("REGEX-RULE {}", rule); rule.make_ascii_lowercase(); // Handle it as a normal REGEX // FIXME: If this line is not a valid regex, how can we know without actually compile it? self.rules_regex.push(rule); } #[inline] fn add_set_rule(&mut self, rule: &str) -> io::Result<()> { trace!("SET-RULE {}", rule); self.add_set_rule_inner(rule) } fn add_set_rule_inner(&mut self, rule: &str) -> io::Result<()> { self.rules_set.insert(self.check_is_ascii(rule)?.to_ascii_lowercase()); Ok(()) } #[inline] fn add_tree_rule(&mut self, rule: &str) -> io::Result<()> { trace!("TREE-RULE {}", rule); self.add_tree_rule_inner(rule) } fn add_tree_rule_inner(&mut self, rule: &str) -> io::Result<()> { // SubDomainsTree do lowercase conversion inside insert self.rules_tree.insert(self.check_is_ascii(rule)?); Ok(()) } fn check_is_ascii<'a>(&self, str: &'a str) -> io::Result<&'a str> { if str.is_ascii() { // Remove the last `.` of FQDN Ok(str.trim_end_matches('.')) } else { Err(Error::other(format!( "{} parsing error: Unicode not allowed here `{}`", self.name, str ))) } } fn compile_regex(name: &'static str, regex_rules: Vec) -> io::Result { const REGEX_SIZE_LIMIT: usize = usize::MAX; RegexSetBuilder::new(regex_rules) .size_limit(REGEX_SIZE_LIMIT) .unicode(false) .build() .map_err(|err| Error::other(format!("{name} regex error: {err}"))) } fn into_rules(self) -> io::Result { Ok(Rules::new( self.ipv4, self.ipv6, Self::compile_regex(self.name, self.rules_regex)?, self.rules_set, self.rules_tree, )) } } /// ACL rules /// /// ## Sections /// /// ACL File is formatted in sections, each section has a name with surrounded by brackets `[` and `]` /// followed by Rules line by line. /// /// ```plain /// [SECTION-1] /// RULE-1 /// RULE-2 /// RULE-3 /// /// [SECTION-2] /// RULE-1 /// RULE-2 /// RULE-3 /// ``` /// /// Available sections are /// /// - For local servers (`sslocal`, `ssredir`, ...) /// * `[bypass_all]` - ACL runs in `WhiteList` mode. /// * `[proxy_all]` - ACL runs in `BlackList` mode. /// * `[bypass_list]` - Rules for connecting directly /// * `[proxy_list]` - Rules for connecting through proxies /// - For remote servers (`ssserver`) /// * `[reject_all]` - ACL runs in `WhiteList` mode. /// * `[accept_all]` - ACL runs in `BlackList` mode. /// * `[black_list]` - Rules for rejecting /// * `[white_list]` - Rules for allowing /// * `[outbound_block_all]` - ACL runs in `WhiteList` mode for outbound addresses. /// * `[outbound_allow_all]` - ACL runs in `BlackList` mode for outbound addresses. /// * `[outbound_block_list]` - Rules for blocking outbound addresses. /// * `[outbound_allow_list]` - Rules for allowing outbound addresses. /// /// ## Mode /// /// Mode is the default ACL strategy for those addresses that are not in configuration file. /// /// - `WhiteList` - Bypasses / Rejects all addresses except those in `[proxy_list]` or `[white_list]` /// - `BlackList` - Proxies / Accepts all addresses except those in `[bypass_list]` or `[black_list]` /// /// ## Rules /// /// Rules can be either /// /// - CIDR form network addresses, like `10.9.0.32/16` /// - IP addresses, like `127.0.0.1` or `::1` /// - Regular Expression for matching hosts, like `(^|\.)gmail\.com$` /// - Domain with preceding `|` for exact matching, like `|google.com` /// - Domain with preceding `||` for matching with subdomains, like `||google.com` #[derive(Debug, Clone)] pub struct AccessControl { outbound_block: Rules, outbound_allow: Rules, black_list: Rules, white_list: Rules, mode: Mode, outbound_mode: Mode, file_path: PathBuf, } impl AccessControl { /// Load ACL rules from a file pub fn load_from_file>(p: P) -> io::Result { trace!("ACL loading from {:?}", p.as_ref()); let file_path_ref = p.as_ref(); let file_path = file_path_ref.to_path_buf(); let fp = File::open(file_path_ref)?; let r = BufReader::new(fp); let mut mode = Mode::BlackList; let mut outbound_mode = Mode::BlackList; let mut outbound_block = ParsingRules::new("[outbound_block_list]"); let mut outbound_allow = ParsingRules::new("[outbound_allow_list]"); let mut bypass = ParsingRules::new("[black_list] or [bypass_list]"); let mut proxy = ParsingRules::new("[white_list] or [proxy_list]"); let mut curr = &mut bypass; trace!("ACL parsing start from mode {:?} and black_list / bypass_list", mode); for line in r.lines() { let line = line?; if line.is_empty() { continue; } // Comments if line.starts_with('#') { continue; } let line = line.trim(); if !line.is_ascii() { warn!("ACL rule {} containing non-ASCII characters, skipped", line); continue; } if let Some(rule) = line.strip_prefix("||") { curr.add_tree_rule(rule)?; continue; } if let Some(rule) = line.strip_prefix('|') { curr.add_set_rule(rule)?; continue; } match line { "[reject_all]" | "[bypass_all]" => { mode = Mode::WhiteList; trace!("switch to mode {:?}", mode); } "[accept_all]" | "[proxy_all]" => { mode = Mode::BlackList; trace!("switch to mode {:?}", mode); } "[outbound_block_all]" => { outbound_mode = Mode::WhiteList; trace!("switch to outbound_mode {:?}", outbound_mode); } "[outbound_allow_all]" => { outbound_mode = Mode::BlackList; trace!("switch to outbound_mode {:?}", outbound_mode); } "[outbound_block_list]" => { curr = &mut outbound_block; trace!("loading outbound_block_list"); } "[outbound_allow_list]" => { curr = &mut outbound_allow; trace!("loading outbound_allow_list"); } "[black_list]" | "[bypass_list]" => { curr = &mut bypass; trace!("loading black_list / bypass_list"); } "[white_list]" | "[proxy_list]" => { curr = &mut proxy; trace!("loading white_list / proxy_list"); } _ => { match line.parse::() { Ok(IpNet::V4(v4)) => { curr.add_ipv4_rule(v4); } Ok(IpNet::V6(v6)) => { curr.add_ipv6_rule(v6); } Err(..) => { // Maybe it is a pure IpAddr match line.parse::() { Ok(IpAddr::V4(v4)) => { curr.add_ipv4_rule(v4); } Ok(IpAddr::V6(v6)) => { curr.add_ipv6_rule(v6); } Err(..) => { curr.add_regex_rule(line.to_owned()); } } } } } } } Ok(Self { outbound_block: outbound_block.into_rules()?, outbound_allow: outbound_allow.into_rules()?, black_list: bypass.into_rules()?, white_list: proxy.into_rules()?, mode, outbound_mode, file_path, }) } /// Get ACL file path pub fn file_path(&self) -> &Path { &self.file_path } /// Check if domain name is in proxy_list. /// If so, it should be resolved from remote (for Android's DNS relay) /// /// Return /// - `Some(true)` if `host` is in `white_list` (should be proxied) /// - `Some(false)` if `host` is in `black_list` (should be bypassed) /// - `None` if `host` doesn't match any rules pub fn check_host_in_proxy_list(&self, host: &str) -> Option { let host = Self::convert_to_ascii(host); self.check_ascii_host_in_proxy_list(&host) } /// Check if ASCII domain name is in proxy_list. /// If so, it should be resolved from remote (for Android's DNS relay) /// /// Return /// - `Some(true)` if `host` is in `white_list` (should be proxied) /// - `Some(false)` if `host` is in `black_list` (should be bypassed) /// - `None` if `host` doesn't match any rules pub fn check_ascii_host_in_proxy_list(&self, host: &str) -> Option { // Addresses in proxy_list will be proxied if self.white_list.check_host_matched(host) { return Some(true); } // Addresses in bypass_list will be bypassed if self.black_list.check_host_matched(host) { return Some(false); } None } /// If there are no IP rules #[inline] pub fn is_ip_empty(&self) -> bool { self.black_list.is_ip_empty() && self.white_list.is_ip_empty() } /// If there are no domain name rules #[inline] pub fn is_host_empty(&self) -> bool { self.black_list.is_host_empty() && self.white_list.is_host_empty() } /// Check if `IpAddr` should be proxied pub fn check_ip_in_proxy_list(&self, ip: &IpAddr) -> bool { if self.black_list.check_ip_matched(ip) { // If IP is in black_list, it should be bypassed return false; } if self.white_list.check_ip_matched(ip) { // If IP is in white_list, it should be proxied return true; } self.is_default_in_proxy_list() } /// Default mode /// /// Default behavior for hosts that are not configured /// - `true` - Proxied /// - `false` - Bypassed #[inline] pub fn is_default_in_proxy_list(&self) -> bool { match self.mode { Mode::BlackList => true, Mode::WhiteList => false, } } /// Returns the ASCII representation a domain name, /// if conversion fails returns original string fn convert_to_ascii(host: &str) -> Cow<'_, str> { idna::domain_to_ascii(host) .map(From::from) .unwrap_or_else(|_| host.into()) } /// Check if target address should be bypassed (for client) /// /// This function may perform a DNS resolution pub async fn check_target_bypassed(&self, context: &Context, addr: &Address) -> bool { match *addr { Address::SocketAddress(ref addr) => !self.check_ip_in_proxy_list(&addr.ip()), // Resolve hostname and check the list Address::DomainNameAddress(ref host, port) => { if let Some(value) = self.check_host_in_proxy_list(host) { return !value; } // If mode is BlackList, host is proxied by default. If it has any resolved IPs in black_list, then it should be bypassed. // If mode is WhiteList, host is bypassed by default. If it has any resolved IPs in white_list, then it should be proxied. let (check_list, bypass_if_matched) = match self.mode { Mode::BlackList => (&self.black_list, true), Mode::WhiteList => (&self.white_list, false), }; if check_list.is_ip_empty() { return !self.is_default_in_proxy_list(); } if let Ok(vaddr) = context.dns_resolve(host, port).await { for addr in vaddr { let ip = addr.ip(); if check_list.check_ip_matched(&ip) { return bypass_if_matched; } } } !self.is_default_in_proxy_list() } } } /// Check if client address should be blocked (for server) pub fn check_client_blocked(&self, addr: &SocketAddr) -> bool { match self.mode { Mode::BlackList => { // Only clients in black_list will be blocked self.black_list.check_ip_matched(&addr.ip()) } Mode::WhiteList => { // Only clients not in white_list will be blocked !self.white_list.check_ip_matched(&addr.ip()) } } } /// Check if outbound address is blocked (for server) /// /// NOTE: `Address::DomainName` is only validated by regex rules, /// resolved addresses are checked in the `lookup_outbound_then!` macro pub async fn check_outbound_blocked(&self, context: &Context, outbound: &Address) -> bool { match outbound { Address::SocketAddress(saddr) => self.check_outbound_ip_blocked(&saddr.ip()), Address::DomainNameAddress(host, port) => { let ascii_host = Self::convert_to_ascii(host); if self.outbound_block.check_host_matched(&ascii_host) { return true; // Blocked by config } if self.outbound_allow.check_host_matched(&ascii_host) { return false; // Allowed by config } // If no domain name rules matched, // we need to resolve the hostname to IP addresses // If mode is BlackList, host is allowed by default. If any of its resolved IPs is in outbound_block, then it is blocked. // If mode is WhiteList, host is blocked by default. If any of its resolved IPs is in outbound_allow, then it is allowed. let (check_rule, block_if_matched) = match self.outbound_mode { Mode::BlackList => (&self.outbound_block, true), Mode::WhiteList => (&self.outbound_allow, false), }; if check_rule.is_ip_empty() { // If there are no IP rules, use the default mode return self.is_outbound_default_blocked(); } if let Ok(vaddr) = context.dns_resolve(host, *port).await { for addr in vaddr { let ip = addr.ip(); if check_rule.check_ip_matched(&ip) { return block_if_matched; } } } self.is_outbound_default_blocked() } } } fn check_outbound_ip_blocked(&self, ip: &IpAddr) -> bool { if self.outbound_block.check_ip_matched(ip) { // If IP is in outbound_block, it should be blocked return true; } if self.outbound_allow.check_ip_matched(ip) { // If IP is in outbound_allow, it should be allowed return false; } // If IP is not in any list, check the default mode self.is_outbound_default_blocked() } #[inline] fn is_outbound_default_blocked(&self) -> bool { match self.outbound_mode { Mode::BlackList => false, Mode::WhiteList => true, } } } ================================================ FILE: crates/shadowsocks-service/src/acl/sub_domains_tree.rs ================================================ use std::{ collections::HashMap, fmt::{self, Debug}, }; #[derive(Debug, Clone)] struct DomainPart { included: bool, children: HashMap, } impl DomainPart { fn new() -> Self { Self { included: false, children: HashMap::new(), } } } #[derive(Clone)] pub struct SubDomainsTree(HashMap); impl Debug for SubDomainsTree { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "SubDomainsTree {{ .. }}") } } impl SubDomainsTree { pub fn new() -> Self { Self(HashMap::new()) } pub fn insert(&mut self, value: &str) { let mut current_map = &mut self.0; let mut last_included = None; for part in value.rsplit('.') { let entry = current_map .entry(part.to_ascii_lowercase()) .or_insert_with(DomainPart::new); // We don't need to include `a.b.c` if we already have `b.c` if entry.included { return; } current_map = &mut entry.children; last_included = Some(&mut entry.included); } if let Some(last_included) = last_included { *last_included = true; // Remove all subdomains to free memory. `contains` will stop here anyway. current_map.clear(); } } pub fn contains(&self, value: &str) -> bool { let mut current_map = &self.0; for part in value.rsplit('.') { if let Some(el) = current_map.get(part) { if el.included { return true; } current_map = &el.children; } else { break; } } false } pub fn is_empty(&self) -> bool { self.0.is_empty() } } ================================================ FILE: crates/shadowsocks-service/src/config.rs ================================================ //! This is a mod for storing and parsing configuration //! //! According to shadowsocks' official documentation, the standard configuration //! file should be in JSON format: //! //! ```ignore //! { //! "server": "127.0.0.1", //! "server_port": 1080, //! "local_port": 8388, //! "password": "the-password", //! "timeout": 300, //! "method": "aes-256-cfb", //! "local_address": "127.0.0.1" //! } //! ``` //! //! But this configuration is not for using multiple shadowsocks server, so we //! introduce an extended configuration file format: //! //! ```ignore //! { //! "servers": [ //! { //! "server": "127.0.0.1", //! "server_port": 1080, //! "password": "hellofuck", //! "method": "bf-cfb" //! }, //! { //! "server": "127.0.0.1", //! "server_port": 1081, //! "password": "hellofuck", //! "method": "aes-128-cfb" //! } //! ], //! "local_port": 8388, //! "local_address": "127.0.0.1" //! } //! ``` //! //! These defined server will be used with a load balancing algorithm. use std::{ borrow::Cow, convert::{From, Infallible}, default::Default, env, fmt::{self, Debug, Display, Formatter}, fs::OpenOptions, io::Read, net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6}, option::Option, path::{Path, PathBuf}, str::FromStr, string::ToString, time::Duration, }; use cfg_if::cfg_if; #[cfg(feature = "hickory-dns")] use hickory_resolver::config::{NameServerConfig, ResolverConfig}; #[cfg(feature = "local-tun")] use ipnet::IpNet; #[cfg(feature = "local-fake-dns")] use ipnet::{Ipv4Net, Ipv6Net}; use log::warn; use serde::{Deserialize, Serialize}; #[cfg(any(feature = "local-tunnel", feature = "local-dns"))] use shadowsocks::relay::socks5::Address; use shadowsocks::{ config::{ ManagerAddr, Mode, ReplayAttackPolicy, ServerAddr, ServerConfig, ServerSource, ServerUser, ServerUserManager, ServerWeight, }, crypto::CipherKind, plugin::PluginConfig, }; use crate::acl::AccessControl; #[cfg(feature = "local-dns")] use crate::local::dns::NameServerAddr; #[cfg(feature = "local-http")] use crate::local::http::config::HttpAuthConfig; #[cfg(feature = "local")] use crate::local::socks::config::Socks5AuthConfig; #[derive(Serialize, Deserialize, Debug)] #[serde(untagged)] enum SSDnsConfig { Simple(String), #[cfg(feature = "hickory-dns")] HickoryDns(ResolverConfig), } #[derive(Serialize, Deserialize, Debug, Default)] struct SSSecurityConfig { #[serde(skip_serializing_if = "Option::is_none")] replay_attack: Option, } #[derive(Serialize, Deserialize, Debug, Default)] struct SSSecurityReplayAttackConfig { #[serde(skip_serializing_if = "Option::is_none")] policy: Option, } #[derive(Serialize, Deserialize, Debug, Default)] struct SSBalancerConfig { #[serde(skip_serializing_if = "Option::is_none")] max_server_rtt: Option, #[serde(skip_serializing_if = "Option::is_none")] check_interval: Option, #[serde(skip_serializing_if = "Option::is_none")] check_best_interval: Option, } #[derive(Serialize, Deserialize, Debug, Default)] struct SSConfig { #[serde(skip_serializing_if = "Option::is_none")] server: Option, #[serde(skip_serializing_if = "Option::is_none")] server_port: Option, #[serde(skip_serializing_if = "Option::is_none")] local_address: Option, #[serde(skip_serializing_if = "Option::is_none")] local_port: Option, /// macOS launch activate socket for local_port #[cfg(target_os = "macos")] #[serde(skip_serializing_if = "Option::is_none")] launchd_udp_socket_name: Option, #[cfg(target_os = "macos")] #[serde(skip_serializing_if = "Option::is_none")] launchd_tcp_socket_name: Option, #[serde(skip_serializing_if = "Option::is_none")] protocol: Option, #[serde(skip_serializing_if = "Option::is_none")] manager_address: Option, #[serde(skip_serializing_if = "Option::is_none")] manager_port: Option, #[serde(skip_serializing_if = "Option::is_none")] password: Option, #[serde(skip_serializing_if = "Option::is_none")] method: Option, #[serde(skip_serializing_if = "Option::is_none")] plugin: Option, #[serde(skip_serializing_if = "Option::is_none")] plugin_opts: Option, #[serde(skip_serializing_if = "Option::is_none")] plugin_args: Option>, #[serde(skip_serializing_if = "Option::is_none")] plugin_mode: Option, #[serde(skip_serializing_if = "Option::is_none")] timeout: Option, #[serde(skip_serializing_if = "Option::is_none")] udp_timeout: Option, #[serde(skip_serializing_if = "Option::is_none")] udp_max_associations: Option, #[serde(skip_serializing_if = "Option::is_none")] udp_mtu: Option, #[serde(skip_serializing_if = "Option::is_none", alias = "shadowsocks")] servers: Option>, #[serde(skip_serializing_if = "Option::is_none")] locals: Option>, #[serde(skip_serializing_if = "Option::is_none")] dns: Option, #[serde(skip_serializing_if = "Option::is_none")] dns_cache_size: Option, #[serde(skip_serializing_if = "Option::is_none")] mode: Option, #[serde(skip_serializing_if = "Option::is_none")] no_delay: Option, #[serde(skip_serializing_if = "Option::is_none")] keep_alive: Option, #[cfg(all(unix, not(target_os = "android")))] #[serde(skip_serializing_if = "Option::is_none")] nofile: Option, #[serde(skip_serializing_if = "Option::is_none")] ipv6_first: Option, #[serde(skip_serializing_if = "Option::is_none")] ipv6_only: Option, #[serde(skip_serializing_if = "Option::is_none")] fast_open: Option, #[serde(skip_serializing_if = "Option::is_none")] mptcp: Option, #[serde(skip_serializing_if = "Option::is_none")] #[cfg(any(target_os = "linux", target_os = "android"))] outbound_fwmark: Option, #[serde(skip_serializing_if = "Option::is_none")] #[cfg(target_os = "freebsd")] outbound_user_cookie: Option, #[serde(skip_serializing_if = "Option::is_none")] outbound_bind_addr: Option, #[serde(skip_serializing_if = "Option::is_none")] outbound_bind_interface: Option, #[serde(skip_serializing_if = "Option::is_none")] outbound_udp_allow_fragmentation: Option, #[serde(skip_serializing_if = "Option::is_none")] security: Option, #[serde(skip_serializing_if = "Option::is_none")] balancer: Option, #[serde(skip_serializing_if = "Option::is_none")] acl: Option, #[cfg(feature = "local-online-config")] #[serde(skip_serializing_if = "Option::is_none")] version: Option, #[cfg(feature = "local-online-config")] #[serde(skip_serializing_if = "Option::is_none")] online_config: Option, } #[derive(Serialize, Deserialize, Debug, Default)] struct SSLocalExtConfig { #[serde(skip_serializing_if = "Option::is_none")] local_address: Option, #[serde(skip_serializing_if = "Option::is_none")] local_port: Option, #[serde(skip_serializing_if = "Option::is_none")] disabled: Option, #[serde(skip_serializing_if = "Option::is_none")] mode: Option, #[serde(skip_serializing_if = "Option::is_none")] local_udp_address: Option, #[serde(skip_serializing_if = "Option::is_none")] local_udp_port: Option, #[serde(skip_serializing_if = "Option::is_none")] protocol: Option, /// macOS launch activate socket #[cfg(target_os = "macos")] #[serde(skip_serializing_if = "Option::is_none")] launchd_udp_socket_name: Option, #[cfg(target_os = "macos")] #[serde(skip_serializing_if = "Option::is_none")] launchd_tcp_socket_name: Option, /// TCP Transparent Proxy type #[cfg(feature = "local-redir")] #[serde(skip_serializing_if = "Option::is_none")] tcp_redir: Option, /// UDP Transparent Proxy type #[cfg(feature = "local-redir")] #[serde(skip_serializing_if = "Option::is_none")] udp_redir: Option, /// Local DNS's address /// /// Sending DNS query directly to this address #[cfg(feature = "local-dns")] #[serde(skip_serializing_if = "Option::is_none")] local_dns_address: Option, #[cfg(feature = "local-dns")] #[serde(skip_serializing_if = "Option::is_none")] local_dns_port: Option, /// Remote DNS's address /// /// Sending DNS query through proxy to this address #[cfg(feature = "local-dns")] #[serde(skip_serializing_if = "Option::is_none")] remote_dns_address: Option, #[cfg(feature = "local-dns")] #[serde(skip_serializing_if = "Option::is_none")] remote_dns_port: Option, #[cfg(feature = "local-dns")] #[serde(skip_serializing_if = "Option::is_none")] client_cache_size: Option, /// Tunnel #[cfg(feature = "local-tunnel")] #[serde(skip_serializing_if = "Option::is_none")] forward_address: Option, #[cfg(feature = "local-tunnel")] #[serde(skip_serializing_if = "Option::is_none")] forward_port: Option, /// Tun #[cfg(feature = "local-tun")] #[serde(skip_serializing_if = "Option::is_none")] tun_interface_name: Option, #[cfg(feature = "local-tun")] #[serde(skip_serializing_if = "Option::is_none")] tun_interface_address: Option, #[cfg(feature = "local-tun")] #[serde(skip_serializing_if = "Option::is_none")] tun_interface_destination: Option, #[cfg(all(feature = "local-tun", unix))] #[serde(skip_serializing_if = "Option::is_none")] tun_device_fd_from_path: Option, /// SOCKS5 #[cfg(feature = "local")] #[serde(skip_serializing_if = "Option::is_none")] socks5_auth_config_path: Option, /// HTTP #[cfg(feature = "local-http")] #[serde(skip_serializing_if = "Option::is_none")] http_auth_config_path: Option, /// Fake DNS #[cfg(feature = "local-fake-dns")] #[serde(skip_serializing_if = "Option::is_none")] pub fake_dns_record_expire_duration: Option, #[cfg(feature = "local-fake-dns")] #[serde(skip_serializing_if = "Option::is_none")] pub fake_dns_ipv4_network: Option, #[cfg(feature = "local-fake-dns")] #[serde(skip_serializing_if = "Option::is_none")] pub fake_dns_ipv6_network: Option, #[cfg(feature = "local-fake-dns")] #[serde(skip_serializing_if = "Option::is_none")] pub fake_dns_database_path: Option, #[serde(skip_serializing_if = "Option::is_none")] acl: Option, } #[derive(Serialize, Deserialize, Debug)] struct SSServerUserConfig { name: String, password: String, } #[derive(Serialize, Deserialize, Debug)] struct SSServerExtConfig { // SIP008 https://github.com/shadowsocks/shadowsocks-org/issues/89 // // `address` and `port` are non-standard field name only for shadowsocks-rust #[serde(alias = "address")] server: String, #[serde(alias = "port")] server_port: u16, #[serde(skip_serializing_if = "Option::is_none")] password: Option, method: String, #[serde(skip_serializing_if = "Option::is_none")] users: Option>, #[serde(skip_serializing_if = "Option::is_none")] disabled: Option, #[serde(skip_serializing_if = "Option::is_none")] plugin: Option, #[serde(skip_serializing_if = "Option::is_none")] plugin_opts: Option, #[serde(skip_serializing_if = "Option::is_none")] plugin_args: Option>, #[serde(skip_serializing_if = "Option::is_none")] plugin_mode: Option, #[serde(skip_serializing_if = "Option::is_none")] timeout: Option, #[serde(skip_serializing_if = "Option::is_none", alias = "name")] remarks: Option, #[serde(skip_serializing_if = "Option::is_none")] id: Option, #[serde(skip_serializing_if = "Option::is_none")] mode: Option, #[serde(skip_serializing_if = "Option::is_none")] tcp_weight: Option, #[serde(skip_serializing_if = "Option::is_none")] udp_weight: Option, #[serde(skip_serializing_if = "Option::is_none")] acl: Option, #[serde(skip_serializing_if = "Option::is_none")] #[cfg(any(target_os = "linux", target_os = "android"))] outbound_fwmark: Option, #[serde(skip_serializing_if = "Option::is_none")] #[cfg(target_os = "freebsd")] outbound_user_cookie: Option, #[serde(skip_serializing_if = "Option::is_none")] outbound_bind_addr: Option, #[serde(skip_serializing_if = "Option::is_none")] outbound_bind_interface: Option, #[serde(skip_serializing_if = "Option::is_none")] outbound_udp_allow_fragmentation: Option, } #[cfg(feature = "local-online-config")] #[derive(Serialize, Deserialize, Debug, Default)] struct SSOnlineConfig { config_url: String, #[serde(skip_serializing_if = "Option::is_none")] update_interval: Option, #[serde(skip_serializing_if = "Option::is_none")] allowed_plugins: Option>, } /// Server config type #[derive(Clone, Copy, Debug, Eq, PartialEq)] pub enum ConfigType { /// Config for local Local, /// Config for server Server, /// Config for Manager server Manager, /// Config for online config (SIP008) /// https://shadowsocks.org/doc/sip008.html #[cfg(feature = "local-online-config")] OnlineConfig, } impl ConfigType { /// Check if it is local server type pub fn is_local(self) -> bool { self == Self::Local } /// Check if it is remote server type pub fn is_server(self) -> bool { self == Self::Server } /// Check if it is manager server type pub fn is_manager(self) -> bool { self == Self::Manager } /// Check if it is online config type (SIP008) #[cfg(feature = "local-online-config")] pub fn is_online_config(self) -> bool { self == Self::OnlineConfig } } cfg_if! { if #[cfg(feature = "local-redir")] { /// Transparent Proxy type #[derive(Clone, Copy, Debug, Eq, PartialEq)] pub enum RedirType { /// For not supported platforms NotSupported, /// For Linux-like systems' Netfilter `REDIRECT`. Only for TCP connections. /// /// This is supported from Linux 2.4 Kernel. Document: /// /// NOTE: Filter rule `REDIRECT` can only be applied to TCP connections. #[cfg(any(target_os = "linux", target_os = "android"))] Redirect, /// For Linux-like systems' Netfilter TPROXY rule. /// /// NOTE: Filter rule `TPROXY` can be applied to TCP and UDP connections. #[cfg(any(target_os = "linux", target_os = "android"))] TProxy, /// Packet Filter (pf) /// /// Supported by OpenBSD 3.0+, FreeBSD 5.3+, NetBSD 3.0+, Solaris 11.3+, macOS 10.7+, iOS, QNX /// /// Document: #[cfg(any( target_os = "freebsd", target_os = "openbsd", target_os = "macos", target_os = "ios" ))] PacketFilter, /// IPFW /// /// Supported by FreeBSD, macOS 10.6- (Have been removed completely on macOS 10.10) /// /// Document: https://www.freebsd.org/doc/handbook/firewalls-ipfw.html #[cfg(any(target_os = "freebsd", target_os = "macos", target_os = "ios"))] IpFirewall, } impl RedirType { cfg_if! { if #[cfg(any(target_os = "linux", target_os = "android"))] { /// Default TCP transparent proxy solution on this platform pub const fn tcp_default() -> Self { Self::Redirect } /// Available TCP transparent proxy types #[doc(hidden)] pub fn tcp_available_types() -> &'static [&'static str] { const AVAILABLE_TYPES: &[&str] = &[RedirType::Redirect.name(), RedirType::TProxy.name()]; AVAILABLE_TYPES } /// Default UDP transparent proxy solution on this platform pub const fn udp_default() -> Self { Self::TProxy } /// Available UDP transparent proxy types #[doc(hidden)] pub fn udp_available_types() -> &'static [&'static str] { const AVAILABLE_TYPES: &[&str] = &[RedirType::TProxy.name()]; AVAILABLE_TYPES } } else if #[cfg(any(target_os = "freebsd"))] { /// Default TCP transparent proxy solution on this platform pub fn tcp_default() -> RedirType { RedirType::PacketFilter } /// Available TCP transparent proxy types #[doc(hidden)] pub fn tcp_available_types() -> &'static [&'static str] { const AVAILABLE_TYPES: &[&str] = &[RedirType::PacketFilter.name(), RedirType::IpFirewall.name()]; AVAILABLE_TYPES } /// Default UDP transparent proxy solution on this platform pub fn udp_default() -> RedirType { RedirType::PacketFilter } /// Available UDP transparent proxy types #[doc(hidden)] pub const fn udp_available_types() -> &'static [&'static str] { const AVAILABLE_TYPES: &[&str] = &[RedirType::PacketFilter.name(), RedirType::IpFirewall.name()]; AVAILABLE_TYPES } } else if #[cfg(target_os = "openbsd")] { /// Default TCP transparent proxy solution on this platform pub fn tcp_default() -> RedirType { RedirType::PacketFilter } /// Available TCP transparent proxy types #[doc(hidden)] pub fn tcp_available_types() -> &'static [&'static str] { const AVAILABLE_TYPES: &[&str] = &[RedirType::PacketFilter.name()]; AVAILABLE_TYPES } /// Default UDP transparent proxy solution on this platform pub fn udp_default() -> RedirType { RedirType::PacketFilter } /// Available UDP transparent proxy types #[doc(hidden)] pub const fn udp_available_types() -> &'static [&'static str] { const AVAILABLE_TYPES: &[&str] = &[RedirType::PacketFilter.name()]; AVAILABLE_TYPES } } else if #[cfg(any(target_os = "macos", target_os = "ios"))] { /// Default TCP transparent proxy solution on this platform pub fn tcp_default() -> RedirType { RedirType::PacketFilter } /// Available TCP transparent proxy types #[doc(hidden)] pub const fn tcp_available_types() -> &'static [&'static str] { const AVAILABLE_TYPES: &[&str] = &[RedirType::PacketFilter.name(), RedirType::IpFirewall.name()]; AVAILABLE_TYPES } /// Default UDP transparent proxy solution on this platform pub fn udp_default() -> RedirType { RedirType::PacketFilter } /// Available UDP transparent proxy types #[doc(hidden)] pub const fn udp_available_types() -> &'static [&'static str] { const AVAILABLE_TYPES: &[&str] = &[RedirType::PacketFilter.name()]; AVAILABLE_TYPES } } else { /// Default TCP transparent proxy solution on this platform pub fn tcp_default() -> RedirType { RedirType::NotSupported } /// Available TCP transparent proxy types #[doc(hidden)] pub const fn tcp_available_types() -> &'static [&'static str] { const AVAILABLE_TYPES: &[&str] = &[]; AVAILABLE_TYPES } /// Default UDP transparent proxy solution on this platform pub fn udp_default() -> RedirType { RedirType::NotSupported } /// Available UDP transparent proxy types #[doc(hidden)] pub const fn udp_available_types() -> &'static [&'static str] { const AVAILABLE_TYPES: &[&str] = &[]; AVAILABLE_TYPES } } } /// Check if transparent proxy is supported on this platform pub fn is_supported(self) -> bool { self != Self::NotSupported } /// Name of redirect type (transparent proxy type) pub const fn name(self) -> &'static str { match self { // Dummy, shouldn't be used in any useful situations Self::NotSupported => "not_supported", #[cfg(any(target_os = "linux", target_os = "android"))] Self::Redirect => "redirect", #[cfg(any(target_os = "linux", target_os = "android"))] Self::TProxy => "tproxy", #[cfg(any( target_os = "freebsd", target_os = "openbsd", target_os = "macos", target_os = "ios" ))] RedirType::PacketFilter => "pf", #[cfg(any(target_os = "freebsd", target_os = "macos", target_os = "ios"))] RedirType::IpFirewall => "ipfw", } } } impl Display for RedirType { fn fmt(&self, f: &mut Formatter) -> fmt::Result { f.write_str(self.name()) } } /// Error type for `RedirType`'s `FromStr::Err` #[derive(Debug)] pub struct InvalidRedirType; impl Display for InvalidRedirType { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.write_str("invalid RedirType") } } impl FromStr for RedirType { type Err = InvalidRedirType; fn from_str(s: &str) -> Result { match s { #[cfg(any(target_os = "linux", target_os = "android"))] "redirect" => Ok(Self::Redirect), #[cfg(any(target_os = "linux", target_os = "android"))] "tproxy" => Ok(Self::TProxy), #[cfg(any( target_os = "freebsd", target_os = "openbsd", target_os = "macos", target_os = "ios", ))] "pf" => Ok(RedirType::PacketFilter), #[cfg(any( target_os = "freebsd", target_os = "macos", target_os = "ios", ))] "ipfw" => Ok(RedirType::IpFirewall), _ => Err(InvalidRedirType), } } } } } /// Host for servers to bind /// /// Servers will bind to a port of this host #[derive(Clone, Debug)] pub enum ManagerServerHost { /// Domain name Domain(String), /// IP address Ip(IpAddr), } impl Default for ManagerServerHost { fn default() -> Self { Self::Ip(Ipv4Addr::UNSPECIFIED.into()) } } impl FromStr for ManagerServerHost { type Err = Infallible; fn from_str(s: &str) -> Result { match s.parse::() { Ok(s) => Ok(Self::Ip(s)), Err(..) => Ok(Self::Domain(s.to_owned())), } } } /// Mode of Manager's server #[derive(Debug, Clone, Copy, Eq, PartialEq, Default)] pub enum ManagerServerMode { /// Run shadowsocks server in the same process of manager #[default] Builtin, /// Run shadowsocks server in standalone (process) mode #[cfg(unix)] Standalone, } /// Parsing ManagerServerMode error #[derive(Debug, Clone, Copy)] pub struct ManagerServerModeError; impl Display for ManagerServerModeError { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { f.write_str("invalid ManagerServerMode") } } impl FromStr for ManagerServerMode { type Err = ManagerServerModeError; fn from_str(s: &str) -> Result { match s { "builtin" => Ok(Self::Builtin), #[cfg(unix)] "standalone" => Ok(Self::Standalone), _ => Err(ManagerServerModeError), } } } impl Display for ManagerServerMode { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { Self::Builtin => f.write_str("builtin"), #[cfg(unix)] Self::Standalone => f.write_str("standalone"), } } } /// Configuration for Manager #[derive(Clone, Debug)] pub struct ManagerConfig { /// Address of `ss-manager`. Send servers' statistic data to the manager server pub addr: ManagerAddr, /// Manager's default method pub method: Option, /// Manager's default plugin pub plugin: Option, /// Timeout for TCP connections, setting to manager's created servers pub timeout: Option, /// IP/Host for servers to bind (inbound) /// /// Note: Outbound address is defined in Config.local_addr pub server_host: ManagerServerHost, /// Server's mode pub mode: Mode, /// Server's running mode pub server_mode: ManagerServerMode, /// Server's command if running in Standalone mode #[cfg(unix)] pub server_program: String, /// Server's working directory if running in Standalone mode #[cfg(unix)] pub server_working_directory: PathBuf, } impl ManagerConfig { /// Create a ManagerConfig with default options pub fn new(addr: ManagerAddr) -> Self { Self { addr, method: None, plugin: None, timeout: None, server_host: ManagerServerHost::default(), mode: Mode::TcpOnly, server_mode: ManagerServerMode::Builtin, #[cfg(unix)] server_program: "ssserver".to_owned(), #[cfg(unix)] server_working_directory: match std::env::current_dir() { Ok(d) => d, Err(..) => "/tmp/shadowsocks-manager".into(), }, } } } /// Protocol of local server #[derive(Debug, Default, Clone, Copy, Eq, PartialEq)] pub enum ProtocolType { #[default] Socks, #[cfg(feature = "local-http")] Http, #[cfg(feature = "local-tunnel")] Tunnel, #[cfg(feature = "local-redir")] Redir, #[cfg(feature = "local-dns")] Dns, #[cfg(feature = "local-tun")] Tun, #[cfg(feature = "local-fake-dns")] FakeDns, } impl ProtocolType { /// As string representation pub fn as_str(&self) -> &'static str { match *self { Self::Socks => "socks", #[cfg(feature = "local-http")] Self::Http => "http", #[cfg(feature = "local-tunnel")] Self::Tunnel => "tunnel", #[cfg(feature = "local-redir")] Self::Redir => "redir", #[cfg(feature = "local-dns")] Self::Dns => "dns", #[cfg(feature = "local-tun")] Self::Tun => "tun", #[cfg(feature = "local-fake-dns")] Self::FakeDns => "fake-dns", } } /// Get all available protocols pub fn available_protocols() -> &'static [&'static str] { &[ "socks", #[cfg(feature = "local-http")] "http", #[cfg(feature = "local-tunnel")] "tunnel", #[cfg(feature = "local-redir")] "redir", #[cfg(feature = "local-dns")] "dns", #[cfg(feature = "local-tun")] "tun", #[cfg(feature = "local-fake-dns")] "fake-dns", ] } } /// Error while parsing `ProtocolType` from string #[derive(Debug)] pub struct ProtocolTypeError; impl Display for ProtocolTypeError { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { f.write_str("invalid ProtocolType") } } impl FromStr for ProtocolType { type Err = ProtocolTypeError; fn from_str(s: &str) -> Result { match s { "socks" => Ok(Self::Socks), #[cfg(feature = "local-http")] "http" => Ok(Self::Http), #[cfg(feature = "local-tunnel")] "tunnel" => Ok(Self::Tunnel), #[cfg(feature = "local-redir")] "redir" => Ok(Self::Redir), #[cfg(feature = "local-dns")] "dns" => Ok(Self::Dns), #[cfg(feature = "local-tun")] "tun" => Ok(Self::Tun), #[cfg(feature = "local-fake-dns")] "fake-dns" => Ok(Self::FakeDns), _ => Err(ProtocolTypeError), } } } /// Local server configuration #[derive(Clone, Debug)] pub struct LocalConfig { /// Listen address for local servers pub addr: Option, /// Local Protocol pub protocol: ProtocolType, /// Mode /// Uses global `mode` if not specified pub mode: Mode, /// UDP server bind address. Uses `addr` if not specified /// /// Resolving Android's issue: [shadowsocks/shadowsocks-android#2571](https://github.com/shadowsocks/shadowsocks-android/issues/2571) pub udp_addr: Option, /// UDP Associate address. Uses `udp_addr` if not specified pub udp_associate_addr: Option, /// Destination address for tunnel #[cfg(feature = "local-tunnel")] pub forward_addr: Option
, /// TCP Transparent Proxy type #[cfg(feature = "local-redir")] pub tcp_redir: RedirType, /// UDP Transparent Proxy type #[cfg(feature = "local-redir")] pub udp_redir: RedirType, /// Local DNS's address /// /// Sending DNS query directly to this address #[cfg(feature = "local-dns")] pub local_dns_addr: Option, /// Remote DNS's address /// /// Sending DNS query through proxy to this address #[cfg(feature = "local-dns")] pub remote_dns_addr: Option
, // client cache size // if a lot of `create connection` observed in log, // increase the size #[cfg(feature = "local-dns")] pub client_cache_size: Option, /// Tun interface's name /// /// Linux: eth0, eth1, ... /// macOS: utun0, utun1, ... #[cfg(feature = "local-tun")] pub tun_interface_name: Option, /// Tun interface's address and netmask #[cfg(feature = "local-tun")] pub tun_interface_address: Option, /// Tun interface's destination address and netmask #[cfg(feature = "local-tun")] pub tun_interface_destination: Option, /// Tun interface's file descriptor #[cfg(all(feature = "local-tun", unix))] pub tun_device_fd: Option, /// Tun interface's file descriptor read from this Unix Domain Socket #[cfg(all(feature = "local-tun", unix))] pub tun_device_fd_from_path: Option, /// macOS launchd socket for TCP listener /// /// /// /// /// ```plist /// Sockets /// /// {launchd_tcp_socket_name} /// /// SockType /// stream /// ... other keys ... /// /// /// ``` #[cfg(target_os = "macos")] pub launchd_tcp_socket_name: Option, /// macOS launchd socket for UDP listener /// /// /// /// /// ```plist /// Sockets /// /// {launchd_udp_socket_name} /// /// SockType /// dgram /// ... other keys ... /// /// /// ``` #[cfg(target_os = "macos")] pub launchd_udp_socket_name: Option, /// Set `IPV6_V6ONLY` for listener socket pub ipv6_only: bool, /// SOCKS5 Authentication configuration #[cfg(feature = "local")] pub socks5_auth: Socks5AuthConfig, /// HTTP Authentication configuration #[cfg(feature = "local-http")] pub http_auth: HttpAuthConfig, /// Fake DNS record expire seconds #[cfg(feature = "local-fake-dns")] pub fake_dns_record_expire_duration: Option, /// Fake DNS IPv4 allocation space #[cfg(feature = "local-fake-dns")] pub fake_dns_ipv4_network: Option, /// Fake DNS IPv6 allocation space #[cfg(feature = "local-fake-dns")] pub fake_dns_ipv6_network: Option, /// Fake DNS storage database path #[cfg(feature = "local-fake-dns")] pub fake_dns_database_path: Option, } impl LocalConfig { /// Create a new `LocalConfig` pub fn new(protocol: ProtocolType) -> Self { // DNS server runs in `TcpAndUdp` mode by default to maintain backwards compatibility // see https://github.com/shadowsocks/shadowsocks-rust/issues/1281 let mode = match protocol { #[cfg(feature = "local-dns")] ProtocolType::Dns => Mode::TcpAndUdp, _ => Mode::TcpOnly, }; Self { addr: None, protocol, mode, udp_addr: None, udp_associate_addr: None, #[cfg(feature = "local-tunnel")] forward_addr: None, #[cfg(feature = "local-redir")] tcp_redir: RedirType::tcp_default(), #[cfg(feature = "local-redir")] udp_redir: RedirType::udp_default(), #[cfg(feature = "local-dns")] local_dns_addr: None, #[cfg(feature = "local-dns")] remote_dns_addr: None, #[cfg(feature = "local-dns")] client_cache_size: None, #[cfg(feature = "local-tun")] tun_interface_name: None, #[cfg(feature = "local-tun")] tun_interface_address: None, #[cfg(feature = "local-tun")] tun_interface_destination: None, #[cfg(all(feature = "local-tun", unix))] tun_device_fd: None, #[cfg(all(feature = "local-tun", unix))] tun_device_fd_from_path: None, #[cfg(target_os = "macos")] launchd_tcp_socket_name: None, #[cfg(target_os = "macos")] launchd_udp_socket_name: None, ipv6_only: false, #[cfg(feature = "local")] socks5_auth: Socks5AuthConfig::default(), #[cfg(feature = "local-http")] http_auth: HttpAuthConfig::default(), #[cfg(feature = "local-fake-dns")] fake_dns_record_expire_duration: None, #[cfg(feature = "local-fake-dns")] fake_dns_ipv4_network: None, #[cfg(feature = "local-fake-dns")] fake_dns_ipv6_network: None, #[cfg(feature = "local-fake-dns")] fake_dns_database_path: None, } } /// Create a new `LocalConfig` with listen address pub fn new_with_addr(addr: ServerAddr, protocol: ProtocolType) -> Self { let mut config = Self::new(protocol); config.addr = Some(addr); config } fn check_integrity(&self) -> Result<(), Error> { match self.protocol { #[cfg(feature = "local-tun")] ProtocolType::Tun => {} _ => { if self.addr.is_none() { let err = Error::new(ErrorKind::MissingField, "missing `addr` in configuration", None); return Err(err); } } } match self.protocol { #[cfg(feature = "local-dns")] ProtocolType::Dns => { if self.local_dns_addr.is_none() || self.remote_dns_addr.is_none() { let err = Error::new( ErrorKind::MissingField, "missing `local_dns_addr` or `remote_dns_addr` in configuration", None, ); return Err(err); } } #[cfg(feature = "local-tunnel")] ProtocolType::Tunnel => { if self.forward_addr.is_none() { let err = Error::new(ErrorKind::MissingField, "missing `forward_addr` in configuration", None); return Err(err); } } #[cfg(feature = "local-http")] ProtocolType::Http => { if !self.mode.enable_tcp() { let err = Error::new(ErrorKind::Invalid, "TCP mode have to be enabled for http", None); return Err(err); } } _ => {} } Ok(()) } // Check if it is a basic format of local pub fn is_basic(&self) -> bool { if self.protocol != ProtocolType::Socks || self.udp_addr.is_some() { return false; } #[cfg(feature = "local-tunnel")] if self.forward_addr.is_some() { return false; } #[cfg(feature = "local-redir")] if self.tcp_redir != RedirType::tcp_default() || self.udp_redir != RedirType::udp_default() { return false; } #[cfg(feature = "local-dns")] if self.local_dns_addr.is_some() || self.remote_dns_addr.is_some() { return false; } true } } #[derive(Clone, Debug, Default)] pub enum DnsConfig { #[default] System, #[cfg(feature = "hickory-dns")] HickoryDns(ResolverConfig), #[cfg(feature = "local-dns")] LocalDns(NameServerAddr), } /// Security Config #[derive(Clone, Debug, Default)] pub struct SecurityConfig { pub replay_attack: SecurityReplayAttackConfig, } #[derive(Clone, Debug, Default)] pub struct SecurityReplayAttackConfig { pub policy: ReplayAttackPolicy, } /// Balancer Config #[derive(Clone, Debug, Default)] pub struct BalancerConfig { /// MAX rtt of servers, which is the timeout duration of each check requests pub max_server_rtt: Option, /// Interval between each checking pub check_interval: Option, /// Interval for checking the best server pub check_best_interval: Option, } /// Address for local to report flow statistic data #[cfg(feature = "local-flow-stat")] #[derive(Debug, Clone)] pub enum LocalFlowStatAddress { /// UNIX Domain Socket address #[cfg(unix)] UnixStreamPath(PathBuf), /// TCP Stream Address TcpStreamAddr(SocketAddr), } /// Server instance config #[derive(Debug, Clone)] pub struct ServerInstanceConfig { /// Server's config pub config: ServerConfig, /// Server's private ACL, set to `None` will use the global `AccessControl` pub acl: Option, /// Server's outbound fwmark / address / interface to support split tunnel #[cfg(any(target_os = "linux", target_os = "android"))] pub outbound_fwmark: Option, #[cfg(target_os = "freebsd")] pub outbound_user_cookie: Option, pub outbound_bind_addr: Option, pub outbound_bind_interface: Option, pub outbound_udp_allow_fragmentation: Option, } impl ServerInstanceConfig { /// Create with `ServerConfig` pub fn with_server_config(config: ServerConfig) -> Self { Self { config, acl: None, #[cfg(any(target_os = "linux", target_os = "android"))] outbound_fwmark: None, #[cfg(target_os = "freebsd")] outbound_user_cookie: None, outbound_bind_addr: None, outbound_bind_interface: None, outbound_udp_allow_fragmentation: None, } } } /// Local instance config #[derive(Debug, Clone)] pub struct LocalInstanceConfig { /// Local server's config pub config: LocalConfig, /// Server's private ACL, set to `None` will use the global `AccessControl` pub acl: Option, } impl LocalInstanceConfig { /// Create with `LocalConfig` pub fn with_local_config(config: LocalConfig) -> Self { Self { config, acl: None } } } /// OnlineConfiguration (SIP008) /// https://shadowsocks.org/doc/sip008.html #[cfg(feature = "local-online-config")] #[derive(Debug, Clone)] pub struct OnlineConfig { /// SIP008 URL pub config_url: String, /// Update interval, 3600s by default pub update_interval: Option, /// Allowed plugins pub allowed_plugins: Option>, } /// Configuration #[derive(Clone, Debug)] pub struct Config { /// Remote ShadowSocks server configurations pub server: Vec, /// Local server configuration pub local: Vec, /// DNS configuration, uses system-wide DNS configuration by default /// /// Value could be a `IpAddr`, uses UDP DNS protocol with port `53`. For example: `8.8.8.8` /// /// Also Value could be some pre-defined DNS server names: /// /// - `google` /// - `cloudflare`, `cloudflare_tls`, `cloudflare_https` /// - `quad9`, `quad9_tls` pub dns: DnsConfig, pub dns_cache_size: Option, /// Uses IPv6 addresses first /// /// Set to `true` if you want to query IPv6 addresses before IPv4 pub ipv6_first: bool, /// Set `IPV6_V6ONLY` for listener sockets pub ipv6_only: bool, /// Set `TCP_NODELAY` socket option pub no_delay: bool, /// Set `TCP_FASTOPEN` socket option pub fast_open: bool, /// Set TCP Keep-Alive duration, will set both `TCP_KEEPIDLE` and `TCP_KEEPINTVL` /// /// /// /// If this is not set, sockets will be set with a default timeout pub keep_alive: Option, /// Multipath-TCP pub mptcp: bool, /// `RLIMIT_NOFILE` option for *nix systems #[cfg(all(unix, not(target_os = "android")))] pub nofile: Option, /// Set `SO_MARK` socket option for outbound sockets #[cfg(any(target_os = "linux", target_os = "android"))] pub outbound_fwmark: Option, /// Set `SO_USER_COOKIE` socket option for outbound sockets #[cfg(target_os = "freebsd")] pub outbound_user_cookie: Option, /// Set `SO_BINDTODEVICE` (Linux), `IP_BOUND_IF` (BSD), `IP_UNICAST_IF` (Windows) socket option for outbound sockets pub outbound_bind_interface: Option, /// Outbound sockets will `bind` to this address pub outbound_bind_addr: Option, /// Outbound UDP sockets allow IP fragmentation pub outbound_udp_allow_fragmentation: bool, /// Path to protect callback unix address, only for Android #[cfg(target_os = "android")] pub outbound_vpn_protect_path: Option, /// Set `SO_SNDBUF` for inbound sockets pub inbound_send_buffer_size: Option, /// Set `SO_RCVBUF` for inbound sockets pub inbound_recv_buffer_size: Option, /// Set `SO_SNDBUF` for outbound sockets pub outbound_send_buffer_size: Option, /// Set `SO_RCVBUF` for outbound sockets pub outbound_recv_buffer_size: Option, /// Manager's configuration pub manager: Option, /// Config is for Client or Server pub config_type: ConfigType, /// Timeout for UDP Associations, default is 5 minutes pub udp_timeout: Option, /// Maximum number of UDP Associations, default is unconfigured pub udp_max_associations: Option, /// Maximum Transmission Unit (MTU) size for UDP packets /// 65535 by default. Suggestion: 1500 /// NOTE: mtu includes IP header, UDP header, UDP payload pub udp_mtu: Option, /// ACL configuration (Global) /// /// Could be overwritten by servers/locals' private `acl` pub acl: Option, /// Flow statistic report Unix socket path (only for Android) #[cfg(feature = "local-flow-stat")] pub local_stat_addr: Option, /// Replay attack policy pub security: SecurityConfig, /// Balancer config of local server pub balancer: BalancerConfig, /// Configuration file path, the actual path of the configuration. /// This is normally for auto-reloading if implementation supports. pub config_path: Option, /// OnlineConfiguration (SIP008) /// https://shadowsocks.org/doc/sip008.html #[cfg(feature = "local-online-config")] pub online_config: Option, } /// Configuration parsing error kind #[derive(Copy, Clone, Debug)] pub enum ErrorKind { /// Missing required fields in JSON configuration MissingField, /// Missing some keys that must be provided together Malformed, /// Invalid value of some configuration keys Invalid, /// Invalid JSON JsonParsingError, /// `std::io::Error` IoError, } /// Configuration parsing error pub struct Error { pub kind: ErrorKind, pub desc: &'static str, pub detail: Option, } impl Error { pub fn new(kind: ErrorKind, desc: &'static str, detail: Option) -> Self { Self { kind, desc, detail } } } impl std::error::Error for Error { fn description(&self) -> &str { self.desc } } macro_rules! impl_from { ($error:ty, $kind:expr, $desc:expr) => { impl From<$error> for Error { fn from(err: $error) -> Self { Error::new($kind, $desc, Some(format!("{:?}", err))) } } }; } impl_from!(::std::io::Error, ErrorKind::IoError, "error while reading file"); impl_from!(json5::Error, ErrorKind::JsonParsingError, "json parse error"); impl_from!(serde_json::Error, ErrorKind::JsonParsingError, "json parse error"); impl Debug for Error { fn fmt(&self, f: &mut Formatter) -> fmt::Result { match self.detail { None => write!(f, "{}", self.desc), Some(ref det) => write!(f, "{} {}", self.desc, det), } } } impl Display for Error { fn fmt(&self, f: &mut Formatter) -> fmt::Result { match self.detail { None => f.write_str(self.desc), Some(ref d) => write!(f, "{}, {}", self.desc, d), } } } impl Config { /// Creates an empty configuration pub fn new(config_type: ConfigType) -> Self { Self { server: Vec::new(), local: Vec::new(), dns: DnsConfig::default(), dns_cache_size: None, ipv6_first: false, ipv6_only: false, no_delay: false, fast_open: false, keep_alive: None, mptcp: false, #[cfg(all(unix, not(target_os = "android")))] nofile: None, #[cfg(any(target_os = "linux", target_os = "android"))] outbound_fwmark: None, #[cfg(target_os = "freebsd")] outbound_user_cookie: None, outbound_bind_interface: None, outbound_bind_addr: None, outbound_udp_allow_fragmentation: false, #[cfg(target_os = "android")] outbound_vpn_protect_path: None, inbound_send_buffer_size: None, inbound_recv_buffer_size: None, outbound_send_buffer_size: None, outbound_recv_buffer_size: None, manager: None, config_type, udp_timeout: None, udp_max_associations: None, udp_mtu: None, acl: None, #[cfg(feature = "local-flow-stat")] local_stat_addr: None, security: SecurityConfig::default(), balancer: BalancerConfig::default(), config_path: None, #[cfg(feature = "local-online-config")] online_config: None, } } fn load_from_ssconfig(config: SSConfig, config_type: ConfigType) -> Result { let mut nconfig = Self::new(config_type); // Client // // local_address is allowed to be NULL, which means to bind to ::1 or 127.0.0.1 // // https://shadowsocks.org/en/config/quick-guide.html #[inline] fn get_local_address(local_address: Option, local_port: u16, ipv6_first: bool) -> ServerAddr { match local_address { Some(addr) => { match addr.parse::() { Ok(ip) => ServerAddr::from(SocketAddr::new(ip, local_port)), Err(..) => { // treated as domain ServerAddr::from((addr, local_port)) } } } None => { // Implementation note: This is not implemented like libev which will choose IPv6 or IPv6 LoopBack address // by checking all its remote servers if all of them supports IPv6. let ip = if ipv6_first { Ipv6Addr::LOCALHOST.into() } else { Ipv4Addr::LOCALHOST.into() }; ServerAddr::from(SocketAddr::new(ip, local_port)) } } } // Mode let mut global_mode = Mode::TcpOnly; if let Some(m) = config.mode { match m.parse::() { Ok(xm) => global_mode = xm, Err(..) => { let e = Error::new( ErrorKind::Malformed, "malformed `mode`, must be one of `tcp_only`, `udp_only` and `tcp_and_udp`", None, ); return Err(e); } } } match config_type { ConfigType::Local => { // Standard config if config.local_address.is_some() && config.local_port.unwrap_or(0) == 0 { let err = Error::new(ErrorKind::MissingField, "missing `local_port`", None); return Err(err); } if let Some(local_port) = config.local_port { // local_port won't be 0, it was checked above assert_ne!(local_port, 0); let local_addr = get_local_address(config.local_address, local_port, config.ipv6_first.unwrap_or(false)); // shadowsocks uses SOCKS5 by default let mut local_config = LocalConfig::new(ProtocolType::Socks); local_config.addr = Some(local_addr); local_config.mode = global_mode; local_config.protocol = match config.protocol { None => ProtocolType::Socks, Some(p) => match p.parse::() { Ok(p) => p, Err(..) => { let err = Error::new( ErrorKind::Malformed, "`protocol` invalid", Some(format!("unrecognized protocol {p}")), ); return Err(err); } }, }; #[cfg(target_os = "macos")] { local_config .launchd_tcp_socket_name .clone_from(&config.launchd_tcp_socket_name); local_config .launchd_udp_socket_name .clone_from(&config.launchd_udp_socket_name); } let local_instance = LocalInstanceConfig { config: local_config, acl: None, }; nconfig.local.push(local_instance); } // Ext locals // `locals` are only effective in local server if let Some(locals) = config.locals { for local in locals { if local.disabled.unwrap_or(false) { continue; } let protocol = match local.protocol { None => ProtocolType::Socks, Some(p) => match p.parse::() { Ok(p) => p, Err(..) => { let err = Error::new( ErrorKind::Malformed, "`protocol` invalid", Some(format!("unrecognized protocol {p}")), ); return Err(err); } }, }; let mut local_config = LocalConfig::new(protocol); if let Some(local_port) = local.local_port { if local_port == 0 { let err = Error::new(ErrorKind::Malformed, "`local_port` cannot be 0", None); return Err(err); } let local_addr = get_local_address(local.local_address, local_port, config.ipv6_first.unwrap_or(false)); local_config.addr = Some(local_addr); } else if local.local_address.is_some() { let err = Error::new(ErrorKind::Malformed, "missing `local_port`", None); return Err(err); } if let Some(local_udp_port) = local.local_udp_port { if local_udp_port == 0 { let err = Error::new(ErrorKind::Malformed, "`local_udp_port` cannot be 0", None); return Err(err); } let local_udp_addr = get_local_address( local.local_udp_address, local_udp_port, config.ipv6_first.unwrap_or(false), ); local_config.udp_addr = Some(local_udp_addr); } #[cfg(target_os = "macos")] { local_config.launchd_tcp_socket_name = local.launchd_tcp_socket_name; local_config.launchd_udp_socket_name = local.launchd_udp_socket_name; } match local.mode { Some(mode) => match mode.parse::() { Ok(mode) => local_config.mode = mode, Err(..) => { let err = Error::new(ErrorKind::Malformed, "invalid `mode`", None); return Err(err); } }, None => { // DNS server runs in `TcpAndUdp` mode by default to maintain backwards compatibility // see https://github.com/shadowsocks/shadowsocks-rust/issues/1281 let mode = match protocol { #[cfg(feature = "local-dns")] ProtocolType::Dns => Mode::TcpAndUdp, _ => global_mode, }; local_config.mode = mode; } } #[cfg(feature = "local-tunnel")] if let Some(forward_address) = local.forward_address { let forward_port = match local.forward_port { None | Some(0) => { let err = Error::new(ErrorKind::Malformed, "`forward_port` cannot be missing or 0", None); return Err(err); } Some(p) => p, }; local_config.forward_addr = Some(match forward_address.parse::() { Ok(ip) => Address::from(SocketAddr::new(ip, forward_port)), Err(..) => Address::from((forward_address, forward_port)), }); } #[cfg(feature = "local-redir")] if let Some(tcp_redir) = local.tcp_redir { match tcp_redir.parse::() { Ok(r) => local_config.tcp_redir = r, Err(..) => { let err = Error::new(ErrorKind::Malformed, "`tcp_redir` invalid", None); return Err(err); } } } #[cfg(feature = "local-redir")] if let Some(udp_redir) = local.udp_redir { match udp_redir.parse::() { Ok(r) => local_config.udp_redir = r, Err(..) => { let err = Error::new(ErrorKind::Malformed, "`udp_redir` invalid", None); return Err(err); } } } #[cfg(feature = "local-dns")] if let Some(local_dns_address) = local.local_dns_address { match local_dns_address.parse::() { Ok(ip) => { local_config.local_dns_addr = Some(NameServerAddr::SocketAddr(SocketAddr::new( ip, local.local_dns_port.unwrap_or(53), ))); } #[cfg(unix)] Err(..) => { local_config.local_dns_addr = Some(NameServerAddr::UnixSocketAddr(PathBuf::from(local_dns_address))); } #[cfg(not(unix))] Err(..) => { let err = Error::new(ErrorKind::Malformed, "`local_dns_address` invalid", None); return Err(err); } } } #[cfg(feature = "local-dns")] if let Some(client_cache_size) = local.client_cache_size { local_config.client_cache_size = Some(client_cache_size); } #[cfg(feature = "local-dns")] if let Some(remote_dns_address) = local.remote_dns_address { let remote_dns_port = local.remote_dns_port.unwrap_or(53); local_config.remote_dns_addr = Some(match remote_dns_address.parse::() { Ok(ip) => Address::from(SocketAddr::new(ip, remote_dns_port)), Err(..) => Address::from((remote_dns_address, remote_dns_port)), }); } #[cfg(feature = "local-tun")] if let Some(tun_interface_address) = local.tun_interface_address { match tun_interface_address.parse::() { Ok(addr) => local_config.tun_interface_address = Some(addr), Err(..) => { let err = Error::new(ErrorKind::Malformed, "`tun_interface_address` invalid", None); return Err(err); } } } #[cfg(feature = "local-tun")] if let Some(tun_interface_destination) = local.tun_interface_destination { match tun_interface_destination.parse::() { Ok(addr) => local_config.tun_interface_destination = Some(addr), Err(..) => { let err = Error::new(ErrorKind::Malformed, "`tun_interface_destination` invalid", None); return Err(err); } } } #[cfg(feature = "local-tun")] if let Some(tun_interface_name) = local.tun_interface_name { local_config.tun_interface_name = Some(tun_interface_name); } #[cfg(all(feature = "local-tun", unix))] if let Some(tun_device_fd_from_path) = local.tun_device_fd_from_path { local_config.tun_device_fd_from_path = Some(From::from(tun_device_fd_from_path)); } #[cfg(feature = "local")] if let Some(socks5_auth_config_path) = local.socks5_auth_config_path { local_config.socks5_auth = Socks5AuthConfig::load_from_file(&socks5_auth_config_path)?; } #[cfg(feature = "local-http")] if let Some(http_auth_config_path) = local.http_auth_config_path { local_config.http_auth = HttpAuthConfig::load_from_file(&http_auth_config_path)?; } #[cfg(feature = "local-fake-dns")] { if let Some(d) = local.fake_dns_record_expire_duration { local_config.fake_dns_record_expire_duration = Some(Duration::from_secs(d)); } if let Some(n) = local.fake_dns_ipv4_network { match n.parse::() { Ok(n) => local_config.fake_dns_ipv4_network = Some(n), Err(..) => { let err = Error::new(ErrorKind::Malformed, "invalid `fake_dns_ipv4_network`", None); return Err(err); } } } if let Some(n) = local.fake_dns_ipv6_network { match n.parse::() { Ok(n) => local_config.fake_dns_ipv6_network = Some(n), Err(..) => { let err = Error::new(ErrorKind::Malformed, "invalid `fake_dns_ipv6_network`", None); return Err(err); } } } if let Some(p) = local.fake_dns_database_path { local_config.fake_dns_database_path = Some(p.into()); } } let mut local_instance = LocalInstanceConfig { config: local_config, acl: None, }; if let Some(acl_path) = local.acl { let acl = match AccessControl::load_from_file(&acl_path) { Ok(acl) => acl, Err(err) => { let err = Error::new( ErrorKind::Invalid, "acl loading failed", Some(format!("file {acl_path}, error: {err}")), ); return Err(err); } }; local_instance.acl = Some(acl); } nconfig.local.push(local_instance); } } } ConfigType::Server | ConfigType::Manager => { // NOTE: IGNORED. // servers only uses `local_address` for binding outbound interfaces // // This behavior causes lots of confusion. use outbound_bind_addr instead } #[cfg(feature = "local-online-config")] ConfigType::OnlineConfig => { // SIP008. https://shadowsocks.org/doc/sip008.html // "version" should be set to "1" match config.version { Some(1) => {} Some(v) => { let err = Error::new( ErrorKind::Invalid, "invalid online config version", Some(format!("version: {v}")), ); return Err(err); } None => { warn!( "OnlineConfig \"version\" is missing in the configuration, assuming it is a compatible version for this project" ); } } } } let server_source = match config_type { ConfigType::Local | ConfigType::Server | ConfigType::Manager => ServerSource::Configuration, #[cfg(feature = "local-online-config")] ConfigType::OnlineConfig => ServerSource::OnlineConfig, }; // Standard config // Server match (config.server, config.server_port, config.password, &config.method) { (Some(address), Some(port), pwd_opt, Some(m)) => { let addr = match address.parse::() { Ok(v4) => ServerAddr::SocketAddr(SocketAddr::V4(SocketAddrV4::new(v4, port))), Err(..) => match address.parse::() { Ok(v6) => ServerAddr::SocketAddr(SocketAddr::V6(SocketAddrV6::new(v6, port, 0, 0))), Err(..) => ServerAddr::DomainName(address, port), }, }; let method = match m.parse::() { Ok(m) => m, Err(..) => { let err = Error::new( ErrorKind::Invalid, "unsupported method", Some(format!("`{m}` is not a supported method")), ); return Err(err); } }; // Only "password" support getting from environment variable. let password = match pwd_opt { Some(ref pwd) => read_variable_field_value(pwd), None => { if method.is_none() { String::new().into() } else { let err = Error::new( ErrorKind::MissingField, "`password` is required", Some(format!("`password` is required for method {method}")), ); return Err(err); } } }; let mut nsvr = match ServerConfig::new(addr, password, method) { Ok(svr) => svr, Err(serr) => { let err = Error::new( ErrorKind::Malformed, "server config create failed", Some(format!("{}", serr)), ); return Err(err); } }; nsvr.set_source(server_source); nsvr.set_mode(global_mode); if let Some(ref p) = config.plugin { // SIP008 allows "plugin" to be an empty string // Empty string implies "no plugin" if !p.is_empty() { let plugin = PluginConfig { plugin: p.clone(), plugin_opts: config.plugin_opts.clone(), plugin_args: config.plugin_args.clone().unwrap_or_default(), plugin_mode: match config.plugin_mode { None => Mode::TcpOnly, Some(ref mode) => match mode.parse::() { Ok(m) => m, Err(..) => { let e = Error::new( ErrorKind::Malformed, "malformed `plugin_mode`, must be one of `tcp_only`, `udp_only` and `tcp_and_udp`", None, ); return Err(e); } }, }, }; nsvr.set_plugin(plugin); } } if let Some(timeout) = config.timeout.map(Duration::from_secs) { nsvr.set_timeout(timeout); } nconfig.server.push(ServerInstanceConfig::with_server_config(nsvr)); } (None, None, None, Some(_)) if config_type.is_manager() => { // Set the default method for manager } (None, None, None, None) => (), _ => { let err = Error::new( ErrorKind::Malformed, "`server`, `server_port`, `method`, `password` must be provided together", None, ); return Err(err); } } // Ext servers if let Some(servers) = config.servers { for svr in servers { // Skip if server is disabled if svr.disabled.unwrap_or(false) { continue; } let address = svr.server; let port = svr.server_port; let addr = match address.parse::() { Ok(v4) => ServerAddr::SocketAddr(SocketAddr::V4(SocketAddrV4::new(v4, port))), Err(..) => match address.parse::() { Ok(v6) => ServerAddr::SocketAddr(SocketAddr::V6(SocketAddrV6::new(v6, port, 0, 0))), Err(..) => ServerAddr::DomainName(address, port), }, }; let method = match svr.method.parse::() { Ok(m) => m, Err(..) => { let err = Error::new( ErrorKind::Invalid, "unsupported method", Some(format!("`{}` is not a supported method", svr.method)), ); return Err(err); } }; // Only "password" support getting from environment variable. let password = match svr.password { Some(ref pwd) => read_variable_field_value(pwd), None => { if method.is_none() { String::new().into() } else { let err = Error::new( ErrorKind::MissingField, "`password` is required", Some(format!("`password` is required for method {method}")), ); return Err(err); } } }; let mut nsvr = match ServerConfig::new(addr, password, method) { Ok(svr) => svr, Err(serr) => { let err = Error::new( ErrorKind::Malformed, "server config create failed", Some(format!("{}", serr)), ); return Err(err); } }; nsvr.set_source(server_source); // Extensible Identity Header, Users if let Some(users) = svr.users { let mut user_manager = ServerUserManager::new(); for user in users { let user = match ServerUser::with_encoded_key(user.name, &user.password) { Ok(u) => u, Err(..) => { let err = Error::new( ErrorKind::Malformed, "`users[].password` should be base64 encoded", None, ); return Err(err); } }; user_manager.add_user(user); } nsvr.set_user_manager(user_manager); } match svr.mode { Some(mode) => match mode.parse::() { Ok(mode) => nsvr.set_mode(mode), Err(..) => { let err = Error::new(ErrorKind::Invalid, "invalid `mode`", None); return Err(err); } }, None => { // Server will derive mode from the global scope if matches!(config_type, ConfigType::Server | ConfigType::Manager) { nsvr.set_mode(global_mode); } } } if let Some(p) = svr.plugin { // SIP008 allows "plugin" to be an empty string // Empty string implies "no plugin" if !p.is_empty() { let plugin = PluginConfig { plugin: p, plugin_opts: svr.plugin_opts, plugin_args: svr.plugin_args.unwrap_or_default(), plugin_mode: match svr.plugin_mode { None => Mode::TcpOnly, Some(ref mode) => match mode.parse::() { Ok(m) => m, Err(..) => { let e = Error::new( ErrorKind::Malformed, "malformed `plugin_mode`, must be one of `tcp_only`, `udp_only` and `tcp_and_udp`", None, ); return Err(e); } }, }, }; nsvr.set_plugin(plugin); } } if let Some(timeout) = config.timeout.map(Duration::from_secs) { nsvr.set_timeout(timeout); } if let Some(remarks) = svr.remarks { nsvr.set_remarks(remarks); } if let Some(id) = svr.id { nsvr.set_id(id); } if svr.tcp_weight.is_some() || svr.udp_weight.is_some() { let tcp_weight = svr.tcp_weight.unwrap_or(1.0); if !(0.0..=1.0).contains(&tcp_weight) { let err = Error::new(ErrorKind::Invalid, "invalid `tcp_weight`, must be in [0, 1]", None); return Err(err); } let udp_weight = svr.udp_weight.unwrap_or(1.0); if !(0.0..=1.0).contains(&udp_weight) { let err = Error::new(ErrorKind::Invalid, "invalid `udp_weight`, must be in [0, 1]", None); return Err(err); } let mut weight = ServerWeight::new(); weight.set_tcp_weight(tcp_weight); weight.set_udp_weight(udp_weight); nsvr.set_weight(weight); } let mut server_instance = ServerInstanceConfig::with_server_config(nsvr); if let Some(acl_path) = svr.acl { let acl = match AccessControl::load_from_file(&acl_path) { Ok(acl) => acl, Err(err) => { let err = Error::new( ErrorKind::Invalid, "acl loading failed", Some(format!("file {acl_path}, error: {err}")), ); return Err(err); } }; server_instance.acl = Some(acl); } #[cfg(any(target_os = "linux", target_os = "android"))] if let Some(outbound_fwmark) = svr.outbound_fwmark { server_instance.outbound_fwmark = Some(outbound_fwmark); } #[cfg(target_os = "freebsd")] if let Some(outbound_user_cookie) = svr.outbound_user_cookie { server_instance.outbound_user_cookie = Some(outbound_user_cookie); } if let Some(outbound_bind_addr) = svr.outbound_bind_addr { server_instance.outbound_bind_addr = Some(outbound_bind_addr); } if let Some(ref outbound_bind_interface) = svr.outbound_bind_interface { server_instance.outbound_bind_interface = Some(outbound_bind_interface.clone()); } if let Some(outbound_udp_allow_fragmentation) = svr.outbound_udp_allow_fragmentation { server_instance.outbound_udp_allow_fragmentation = Some(outbound_udp_allow_fragmentation); } nconfig.server.push(server_instance); } } // Set timeout globally if let Some(timeout) = config.timeout { let timeout = Duration::from_secs(timeout); // Set as a default timeout for inst in &mut nconfig.server { let svr = &mut inst.config; if svr.timeout().is_none() { svr.set_timeout(timeout); } } } // Manager Address if let Some(ma) = config.manager_address { let manager = match config.manager_port { Some(port) => { match ma.parse::() { Ok(ip) => ManagerAddr::from(SocketAddr::new(ip, port)), Err(..) => { // treated as domain ManagerAddr::from((ma, port)) } } } #[cfg(unix)] None => ManagerAddr::from(PathBuf::from(ma)), #[cfg(not(unix))] None => { let e = Error::new(ErrorKind::MissingField, "missing `manager_port`", None); return Err(e); } }; let mut manager_config = ManagerConfig::new(manager); manager_config.mode = global_mode; if let Some(ref m) = config.method { match m.parse::() { Ok(method) => manager_config.method = Some(method), Err(..) => { let err = Error::new( ErrorKind::Invalid, "unsupported method", Some(format!("`{m}` is not a supported method")), ); return Err(err); } } } if let Some(p) = config.plugin { // SIP008 allows "plugin" to be an empty string // Empty string implies "no plugin" if !p.is_empty() { manager_config.plugin = Some(PluginConfig { plugin: p, plugin_opts: config.plugin_opts, plugin_args: config.plugin_args.unwrap_or_default(), plugin_mode: match config.plugin_mode { None => Mode::TcpOnly, Some(ref mode) => match mode.parse::() { Ok(m) => m, Err(..) => { let e = Error::new( ErrorKind::Malformed, "malformed `plugin_mode`, must be one of `tcp_only`, `udp_only` and `tcp_and_udp`", None, ); return Err(e); } }, }, }); } } nconfig.manager = Some(manager_config); } // DNS { match config.dns { Some(SSDnsConfig::Simple(ds)) => nconfig.set_dns_formatted(&ds)?, #[cfg(feature = "hickory-dns")] Some(SSDnsConfig::HickoryDns(c)) => nconfig.dns = DnsConfig::HickoryDns(c), None => nconfig.dns = DnsConfig::System, } nconfig.dns_cache_size = config.dns_cache_size; } // TCP nodelay if let Some(b) = config.no_delay { nconfig.no_delay = b; } // TCP fast open if let Some(b) = config.fast_open { nconfig.fast_open = b; } // TCP Keep-Alive if let Some(d) = config.keep_alive { nconfig.keep_alive = Some(Duration::from_secs(d)); } // Multipath-TCP if let Some(b) = config.mptcp { nconfig.mptcp = b; } // UDP nconfig.udp_timeout = config.udp_timeout.map(Duration::from_secs); // Maximum associations to be kept simultaneously nconfig.udp_max_associations = config.udp_max_associations; // MTU for UDP nconfig.udp_mtu = config.udp_mtu; // RLIMIT_NOFILE #[cfg(all(unix, not(target_os = "android")))] { nconfig.nofile = config.nofile; } // Uses IPv6 first if let Some(f) = config.ipv6_first { nconfig.ipv6_first = f; } // IPV6_V6ONLY if let Some(o) = config.ipv6_only { nconfig.ipv6_only = o; } // SO_MARK #[cfg(any(target_os = "linux", target_os = "android"))] if let Some(fwmark) = config.outbound_fwmark { nconfig.outbound_fwmark = Some(fwmark); } // SO_USER_COOKIE #[cfg(target_os = "freebsd")] if let Some(user_cookie) = config.outbound_user_cookie { nconfig.outbound_user_cookie = Some(user_cookie); } // Outbound bind() address if let Some(bind_addr) = config.outbound_bind_addr { match bind_addr.parse::() { Ok(b) => nconfig.outbound_bind_addr = Some(b), Err(..) => { let err = Error::new(ErrorKind::Invalid, "invalid outbound_bind_addr", None); return Err(err); } } } // Bind device / interface nconfig.outbound_bind_interface = config.outbound_bind_interface; if let Some(b) = config.outbound_udp_allow_fragmentation { nconfig.outbound_udp_allow_fragmentation = b; } // Security if let Some(sec) = config.security && let Some(replay_attack) = sec.replay_attack && let Some(policy) = replay_attack.policy { match policy.parse::() { Ok(p) => nconfig.security.replay_attack.policy = p, Err(..) => { let err = Error::new(ErrorKind::Invalid, "invalid replay attack policy", None); return Err(err); } } } if let Some(balancer) = config.balancer { nconfig.balancer = BalancerConfig { max_server_rtt: balancer.max_server_rtt.map(Duration::from_secs), check_interval: balancer.check_interval.map(Duration::from_secs), check_best_interval: balancer.check_best_interval.map(Duration::from_secs), }; } if let Some(acl_path) = config.acl { let acl = match AccessControl::load_from_file(&acl_path) { Ok(acl) => acl, Err(err) => { let err = Error::new( ErrorKind::Invalid, "acl loading failed", Some(format!("file {acl_path}, error: {err}")), ); return Err(err); } }; nconfig.acl = Some(acl); } #[cfg(feature = "local-online-config")] if let Some(online_config) = config.online_config { nconfig.online_config = Some(OnlineConfig { config_url: online_config.config_url, update_interval: online_config.update_interval.map(Duration::from_secs), allowed_plugins: online_config.allowed_plugins, }); } Ok(nconfig) } /// Set DNS configuration in string format /// /// 1. `[(unix|tcp|udp)://]host[:port][,host[:port]]...` /// 2. Pre-defined. Like `google`, `cloudflare` pub fn set_dns_formatted(&mut self, dns: &str) -> Result<(), Error> { self.dns = match dns { "system" => DnsConfig::System, #[cfg(feature = "hickory-dns")] "google" => DnsConfig::HickoryDns(ResolverConfig::google()), #[cfg(all(feature = "hickory-dns", feature = "dns-over-tls"))] "google_tls" => DnsConfig::HickoryDns(ResolverConfig::google_tls()), #[cfg(all(feature = "hickory-dns", feature = "dns-over-https"))] "google_https" => DnsConfig::HickoryDns(ResolverConfig::google_https()), #[cfg(all(feature = "hickory-dns", feature = "dns-over-h3"))] "google_h3" => DnsConfig::HickoryDns(ResolverConfig::google_h3()), #[cfg(feature = "hickory-dns")] "cloudflare" => DnsConfig::HickoryDns(ResolverConfig::cloudflare()), #[cfg(all(feature = "hickory-dns", feature = "dns-over-tls"))] "cloudflare_tls" => DnsConfig::HickoryDns(ResolverConfig::cloudflare_tls()), #[cfg(all(feature = "hickory-dns", feature = "dns-over-https"))] "cloudflare_https" => DnsConfig::HickoryDns(ResolverConfig::cloudflare_https()), #[cfg(feature = "hickory-dns")] "quad9" => DnsConfig::HickoryDns(ResolverConfig::quad9()), #[cfg(all(feature = "hickory-dns", feature = "dns-over-tls"))] "quad9_tls" => DnsConfig::HickoryDns(ResolverConfig::quad9_tls()), #[cfg(all(feature = "hickory-dns", feature = "dns-over-https"))] "quad9_https" => DnsConfig::HickoryDns(ResolverConfig::quad9_https()), nameservers => self.parse_dns_nameservers(nameservers)?, }; Ok(()) } #[cfg(any(feature = "hickory-dns", feature = "local-dns"))] fn parse_dns_nameservers(&mut self, nameservers: &str) -> Result { use hickory_resolver::proto::xfer::Protocol; #[cfg(all(unix, feature = "local-dns"))] if let Some(nameservers) = nameservers.strip_prefix("unix://") { // A special DNS server only for shadowsocks-android // It serves like a TCP DNS server but using unix domain sockets return Ok(DnsConfig::LocalDns(NameServerAddr::UnixSocketAddr(PathBuf::from( nameservers, )))); } enum DnsProtocol { Tcp, Udp, Both, } impl DnsProtocol { fn enable_tcp(&self) -> bool { matches!(*self, Self::Tcp | Self::Both) } fn enable_udp(&self) -> bool { matches!(*self, Self::Udp | Self::Both) } } let mut protocol = DnsProtocol::Both; let mut nameservers = nameservers; if nameservers.starts_with("tcp://") { protocol = DnsProtocol::Tcp; nameservers = &nameservers[6..]; } else if nameservers.starts_with("udp://") { protocol = DnsProtocol::Udp; nameservers = &nameservers[6..]; } // If enables Trust-DNS, then it supports multiple nameservers // // Set ips directly // Similar to shadowsocks-libev's `ares_set_servers_ports_csv` // // ``` // host[:port][,host[:port]]... // ``` // // For example: // `192.168.1.100,192.168.1.101,3.4.5.6` let mut c = ResolverConfig::new(); for part in nameservers.split(',') { let socket_addr = if let Ok(socket_addr) = part.parse::() { socket_addr } else if let Ok(ipaddr) = part.parse::() { SocketAddr::new(ipaddr, 53) } else { let e = Error::new( ErrorKind::Invalid, "invalid `dns` value, can only be [(tcp|udp)://]host[:port][,host[:port]]..., or unix:///path/to/dns, or predefined keys like \"google\", \"cloudflare\"", None, ); return Err(e); }; if protocol.enable_udp() { let ns_config = NameServerConfig::new(socket_addr, Protocol::Udp); c.add_name_server(ns_config); } if protocol.enable_tcp() { let ns_config = NameServerConfig::new(socket_addr, Protocol::Tcp); c.add_name_server(ns_config); } } Ok(if c.name_servers().is_empty() { DnsConfig::System } else { DnsConfig::HickoryDns(c) }) } #[cfg(not(any(feature = "hickory-dns", feature = "local-dns")))] fn parse_dns_nameservers(&mut self, _nameservers: &str) -> Result { Ok(DnsConfig::System) } /// Load Config from a `str` pub fn load_from_str(s: &str, config_type: ConfigType) -> Result { let c = json5::from_str::(s)?; Self::load_from_ssconfig(c, config_type) } /// Load Config from a JSON `str` pub fn load_from_json_str(s: &str, config_type: ConfigType) -> Result { let c = serde_json::from_str::(s)?; Self::load_from_ssconfig(c, config_type) } /// Load Config from a File pub fn load_from_file>(filename: P, config_type: ConfigType) -> Result { let filename = filename.as_ref(); let mut reader = OpenOptions::new().read(true).open(filename)?; let mut content = String::new(); reader.read_to_string(&mut content)?; let mut config = Self::load_from_str(&content[..], config_type)?; // Record the path of the configuration for auto-reloading config.config_path = Some(filename.to_owned()); Ok(config) } /// Check if there are any plugin are enabled with servers pub fn has_server_plugins(&self) -> bool { for inst in &self.server { let server = &inst.config; if server.plugin().is_some() { return true; } } false } /// Check if all required fields are already set pub fn check_integrity(&self) -> Result<(), Error> { if self.config_type.is_local() { if self.local.is_empty() { let err = Error::new( ErrorKind::MissingField, "missing `locals` for client configuration", None, ); return Err(err); } for local_config in &self.local { local_config.config.check_integrity()?; } // Balancer related checks if let Some(rtt) = self.balancer.max_server_rtt && rtt.as_secs() == 0 { let err = Error::new(ErrorKind::Invalid, "balancer.max_server_rtt must be > 0", None); return Err(err); } if let Some(intv) = self.balancer.check_interval && intv.as_secs() == 0 { let err = Error::new(ErrorKind::Invalid, "balancer.check_interval must be > 0", None); return Err(err); } } if self.config_type.is_server() && self.server.is_empty() { let err = Error::new( ErrorKind::MissingField, "missing any valid servers in configuration", None, ); return Err(err); } #[cfg(feature = "local-online-config")] if self.config_type.is_online_config() && self.server.is_empty() { let err = Error::new( ErrorKind::MissingField, "missing any valid servers in configuration", None, ); return Err(err); } if self.config_type.is_manager() && self.manager.is_none() { let err = Error::new( ErrorKind::MissingField, "missing `manager_addr` and `manager_port` in configuration", None, ); return Err(err); } for inst in &self.server { let server = &inst.config; // Plugin shouldn't be an empty string if let Some(plugin) = server.plugin() && plugin.plugin.trim().is_empty() { let err = Error::new(ErrorKind::Malformed, "`plugin` shouldn't be an empty string", None); return Err(err); } // Server's domain name shouldn't be an empty string match server.addr() { ServerAddr::SocketAddr(sa) => { if sa.port() == 0 { let err = Error::new(ErrorKind::Malformed, "`server_port` shouldn't be 0", None); return Err(err); } if self.config_type.is_local() { // Only server could bind to INADDR_ANY let ip = sa.ip(); if ip.is_unspecified() { let err = Error::new( ErrorKind::Malformed, "`server` shouldn't be an unspecified address (INADDR_ANY)", None, ); return Err(err); } } #[cfg(feature = "local-online-config")] if self.config_type.is_online_config() { // Only server could bind to INADDR_ANY let ip = sa.ip(); if ip.is_unspecified() { let err = Error::new( ErrorKind::Malformed, "`server` shouldn't be an unspecified address (INADDR_ANY)", None, ); return Err(err); } } } ServerAddr::DomainName(dn, port) => { if dn.is_empty() || *port == 0 { let err = Error::new( ErrorKind::Malformed, "`server` shouldn't be an empty string, `server_port` shouldn't be 0", None, ); return Err(err); } } } // Users' key must match key length if let Some(user_manager) = server.user_manager() { #[cfg(feature = "aead-cipher-2022")] if server.method().is_aead_2022() { use shadowsocks::config::method_support_eih; if user_manager.user_count() > 0 && !method_support_eih(server.method()) { let err = Error::new( ErrorKind::Invalid, "server method doesn't support Extended Identity Header (EIH), remove `users`", Some(format!("method {}", server.method())), ); return Err(err); } } let key_len = server.method().key_len(); for user in user_manager.users_iter() { if user.key().len() != key_len { let err = Error::new( ErrorKind::Malformed, "`users[].password` length must be exactly the same as method's key length", None, ); return Err(err); } } } } Ok(()) } } impl fmt::Display for Config { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { // Convert to json let mut jconf = SSConfig::default(); // Locals if !self.local.is_empty() { if self.local.len() == 1 && self.local[0].config.is_basic() { let local_instance = &self.local[0]; let local = &local_instance.config; if let Some(ref a) = local.addr { jconf.local_address = Some(match a { ServerAddr::SocketAddr(sa) => sa.ip().to_string(), ServerAddr::DomainName(dm, ..) => dm.to_string(), }); jconf.local_port = Some(match a { ServerAddr::SocketAddr(sa) => sa.port(), ServerAddr::DomainName(.., port) => *port, }); } #[cfg(target_os = "macos")] { jconf.launchd_tcp_socket_name.clone_from(&local.launchd_tcp_socket_name); jconf.launchd_udp_socket_name.clone_from(&local.launchd_udp_socket_name); } if local.protocol != ProtocolType::Socks { jconf.protocol = Some(local.protocol.as_str().to_owned()); } // ACL if let Some(ref acl) = local_instance.acl { jconf.acl = Some(acl.file_path().to_str().unwrap().to_owned()); } } else { let mut jlocals = Vec::with_capacity(self.local.len()); for local_instance in &self.local { let local = &local_instance.config; let jlocal = SSLocalExtConfig { local_address: local.addr.as_ref().map(|a| match a { ServerAddr::SocketAddr(sa) => sa.ip().to_string(), ServerAddr::DomainName(dm, ..) => dm.to_string(), }), local_port: local.addr.as_ref().map(|a| match a { ServerAddr::SocketAddr(sa) => sa.port(), ServerAddr::DomainName(.., port) => *port, }), disabled: None, local_udp_address: local.udp_addr.as_ref().map(|udp_addr| match udp_addr { ServerAddr::SocketAddr(sa) => sa.ip().to_string(), ServerAddr::DomainName(dm, ..) => dm.to_string(), }), local_udp_port: local.udp_addr.as_ref().map(|udp_addr| match udp_addr { ServerAddr::SocketAddr(sa) => sa.port(), ServerAddr::DomainName(.., port) => *port, }), mode: Some(local.mode.to_string()), protocol: match local.protocol { ProtocolType::Socks => None, #[allow(unreachable_patterns)] p => Some(p.as_str().to_owned()), }, #[cfg(target_os = "macos")] launchd_tcp_socket_name: local.launchd_tcp_socket_name.clone(), #[cfg(target_os = "macos")] launchd_udp_socket_name: local.launchd_udp_socket_name.clone(), #[cfg(feature = "local-redir")] tcp_redir: if local.tcp_redir != RedirType::tcp_default() { Some(local.tcp_redir.to_string()) } else { None }, #[cfg(feature = "local-redir")] udp_redir: if local.udp_redir != RedirType::udp_default() { Some(local.udp_redir.to_string()) } else { None }, #[cfg(feature = "local-tunnel")] forward_address: match local.forward_addr { None => None, Some(ref forward_addr) => match forward_addr { Address::SocketAddress(sa) => Some(sa.ip().to_string()), Address::DomainNameAddress(dm, ..) => Some(dm.to_string()), }, }, #[cfg(feature = "local-tunnel")] forward_port: match local.forward_addr { None => None, Some(ref forward_addr) => match forward_addr { Address::SocketAddress(sa) => Some(sa.port()), Address::DomainNameAddress(.., port) => Some(*port), }, }, #[cfg(feature = "local-dns")] local_dns_address: match local.local_dns_addr { None => None, Some(ref local_dns_addr) => match local_dns_addr { NameServerAddr::SocketAddr(sa) => Some(sa.ip().to_string()), #[cfg(unix)] NameServerAddr::UnixSocketAddr(path) => { Some(path.to_str().expect("path is not utf-8").to_owned()) } }, }, #[cfg(feature = "local-dns")] local_dns_port: match local.local_dns_addr { None => None, Some(ref local_dns_addr) => match local_dns_addr { NameServerAddr::SocketAddr(sa) => Some(sa.port()), #[cfg(unix)] NameServerAddr::UnixSocketAddr(..) => None, }, }, #[cfg(feature = "local-dns")] remote_dns_address: match local.remote_dns_addr { None => None, Some(ref remote_dns_addr) => match remote_dns_addr { Address::SocketAddress(sa) => Some(sa.ip().to_string()), Address::DomainNameAddress(dm, ..) => Some(dm.to_string()), }, }, #[cfg(feature = "local-dns")] remote_dns_port: match local.remote_dns_addr { None => None, Some(ref remote_dns_addr) => match remote_dns_addr { Address::SocketAddress(sa) => Some(sa.port()), Address::DomainNameAddress(.., port) => Some(*port), }, }, #[cfg(feature = "local-dns")] client_cache_size: local.client_cache_size, #[cfg(feature = "local-tun")] tun_interface_name: local.tun_interface_name.clone(), #[cfg(feature = "local-tun")] tun_interface_address: local.tun_interface_address.as_ref().map(ToString::to_string), #[cfg(feature = "local-tun")] tun_interface_destination: local.tun_interface_destination.as_ref().map(ToString::to_string), #[cfg(all(feature = "local-tun", unix))] tun_device_fd_from_path: local .tun_device_fd_from_path .as_ref() .map(|p| p.to_str().expect("tun_device_fd_from_path is not utf-8").to_owned()), #[cfg(feature = "local")] socks5_auth_config_path: None, #[cfg(feature = "local-http")] http_auth_config_path: None, #[cfg(feature = "local-fake-dns")] fake_dns_record_expire_duration: local.fake_dns_record_expire_duration.map(|d| d.as_secs()), #[cfg(feature = "local-fake-dns")] fake_dns_ipv4_network: local.fake_dns_ipv4_network.map(|n| n.to_string()), #[cfg(feature = "local-fake-dns")] fake_dns_ipv6_network: local.fake_dns_ipv6_network.map(|n| n.to_string()), #[cfg(feature = "local-fake-dns")] fake_dns_database_path: local .fake_dns_database_path .as_ref() .and_then(|n| n.to_str().map(ToOwned::to_owned)), acl: local_instance .acl .as_ref() .and_then(|a| a.file_path().to_str().map(ToOwned::to_owned)), }; jlocals.push(jlocal); } jconf.locals = Some(jlocals); } } // Servers match self.server.len() { 0 => {} // For 1 server, uses standard configure format 1 if self.server[0].config.is_basic() => { let inst = &self.server[0]; let svr = &inst.config; jconf.server = Some(match *svr.addr() { ServerAddr::SocketAddr(ref sa) => sa.ip().to_string(), ServerAddr::DomainName(ref dm, ..) => dm.to_string(), }); jconf.server_port = Some(match *svr.addr() { ServerAddr::SocketAddr(ref sa) => sa.port(), ServerAddr::DomainName(.., port) => port, }); jconf.method = Some(svr.method().to_string()); jconf.password = if svr.method().is_none() { None } else { Some(svr.password().to_string()) }; jconf.plugin = svr.plugin().map(|p| p.plugin.to_string()); jconf.plugin_opts = svr.plugin().and_then(|p| p.plugin_opts.clone()); jconf.plugin_args = svr.plugin().and_then(|p| { if p.plugin_args.is_empty() { None } else { Some(p.plugin_args.clone()) } }); jconf.plugin_mode = match svr.plugin() { None => None, Some(p) => match p.plugin_mode { Mode::TcpOnly => None, _ => Some(p.plugin_mode.to_string()), }, }; jconf.timeout = svr.timeout().map(|t| t.as_secs()); jconf.mode = Some(svr.mode().to_string()); if let Some(ref acl) = inst.acl { jconf.acl = Some(acl.file_path().to_str().unwrap().to_owned()); } } // For >1 servers, uses extended multiple server format _ => { let mut vsvr = Vec::new(); for inst in &self.server { let svr = &inst.config; vsvr.push(SSServerExtConfig { server: match *svr.addr() { ServerAddr::SocketAddr(ref sa) => sa.ip().to_string(), ServerAddr::DomainName(ref dm, ..) => dm.to_string(), }, server_port: match *svr.addr() { ServerAddr::SocketAddr(ref sa) => sa.port(), ServerAddr::DomainName(.., port) => port, }, password: if svr.method().is_none() { None } else { Some(svr.password().to_string()) }, method: svr.method().to_string(), users: svr.user_manager().map(|m| { let mut vu = Vec::new(); for u in m.users_iter() { vu.push(SSServerUserConfig { name: u.name().to_owned(), password: u.encoded_key(), }); } vu }), disabled: None, plugin: svr.plugin().map(|p| p.plugin.to_string()), plugin_opts: svr.plugin().and_then(|p| p.plugin_opts.clone()), plugin_args: svr.plugin().and_then(|p| { if p.plugin_args.is_empty() { None } else { Some(p.plugin_args.clone()) } }), plugin_mode: match svr.plugin() { None => None, Some(p) => match p.plugin_mode { Mode::TcpOnly => None, _ => Some(p.plugin_mode.to_string()), }, }, timeout: svr.timeout().map(|t| t.as_secs()), remarks: svr.remarks().map(ToOwned::to_owned), id: svr.id().map(ToOwned::to_owned), mode: Some(svr.mode().to_string()), tcp_weight: if (svr.weight().tcp_weight() - 1.0).abs() > f32::EPSILON { Some(svr.weight().tcp_weight()) } else { None }, udp_weight: if (svr.weight().udp_weight() - 1.0).abs() > f32::EPSILON { Some(svr.weight().udp_weight()) } else { None }, acl: inst .acl .as_ref() .and_then(|a| a.file_path().to_str().map(ToOwned::to_owned)), #[cfg(any(target_os = "linux", target_os = "android"))] outbound_fwmark: inst.outbound_fwmark, #[cfg(target_os = "freebsd")] outbound_user_cookie: inst.outbound_user_cookie, outbound_bind_addr: inst.outbound_bind_addr, outbound_bind_interface: inst.outbound_bind_interface.clone(), outbound_udp_allow_fragmentation: inst.outbound_udp_allow_fragmentation, }); } jconf.servers = Some(vsvr); } } if let Some(ref m) = self.manager { jconf.manager_address = Some(match m.addr { ManagerAddr::SocketAddr(ref saddr) => saddr.ip().to_string(), ManagerAddr::DomainName(ref dname, ..) => dname.clone(), #[cfg(unix)] ManagerAddr::UnixSocketAddr(ref path) => path.display().to_string(), }); jconf.manager_port = match m.addr { ManagerAddr::SocketAddr(ref saddr) => Some(saddr.port()), ManagerAddr::DomainName(.., port) => Some(port), #[cfg(unix)] ManagerAddr::UnixSocketAddr(..) => None, }; if jconf.mode.is_none() { jconf.mode = Some(m.mode.to_string()); } if jconf.method.is_none() && let Some(ref m) = m.method { jconf.method = Some(m.to_string()); } if jconf.plugin.is_none() && let Some(ref p) = m.plugin { jconf.plugin = Some(p.plugin.clone()); if let Some(ref o) = p.plugin_opts { jconf.plugin_opts = Some(o.clone()); } if !p.plugin_args.is_empty() { jconf.plugin_args = Some(p.plugin_args.clone()); } } } if self.no_delay { jconf.no_delay = Some(self.no_delay); } if self.fast_open { jconf.fast_open = Some(self.fast_open); } if let Some(keepalive) = self.keep_alive { jconf.keep_alive = Some(keepalive.as_secs()); } if self.mptcp { jconf.mptcp = Some(self.mptcp); } match self.dns { DnsConfig::System => {} #[cfg(feature = "hickory-dns")] DnsConfig::HickoryDns(ref dns) => { jconf.dns = Some(SSDnsConfig::HickoryDns(dns.clone())); } #[cfg(feature = "local-dns")] DnsConfig::LocalDns(ref ns) => { jconf.dns = Some(SSDnsConfig::Simple(ns.to_string())); } } jconf.udp_timeout = self.udp_timeout.map(|t| t.as_secs()); jconf.udp_max_associations = self.udp_max_associations; jconf.udp_mtu = self.udp_mtu; #[cfg(all(unix, not(target_os = "android")))] { jconf.nofile = self.nofile; } if self.ipv6_first { jconf.ipv6_first = Some(self.ipv6_first); } if self.ipv6_only { jconf.ipv6_only = Some(self.ipv6_only); } #[cfg(any(target_os = "linux", target_os = "android"))] { jconf.outbound_fwmark = self.outbound_fwmark; } #[cfg(target_os = "freebsd")] { jconf.outbound_user_cookie = self.outbound_user_cookie; } jconf.outbound_bind_addr = self.outbound_bind_addr.map(|i| i.to_string()); jconf.outbound_bind_interface.clone_from(&self.outbound_bind_interface); jconf.outbound_udp_allow_fragmentation = Some(self.outbound_udp_allow_fragmentation); // Security if self.security.replay_attack.policy != ReplayAttackPolicy::default() { jconf.security = Some(SSSecurityConfig { replay_attack: Some(SSSecurityReplayAttackConfig { policy: Some(self.security.replay_attack.policy.to_string()), }), }); } // Balancer if self.balancer.max_server_rtt.is_some() || self.balancer.check_interval.is_some() { jconf.balancer = Some(SSBalancerConfig { max_server_rtt: self.balancer.max_server_rtt.as_ref().map(Duration::as_secs), check_interval: self.balancer.check_interval.as_ref().map(Duration::as_secs), check_best_interval: self.balancer.check_best_interval.as_ref().map(Duration::as_secs), }); } // ACL if let Some(ref acl) = self.acl { jconf.acl = Some(acl.file_path().to_str().unwrap().to_owned()); } // OnlineConfig #[cfg(feature = "local-online-config")] if let Some(ref online_config) = self.online_config { jconf.online_config = Some(SSOnlineConfig { config_url: online_config.config_url.clone(), update_interval: online_config.update_interval.as_ref().map(Duration::as_secs), allowed_plugins: online_config.allowed_plugins.clone(), }); } write!(f, "{}", json5::to_string(&jconf).unwrap()) } } /// Parse variable value if it is an environment variable /// /// If value is in format `${VAR_NAME}` then it will try to read from `VAR_NAME` environment variable. /// It will return the original value if fails to read `${VAR_NAME}`. pub fn read_variable_field_value(value: &str) -> Cow<'_, str> { if let Some(left_over) = value.strip_prefix("${") && let Some(var_name) = left_over.strip_suffix('}') { match env::var(var_name) { Ok(value) => return value.into(), Err(err) => { warn!( "couldn't read password from environment variable {}, error: {}", var_name, err ); } } } value.into() } ================================================ FILE: crates/shadowsocks-service/src/dns/mod.rs ================================================ //! DNS resolvers #[cfg(feature = "hickory-dns")] use hickory_resolver::config::ResolverOpts; use log::trace; use shadowsocks::{dns_resolver::DnsResolver, net::ConnectOpts}; use crate::config::DnsConfig; #[allow(unused_variables, dead_code)] pub async fn build_dns_resolver( dns: DnsConfig, ipv6_first: bool, dns_cache_size: Option, connect_opts: &ConnectOpts, ) -> Option { match dns { DnsConfig::System => { #[cfg(feature = "hickory-dns")] if crate::hint_support_default_system_resolver() { use log::warn; use std::env; let force_system_builtin = match env::var("SS_SYSTEM_DNS_RESOLVER_FORCE_BUILTIN") { Ok(mut v) => { v.make_ascii_lowercase(); v == "1" || v == "true" } Err(..) => false, }; if !force_system_builtin { let mut opts_opt = None; if let Some(dns_cache_size) = dns_cache_size { let mut opts = ResolverOpts::default(); opts.cache_size = dns_cache_size; opts_opt = Some(opts); } return match DnsResolver::hickory_dns_system_resolver(opts_opt, connect_opts.clone()).await { Ok(r) => Some(r), Err(err) => { warn!( "initialize hickory-dns DNS system resolver failed, fallback to default system resolver, error: {}", err ); None } }; } } trace!("initialized DNS system resolver builtin"); None } #[cfg(feature = "hickory-dns")] DnsConfig::HickoryDns(dns) => { let mut opts_opt = None; if let Some(dns_cache_size) = dns_cache_size { let mut opts = ResolverOpts::default(); opts.cache_size = dns_cache_size; opts_opt = Some(opts); } match DnsResolver::hickory_resolver(dns, opts_opt, connect_opts.clone()).await { Ok(r) => Some(r), Err(err) => { use log::warn; warn!( "initialize hickory-dns DNS resolver failed, fallback to default system resolver, error: {}", err ); None } } } #[cfg(feature = "local-dns")] DnsConfig::LocalDns(ns) => { use crate::local::dns::dns_resolver::DnsResolver as LocalDnsResolver; use shadowsocks::config::Mode; trace!("initializing direct DNS resolver for {}", ns); let mut resolver = LocalDnsResolver::new(ns); resolver.set_mode(Mode::TcpAndUdp); resolver.set_ipv6_first(ipv6_first); resolver.set_connect_opts(connect_opts.clone()); Some(DnsResolver::custom_resolver(resolver)) } } } ================================================ FILE: crates/shadowsocks-service/src/lib.rs ================================================ //! Shadowsocks Service //! //! //! //! shadowsocks is a fast tunnel proxy that helps you bypass firewalls. //! //! ## Usage //! //! Build shadowsocks and you will get at least 2 binaries: `sslocal` and `ssserver` //! //! Write your servers in a configuration file. Format is defined in //! [shadowsocks' documentation](https://github.com/shadowsocks/shadowsocks/wiki) //! //! For example: //! //! ```json //! { //! "server": "my_server_ip", //! "server_port": 8388, //! "local_address": "127.0.0.1", //! "local_port": 1080, //! "password": "mypassword", //! "timeout": 300, //! "method": "aes-256-cfb" //! } //! ``` //! //! Save it in file `shadowsocks.json` and run local proxy server with //! //! ```bash //! cargo run --bin sslocal -- -c shadowsocks.json //! ``` //! //! Now you can use SOCKS5 protocol to proxy your requests, for example: //! //! ```bash //! curl --socks5-hostname 127.0.0.1:1080 https://www.google.com //! ``` //! //! On the server side, you can run the server with //! //! ```bash //! cargo run --bin ssserver -- -c shadowsocks.json //! ``` //! //! Server should use the same configuration file as local, except the listen addresses for servers must be socket //! addresses. //! //! Of course, you can also use `cargo install` to install binaries. use std::time::Duration; #[cfg(feature = "local")] pub use self::local::run as run_local; #[cfg(feature = "manager")] pub use self::manager::run as run_manager; #[cfg(feature = "server")] pub use self::server::run as run_server; pub use shadowsocks; pub mod acl; pub mod config; mod dns; #[cfg(feature = "local")] pub mod local; #[cfg(feature = "manager")] pub mod manager; pub mod net; #[cfg(feature = "server")] pub mod server; mod sys; mod utils; /// Default UDP association's expire duration #[allow(dead_code)] const DEFAULT_UDP_EXPIRY_DURATION: Duration = Duration::from_secs(5 * 60); #[cfg(feature = "hickory-dns")] fn hint_support_default_system_resolver() -> bool { // Nearly all *nix system have /etc/resolv.conf, except Android. // macOS have to use system provided resolver. cfg!(all( unix, not(target_os = "android"), // not(target_os = "macos"), // not(target_os = "ios") )) } ================================================ FILE: crates/shadowsocks-service/src/local/context.rs ================================================ //! Shadowsocks Local Server Context use std::sync::Arc; #[cfg(feature = "local-dns")] use std::{net::IpAddr, time::Duration}; #[cfg(feature = "local-dns")] use lru_time_cache::LruCache; use shadowsocks::{ config::ServerType, context::{Context, SharedContext}, dns_resolver::DnsResolver, net::{AcceptOpts, ConnectOpts}, relay::Address, }; #[cfg(feature = "local-dns")] use tokio::sync::Mutex; #[cfg(feature = "local-fake-dns")] use tokio::sync::RwLock; use crate::{acl::AccessControl, config::SecurityConfig, net::FlowStat}; #[cfg(feature = "local-fake-dns")] use super::fake_dns::manager::FakeDnsManager; /// Local Service Context #[derive(Clone)] pub struct ServiceContext { context: SharedContext, connect_opts: ConnectOpts, accept_opts: AcceptOpts, // Access Control acl: Option>, // Flow statistic report flow_stat: Arc, // For DNS relay's ACL domain name reverse lookup -- whether the IP shall be forwarded #[cfg(feature = "local-dns")] reverse_lookup_cache: Arc>>, #[cfg(feature = "local-fake-dns")] fake_dns_manager: Arc>>>, } impl Default for ServiceContext { fn default() -> Self { Self::new() } } impl ServiceContext { /// Create a new `ServiceContext` pub fn new() -> Self { Self { context: Context::new_shared(ServerType::Local), connect_opts: ConnectOpts::default(), accept_opts: AcceptOpts::default(), acl: None, flow_stat: Arc::new(FlowStat::new()), #[cfg(feature = "local-dns")] reverse_lookup_cache: Arc::new(Mutex::new(LruCache::with_expiry_duration_and_capacity( Duration::from_secs(3 * 24 * 60 * 60), 10240, // XXX: It should be enough for a normal user. ))), #[cfg(feature = "local-fake-dns")] fake_dns_manager: Arc::new(RwLock::new(Vec::new())), } } /// Get cloned `shadowsocks` Context pub fn context(&self) -> SharedContext { self.context.clone() } /// Get `shadowsocks` Context reference pub fn context_ref(&self) -> &Context { self.context.as_ref() } /// Set `ConnectOpts` pub fn set_connect_opts(&mut self, connect_opts: ConnectOpts) { self.connect_opts = connect_opts; } /// Get `ConnectOpts` reference pub fn connect_opts_ref(&self) -> &ConnectOpts { &self.connect_opts } /// Set `AcceptOpts` pub fn set_accept_opts(&mut self, accept_opts: AcceptOpts) { self.accept_opts = accept_opts; } /// Get `AcceptOpts` cloned pub fn accept_opts(&self) -> AcceptOpts { self.accept_opts.clone() } /// Set Access Control List pub fn set_acl(&mut self, acl: Arc) { self.acl = Some(acl); } /// Get Access Control List reference pub fn acl(&self) -> Option<&AccessControl> { self.acl.as_deref() } /// Get cloned flow statistic pub fn flow_stat(&self) -> Arc { self.flow_stat.clone() } /// Get flow statistic reference pub fn flow_stat_ref(&self) -> &FlowStat { self.flow_stat.as_ref() } /// Set customized DNS resolver pub fn set_dns_resolver(&mut self, resolver: Arc) { let context = Arc::get_mut(&mut self.context).expect("cannot set DNS resolver on a shared context"); context.set_dns_resolver(resolver) } /// Get reference of DNS resolver pub fn dns_resolver(&self) -> &DnsResolver { self.context.dns_resolver() } /// Check if target should be bypassed pub async fn check_target_bypassed(&self, addr: &Address) -> bool { match self.acl { None => false, Some(ref acl) => { #[cfg(feature = "local-dns")] { if let Address::SocketAddress(saddr) = addr { // do the reverse lookup in our local cache let mut reverse_lookup_cache = self.reverse_lookup_cache.lock().await; // if a qname is found if let Some(forward) = reverse_lookup_cache.get(&saddr.ip()) { return !*forward; } } } acl.check_target_bypassed(&self.context, addr).await } } } /// Add a record to the reverse lookup cache #[cfg(feature = "local-dns")] pub async fn add_to_reverse_lookup_cache(&self, addr: IpAddr, forward: bool) { let is_exception = forward != match self.acl { // Proxy everything by default None => true, Some(ref a) => a.check_ip_in_proxy_list(&addr), }; let mut reverse_lookup_cache = self.reverse_lookup_cache.lock().await; match reverse_lookup_cache.get_mut(&addr) { Some(value) => { if is_exception { *value = forward; } else { // we do not need to remember the entry if it is already matched correctly reverse_lookup_cache.remove(&addr); } } None => { if is_exception { reverse_lookup_cache.insert(addr, forward); } } } } /// Try to connect IPv6 addresses first if hostname could be resolved to both IPv4 and IPv6 pub fn set_ipv6_first(&mut self, ipv6_first: bool) { let context = Arc::get_mut(&mut self.context).expect("cannot set ipv6_first on a shared context"); context.set_ipv6_first(ipv6_first); } /// Set security config pub fn set_security_config(&mut self, security: &SecurityConfig) { let context = Arc::get_mut(&mut self.context).expect("cannot set security on a shared context"); context.set_replay_attack_policy(security.replay_attack.policy); } /// Set Fake DNS manager #[cfg(feature = "local-fake-dns")] pub async fn add_fake_dns_manager(&self, manager: Arc) { let mut managers = self.fake_dns_manager.write().await; managers.push(manager); } /// Fake DNS maps IP to Domain #[cfg(feature = "local-fake-dns")] pub async fn try_map_fake_address(&self, addr: &Address) -> Option
{ let socket_addr = match addr { Address::DomainNameAddress(..) => return None, Address::SocketAddress(socket_addr) => socket_addr, }; let ip_addr = socket_addr.ip(); for mgr in self.fake_dns_manager.read().await.iter() { if let Ok(Some(name)) = mgr.map_ip_domain(ip_addr).await { let new_addr = Address::DomainNameAddress(name.to_string(), socket_addr.port()); log::trace!("fakedns mapped {} -> {}", addr, new_addr); return Some(new_addr); } } None } } ================================================ FILE: crates/shadowsocks-service/src/local/dns/client_cache.rs ================================================ //! DNS Client cache #[cfg(unix)] use std::path::Path; use std::{ collections::{HashMap, VecDeque, hash_map::Entry}, future::Future, io, net::SocketAddr, time::Duration, }; use hickory_resolver::proto::{ProtoError, op::Message}; use log::{debug, trace}; use tokio::sync::Mutex; use shadowsocks::{config::ServerConfig, net::ConnectOpts, relay::socks5::Address}; use crate::local::context::ServiceContext; use super::upstream::DnsClient; #[derive(Clone, Debug, Hash, Eq, PartialEq, PartialOrd, Ord)] enum DnsClientKey { TcpLocal(SocketAddr), UdpLocal(SocketAddr), TcpRemote(Address), UdpRemote(Address), } pub struct DnsClientCache { cache: Mutex>>, timeout: Duration, retry_count: usize, max_client_per_addr: usize, } impl DnsClientCache { pub fn new(max_client_per_addr: usize) -> Self { Self { cache: Mutex::new(HashMap::new()), timeout: Duration::from_secs(5), retry_count: 1, max_client_per_addr, } } pub async fn lookup_local( &self, ns: SocketAddr, msg: Message, connect_opts: &ConnectOpts, is_udp: bool, ) -> Result { let key = match is_udp { true => DnsClientKey::UdpLocal(ns), false => DnsClientKey::TcpLocal(ns), }; self.lookup_dns(&key, msg, Some(connect_opts), None, None).await } pub async fn lookup_remote( &self, context: &ServiceContext, svr_cfg: &ServerConfig, ns: &Address, msg: Message, is_udp: bool, ) -> Result { let key = match is_udp { true => DnsClientKey::UdpRemote(ns.clone()), false => DnsClientKey::TcpRemote(ns.clone()), }; self.lookup_dns(&key, msg, None, Some(context), Some(svr_cfg)).await } #[cfg(unix)] pub async fn lookup_unix_stream>(&self, ns: &P, msg: Message) -> Result { let mut last_err = None; for _ in 0..self.retry_count { // UNIX stream won't keep connection alive // // https://github.com/shadowsocks/shadowsocks-rust/pull/567 // // 1. The cost of recreating UNIX stream sockets are very low // 2. This feature is only used by shadowsocks-android, and it doesn't support connection reuse let mut client = match DnsClient::connect_unix_stream(ns).await { Ok(client) => client, Err(err) => { last_err = Some(From::from(err)); continue; } }; let res = match client.lookup_timeout(msg.clone(), self.timeout).await { Ok(msg) => msg, Err(error) => { last_err = Some(error); continue; } }; return Ok(res); } Err(last_err.unwrap()) } async fn lookup_dns( &self, dck: &DnsClientKey, msg: Message, connect_opts: Option<&ConnectOpts>, context: Option<&ServiceContext>, svr_cfg: Option<&ServerConfig>, ) -> Result { let mut last_err = None; for _ in 0..self.retry_count { let create_fn = async { match dck { DnsClientKey::TcpLocal(tcp_l) => { let connect_opts = connect_opts.expect("connect options is required for local DNS"); DnsClient::connect_tcp_local(*tcp_l, connect_opts).await } DnsClientKey::UdpLocal(udp_l) => { let connect_opts = connect_opts.expect("connect options is required for local DNS"); DnsClient::connect_udp_local(*udp_l, connect_opts).await } DnsClientKey::TcpRemote(tcp_l) => { let context = context.expect("context is required for remote DNS"); let svr_cfg = svr_cfg.expect("server config is required for remote DNS"); DnsClient::connect_tcp_remote( context.context(), svr_cfg, tcp_l, context.connect_opts_ref(), context.flow_stat(), ) .await } DnsClientKey::UdpRemote(udp_l) => { let context = context.expect("context is required for remote DNS"); let svr_cfg = svr_cfg.expect("server config is required for remote DNS"); DnsClient::connect_udp_remote( context.context(), svr_cfg, udp_l.clone(), context.connect_opts_ref(), context.flow_stat(), ) .await } } }; match self.get_client_or_create(dck, create_fn).await { Ok(mut client) => match client.lookup_timeout(msg.clone(), self.timeout).await { Ok(msg) => { self.save_client(dck.clone(), client).await; return Ok(msg); } Err(err) => { last_err = Some(err); continue; } }, Err(err) => { last_err = Some(From::from(err)); continue; } } } Err(last_err.unwrap()) } async fn get_client_or_create(&self, key: &DnsClientKey, create_fn: C) -> io::Result where C: Future>, { // Check if there already is a cached client if let Some(q) = self.cache.lock().await.get_mut(key) { while let Some(mut c) = q.pop_front() { trace!("take cached DNS client for {:?}", key); if !c.check_connected().await { debug!("cached DNS client for {:?} is lost", key); continue; } return Ok(c); } } trace!("creating connection to DNS server {:?}", key); // Create one create_fn.await } async fn save_client(&self, key: DnsClientKey, client: DnsClient) { match self.cache.lock().await.entry(key) { Entry::Occupied(occ) => { let q = occ.into_mut(); q.push_back(client); if q.len() > self.max_client_per_addr { q.pop_front(); } } Entry::Vacant(vac) => { let mut q = VecDeque::with_capacity(self.max_client_per_addr); q.push_back(client); vac.insert(q); } } } } ================================================ FILE: crates/shadowsocks-service/src/local/dns/config.rs ================================================ //! DNS configurations #[cfg(unix)] use std::{convert::Infallible, path::PathBuf}; use std::{ fmt::{self, Display}, net::{IpAddr, SocketAddr}, str::FromStr, }; /// DNS name server address #[derive(Debug, Clone, Eq, PartialEq, Hash)] pub enum NameServerAddr { /// IP address SocketAddr(SocketAddr), /// Unix Domain Socket address /// /// Specifically used by Android, which served as a stream protocol based DNS server #[cfg(unix)] UnixSocketAddr(PathBuf), } /// Parse `NameServerAddr` error #[cfg(unix)] pub type NameServerAddrError = Infallible; /// Parse `NameServerAddr` error #[cfg(not(unix))] pub type NameServerAddrError = ::Err; impl FromStr for NameServerAddr { type Err = NameServerAddrError; fn from_str(s: &str) -> Result { if let Ok(ip) = s.parse::() { return Ok(Self::SocketAddr(SocketAddr::new(ip, 53))); } match s.parse::() { Ok(addr) => Ok(Self::SocketAddr(addr)), #[cfg(unix)] Err(..) => Ok(Self::UnixSocketAddr(PathBuf::from(s))), #[cfg(not(unix))] Err(err) => Err(err), } } } impl Display for NameServerAddr { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match *self { Self::SocketAddr(ref sa) => Display::fmt(sa, f), #[cfg(unix)] Self::UnixSocketAddr(ref p) => write!(f, "{}", p.display()), } } } ================================================ FILE: crates/shadowsocks-service/src/local/dns/dns_resolver.rs ================================================ //! Replacement of service's DNS resolver use std::{ io::{self, ErrorKind}, net::{Ipv4Addr, Ipv6Addr, SocketAddr}, }; use futures::future; use hickory_resolver::proto::{ op::{Message, Query}, rr::{DNSClass, Name, RData, RecordType}, }; use log::{debug, trace}; use shadowsocks::{config::Mode, dns_resolver::DnsResolve, net::ConnectOpts}; use super::{client_cache::DnsClientCache, config::NameServerAddr}; pub struct DnsResolver { ns: NameServerAddr, client_cache: DnsClientCache, mode: Mode, ipv6_first: bool, connect_opts: ConnectOpts, attempts: usize, } impl DnsResolver { pub fn new(ns: NameServerAddr) -> Self { Self { ns, client_cache: DnsClientCache::new(5), mode: Mode::UdpOnly, ipv6_first: false, connect_opts: ConnectOpts::default(), attempts: 2, } } pub fn set_mode(&mut self, mode: Mode) { self.mode = mode; } pub fn set_ipv6_first(&mut self, ipv6_first: bool) { self.ipv6_first = ipv6_first; } pub fn set_connect_opts(&mut self, connect_opts: ConnectOpts) { self.connect_opts = connect_opts; } async fn lookup(&self, msg: Message) -> io::Result { let mut last_err = io::Error::new(ErrorKind::InvalidData, "resolve empty"); for _ in 0..self.attempts { match self.lookup_inner(msg.clone()).await { Ok(m) => return Ok(m), Err(err) => last_err = err, } } Err(last_err) } async fn lookup_inner(&self, msg: Message) -> io::Result { match self.ns { NameServerAddr::SocketAddr(ns) => { let mut last_err = io::Error::new(ErrorKind::InvalidData, "resolve empty"); // Query UDP then TCP if self.mode.enable_udp() { match self .client_cache .lookup_local(ns, msg.clone(), &self.connect_opts, true) .await { Ok(msg) => return Ok(msg), Err(err) => { last_err = err.into(); } } } if self.mode.enable_tcp() { match self.client_cache.lookup_local(ns, msg, &self.connect_opts, false).await { Ok(msg) => return Ok(msg), Err(err) => { last_err = err.into(); } } } Err(last_err) } #[cfg(unix)] NameServerAddr::UnixSocketAddr(ref path) => self .client_cache .lookup_unix_stream(path, msg) .await .map_err(From::from), } } } impl DnsResolve for DnsResolver { async fn resolve(&self, host: &str, port: u16) -> io::Result> { let mut name = Name::from_utf8(host)?; name.set_fqdn(true); let mut queryv4 = Query::new(); queryv4.set_query_class(DNSClass::IN); queryv4.set_name(name); let mut queryv6 = queryv4.clone(); queryv4.set_query_type(RecordType::A); queryv6.set_query_type(RecordType::AAAA); let mut msgv4 = Message::new(); msgv4.set_recursion_desired(true); msgv4.add_query(queryv4); let mut msgv6 = Message::new(); msgv6.set_recursion_desired(true); msgv6.add_query(queryv6); match future::join(self.lookup(msgv4), self.lookup(msgv6)).await { (Err(res_v4), Err(res_v6)) => { if self.ipv6_first { Err(res_v6) } else { Err(res_v4) } } (res_v4, res_v6) => { let mut vaddr: Vec = vec![]; if self.ipv6_first { match res_v6 { Ok(res) => vaddr = store_dns(res, port), Err(err) => debug!("failed to resolve AAAA records, error: {}", err), } match res_v4 { Ok(res) => vaddr = store_dns(res, port), Err(err) => debug!("failed to resolve A records, error: {}", err), } } else { match res_v4 { Ok(res) => vaddr = store_dns(res, port), Err(err) => debug!("failed to resolve A records, error: {}", err), } match res_v6 { Ok(res) => vaddr = store_dns(res, port), Err(err) => debug!("failed to resolve AAAA records, error: {}", err), } } if vaddr.is_empty() { let err = io::Error::new(ErrorKind::InvalidData, "resolve empty"); return Err(err); } Ok(vaddr) } } } } fn store_dns(res: Message, port: u16) -> Vec { let mut vaddr = Vec::new(); for record in res.answers() { match record.data() { RData::A(addr) => vaddr.push(SocketAddr::new(Ipv4Addr::from(*addr).into(), port)), RData::AAAA(addr) => vaddr.push(SocketAddr::new(Ipv6Addr::from(*addr).into(), port)), rdata => { trace!("skipped rdata {:?}", rdata); } } } vaddr } ================================================ FILE: crates/shadowsocks-service/src/local/dns/mod.rs ================================================ //! Customized DNS resolver pub use self::{ config::NameServerAddr, server::{Dns, DnsBuilder}, }; mod client_cache; pub mod config; pub mod dns_resolver; pub mod server; mod upstream; ================================================ FILE: crates/shadowsocks-service/src/local/dns/server.rs ================================================ //! Shadowsocks DNS relay local server //! //! This DNS server requires 2 upstream DNS servers, one for direct queries, and the other queries through shadowsocks proxy use std::{ cmp::Ordering, collections::HashSet, io::{self, ErrorKind}, net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr}, str::FromStr, sync::Arc, time::Duration, }; use byteorder::{BigEndian, ByteOrder}; use bytes::{BufMut, BytesMut}; use futures::{ FutureExt, future::{self, Either}, }; use hickory_resolver::proto::{ op::{Message, OpCode, Query, header::MessageType, response_code::ResponseCode}, rr::{DNSClass, Name, RData, RecordType}, }; use log::{debug, error, info, trace, warn}; use tokio::{ io::{AsyncReadExt, AsyncWriteExt}, net::{TcpStream, UdpSocket}, time, }; use shadowsocks::{ ServerAddr, config::Mode, net::TcpListener, relay::{Address, udprelay::MAXIMUM_UDP_PAYLOAD_SIZE}, }; use crate::{ acl::AccessControl, local::{ context::ServiceContext, loadbalancing::PingBalancer, net::{tcp::listener::create_standard_tcp_listener, udp::listener::create_standard_udp_listener}, }, }; use super::{client_cache::DnsClientCache, config::NameServerAddr}; /// DNS Relay server builder pub struct DnsBuilder { context: Arc, mode: Mode, local_addr: NameServerAddr, remote_addr: Address, bind_addr: ServerAddr, balancer: PingBalancer, client_cache_size: usize, #[cfg(target_os = "macos")] launchd_tcp_socket_name: Option, #[cfg(target_os = "macos")] launchd_udp_socket_name: Option, } impl DnsBuilder { /// Create a new DNS Relay server pub fn new( bind_addr: ServerAddr, local_addr: NameServerAddr, remote_addr: Address, balancer: PingBalancer, client_cache_size: usize, ) -> Self { let context = ServiceContext::new(); Self::with_context( Arc::new(context), bind_addr, local_addr, remote_addr, balancer, client_cache_size, ) } /// Create with an existed `context` pub fn with_context( context: Arc, bind_addr: ServerAddr, local_addr: NameServerAddr, remote_addr: Address, balancer: PingBalancer, client_cache_size: usize, ) -> Self { Self { context, mode: Mode::UdpOnly, local_addr, remote_addr, bind_addr, balancer, client_cache_size, #[cfg(target_os = "macos")] launchd_tcp_socket_name: None, #[cfg(target_os = "macos")] launchd_udp_socket_name: None, } } /// Set remote server mode pub fn set_mode(&mut self, mode: Mode) { self.mode = mode; } /// macOS launchd activate socket #[cfg(target_os = "macos")] pub fn set_launchd_tcp_socket_name(&mut self, n: String) { self.launchd_tcp_socket_name = Some(n); } /// macOS launchd activate socket #[cfg(target_os = "macos")] pub fn set_launchd_udp_socket_name(&mut self, n: String) { self.launchd_udp_socket_name = Some(n); } /// Build DNS server pub async fn build(self) -> io::Result { let client = Arc::new(DnsClient::new( self.context.clone(), self.balancer, self.mode, self.client_cache_size, )); let local_addr = Arc::new(self.local_addr); let remote_addr = Arc::new(self.remote_addr); let mut tcp_server = None; if self.mode.enable_tcp() { #[allow(unused_mut)] let mut builder = DnsTcpServerBuilder::new( self.context.clone(), self.bind_addr.clone(), local_addr.clone(), remote_addr.clone(), client.clone(), ); #[cfg(target_os = "macos")] if let Some(s) = self.launchd_tcp_socket_name { builder.set_launchd_socket_name(s); } let server = builder.build().await?; tcp_server = Some(server); } let mut udp_server = None; if self.mode.enable_udp() { #[allow(unused_mut)] let mut builder = DnsUdpServerBuilder::new(self.context, self.bind_addr, local_addr, remote_addr, client); #[cfg(target_os = "macos")] if let Some(s) = self.launchd_udp_socket_name { builder.set_launchd_socket_name(s); } let server = builder.build().await?; udp_server = Some(server); } Ok(Dns { tcp_server, udp_server }) } } struct DnsTcpServerBuilder { context: Arc, bind_addr: ServerAddr, local_addr: Arc, remote_addr: Arc
, client: Arc, #[cfg(target_os = "macos")] launchd_socket_name: Option, } impl DnsTcpServerBuilder { fn new( context: Arc, bind_addr: ServerAddr, local_addr: Arc, remote_addr: Arc
, client: Arc, ) -> Self { Self { context, bind_addr, local_addr, remote_addr, client, #[cfg(target_os = "macos")] launchd_socket_name: None, } } /// macOS launchd activate socket #[cfg(target_os = "macos")] fn set_launchd_socket_name(&mut self, n: String) { self.launchd_socket_name = Some(n); } async fn build(self) -> io::Result { cfg_if::cfg_if! { if #[cfg(target_os = "macos")] { let listener = match self.launchd_socket_name { Some(launchd_socket_name) => { use tokio::net::TcpListener as TokioTcpListener; use crate::net::launch_activate_socket::get_launch_activate_tcp_listener; let std_listener = get_launch_activate_tcp_listener(&launchd_socket_name, true)?; let tokio_listener = TokioTcpListener::from_std(std_listener)?; TcpListener::from_listener(tokio_listener, self.context.accept_opts())? } _ => { create_standard_tcp_listener(&self.context, &self.bind_addr).await? } }; } else { let listener = create_standard_tcp_listener(&self.context, &self.bind_addr).await?; } } Ok(DnsTcpServer { listener, local_addr: self.local_addr, remote_addr: self.remote_addr, client: self.client, }) } } /// DNS TCP server instance pub struct DnsTcpServer { listener: TcpListener, local_addr: Arc, remote_addr: Arc
, client: Arc, } impl DnsTcpServer { /// Get server local address pub fn local_addr(&self) -> io::Result { self.listener.local_addr() } /// Start serving pub async fn run(self) -> io::Result<()> { info!( "shadowsocks dns TCP listening on {}, local: {}, remote: {}", self.listener.local_addr()?, self.local_addr, self.remote_addr ); loop { let (stream, peer_addr) = match self.listener.accept().await { Ok(s) => s, Err(err) => { error!("accept failed with error: {}", err); time::sleep(Duration::from_secs(1)).await; continue; } }; tokio::spawn(Self::handle_tcp_stream( self.client.clone(), stream, peer_addr, self.local_addr.clone(), self.remote_addr.clone(), )); } } async fn handle_tcp_stream( client: Arc, mut stream: TcpStream, peer_addr: SocketAddr, local_addr: Arc, remote_addr: Arc
, ) -> io::Result<()> { let mut length_buf = [0u8; 2]; let mut message_buf = BytesMut::new(); loop { match stream.read_exact(&mut length_buf).await { Ok(..) => {} Err(ref err) if err.kind() == ErrorKind::UnexpectedEof => { break; } Err(err) => { error!("udp tcp {} read length failed, error: {}", peer_addr, err); return Err(err); } } let length = BigEndian::read_u16(&length_buf) as usize; message_buf.clear(); message_buf.reserve(length); unsafe { message_buf.advance_mut(length); } match stream.read_exact(&mut message_buf).await { Ok(..) => {} Err(err) => { error!("dns tcp {} read message failed, error: {}", peer_addr, err); return Err(err); } } let message = match Message::from_vec(&message_buf) { Ok(m) => m, Err(err) => { error!("dns tcp {} parse message failed, error: {}", peer_addr, err); return Err(err.into()); } }; let respond_message = match client.resolve(message, &local_addr, &remote_addr).await { Ok(m) => m, Err(err) => { error!("dns tcp {} lookup error: {}", peer_addr, err); return Err(err); } }; let mut buf = respond_message.to_vec()?; let length = buf.len(); buf.resize(length + 2, 0); buf.copy_within(..length, 2); BigEndian::write_u16(&mut buf[..2], length as u16); stream.write_all(&buf).await?; } trace!("dns tcp connection {} closed", peer_addr); Ok(()) } } struct DnsUdpServerBuilder { context: Arc, bind_addr: ServerAddr, local_addr: Arc, remote_addr: Arc
, client: Arc, #[cfg(target_os = "macos")] launchd_socket_name: Option, } impl DnsUdpServerBuilder { fn new( context: Arc, bind_addr: ServerAddr, local_addr: Arc, remote_addr: Arc
, client: Arc, ) -> Self { Self { context, bind_addr, local_addr, remote_addr, client, #[cfg(target_os = "macos")] launchd_socket_name: None, } } /// macOS launchd activate socket #[cfg(target_os = "macos")] fn set_launchd_socket_name(&mut self, n: String) { self.launchd_socket_name = Some(n); } async fn build(self) -> io::Result { cfg_if::cfg_if! { if #[cfg(target_os = "macos")] { let socket = match self.launchd_socket_name { Some(launchd_socket_name) => { use tokio::net::UdpSocket as TokioUdpSocket; use crate::net::launch_activate_socket::get_launch_activate_udp_socket; let std_socket = get_launch_activate_udp_socket(&launchd_socket_name, true)?; TokioUdpSocket::from_std(std_socket)? } _ => { create_standard_udp_listener(&self.context, &self.bind_addr).await?.into() }}; } else { let socket = create_standard_udp_listener(&self.context, &self.bind_addr).await?.into(); } } Ok(DnsUdpServer { listener: Arc::new(socket), local_addr: self.local_addr, remote_addr: self.remote_addr, client: self.client, }) } } /// DNS UDP server instance pub struct DnsUdpServer { listener: Arc, local_addr: Arc, remote_addr: Arc
, client: Arc, } impl DnsUdpServer { /// Get server local address pub fn local_addr(&self) -> io::Result { self.listener.local_addr() } /// Start serving pub async fn run(self) -> io::Result<()> { info!( "shadowsocks dns UDP listening on {}, local: {}, remote: {}", self.listener.local_addr()?, self.local_addr, self.remote_addr ); let mut buffer = [0u8; MAXIMUM_UDP_PAYLOAD_SIZE]; loop { let (n, peer_addr) = match self.listener.recv_from(&mut buffer).await { Ok(s) => s, Err(err) => { error!("udp server recv_from failed with error: {}", err); time::sleep(Duration::from_secs(1)).await; continue; } }; let data = &buffer[..n]; let message = match Message::from_vec(data) { Ok(m) => m, Err(err) => { error!("dns udp {} query message parse error: {}", peer_addr, err); continue; } }; tokio::spawn(Self::handle_udp_packet( self.client.clone(), self.listener.clone(), peer_addr, message, self.local_addr.clone(), self.remote_addr.clone(), )); } } async fn handle_udp_packet( client: Arc, listener: Arc, peer_addr: SocketAddr, message: Message, local_addr: Arc, remote_addr: Arc
, ) -> io::Result<()> { let respond_message = match client.resolve(message, &local_addr, &remote_addr).await { Ok(m) => m, Err(err) => { error!("dns udp {} lookup failed, error: {}", peer_addr, err); return Err(err); } }; let buf = respond_message.to_vec()?; listener.send_to(&buf, peer_addr).await?; Ok(()) } } /// DNS Relay server pub struct Dns { tcp_server: Option, udp_server: Option, } impl Dns { /// Get TCP server instance pub fn tcp_server(&self) -> Option<&DnsTcpServer> { self.tcp_server.as_ref() } /// Get UDP server instance pub fn udp_server(&self) -> Option<&DnsUdpServer> { self.udp_server.as_ref() } /// Run server pub async fn run(self) -> io::Result<()> { let mut vfut = Vec::new(); if let Some(tcp_server) = self.tcp_server { vfut.push(tcp_server.run().boxed()); } if let Some(udp_server) = self.udp_server { // NOTE: SOCKS 5 RFC requires TCP handshake for UDP ASSOCIATE command // But here we can start a standalone UDP SOCKS 5 relay server, for special use cases vfut.push(udp_server.run().boxed()); } let (res, ..) = future::select_all(vfut).await; res } } fn should_forward_by_ptr_name(acl: &AccessControl, name: &Name) -> bool { let mut iter = name.iter().rev(); let mut next = || match iter.next() { Some(label) => std::str::from_utf8(label).unwrap_or("*"), None => "0", // zero fill the missing labels }; if !"arpa".eq_ignore_ascii_case(next()) { return acl.is_default_in_proxy_list(); } match &next().to_ascii_lowercase()[..] { "in-addr" => { let mut octets: [u8; 4] = [0; 4]; for octet in octets.iter_mut() { match next().parse() { Ok(result) => *octet = result, Err(_) => return acl.is_default_in_proxy_list(), } } acl.check_ip_in_proxy_list(&IpAddr::V4(Ipv4Addr::new(octets[0], octets[1], octets[2], octets[3]))) } "ip6" => { let mut segments: [u16; 8] = [0; 8]; for segment in segments.iter_mut() { match u16::from_str_radix(&[next(), next(), next(), next()].concat(), 16) { Ok(result) => *segment = result, Err(_) => return acl.is_default_in_proxy_list(), } } acl.check_ip_in_proxy_list(&IpAddr::V6(Ipv6Addr::new( segments[0], segments[1], segments[2], segments[3], segments[4], segments[5], segments[6], segments[7], ))) } _ => acl.is_default_in_proxy_list(), } } fn check_name_in_proxy_list(acl: &AccessControl, name: &Name) -> Option { if name.is_fqdn() { // convert to ASCII representation let mut name = name.to_ascii(); name.make_ascii_lowercase(); acl.check_ascii_host_in_proxy_list(&name) } else { // unconditionally use default for PQDNs Some(acl.is_default_in_proxy_list()) } } /// given the query, determine whether remote/local query should be used, or inconclusive fn should_forward_by_query(context: &ServiceContext, balancer: &PingBalancer, query: &Query) -> Option { // No server was configured, then always resolve with local if balancer.is_empty() { return Some(false); } // Check if we are trying to make queries for remote servers // // This happens normally because VPN or TUN device receives DNS queries from local servers' plugins // https://github.com/shadowsocks/shadowsocks-android/issues/2722 for server in balancer.servers() { let svr_cfg = server.server_config(); if let ServerAddr::DomainName(dn, ..) = svr_cfg.addr() { // Convert domain name to `Name` // Ignore it if error occurs if let Ok(mut name) = Name::from_str(dn) { // cmp will handle FQDN in case insensitive way if let Ordering::Equal = query.name().cmp(&name) { // It seems that query is for this server, just bypass it to local resolver trace!("DNS querying name {} of server {:?}", query.name(), svr_cfg); return Some(false); } // test it again with fqdn set name.set_fqdn(true); if let Ordering::Equal = query.name().cmp(&name) { trace!("DNS querying name {} of server {:?}", query.name(), svr_cfg); return Some(false); } } } } if let Some(acl) = context.acl() { if query.query_class() != DNSClass::IN { // unconditionally use default for all non-IN queries Some(acl.is_default_in_proxy_list()) } else if query.query_type() == RecordType::PTR { Some(should_forward_by_ptr_name(acl, query.name())) } else { let result = check_name_in_proxy_list(acl, query.name()); if result.is_none() && acl.is_ip_empty() && acl.is_host_empty() { Some(acl.is_default_in_proxy_list()) } else { result } } } else { Some(true) } } /// given the local response, determine whether remote response should be used instead fn should_forward_by_response( acl: Option<&AccessControl>, local_response: &io::Result, query: &Query, ) -> bool { if let Some(acl) = acl { if let Ok(local_response) = local_response { let mut names = HashSet::new(); names.insert(query.name()); macro_rules! examine_name { ($name:expr_2021, $is_answer:expr_2021) => {{ names.insert($name); if $is_answer { if let Some(value) = check_name_in_proxy_list(acl, $name) { value } else { acl.is_default_in_proxy_list() } } else { acl.is_default_in_proxy_list() } }}; } macro_rules! examine_record { ($rec:ident, $is_answer:expr_2021) => { if let RData::CNAME(name) = $rec.data() { if $is_answer { if let Some(value) = check_name_in_proxy_list(acl, name) { return value; } } names.insert(name); continue; } if $is_answer && !query.query_type().is_any() && $rec.record_type() != query.query_type() { warn!( "local DNS response has inconsistent answer type {} for query {}", $rec.record_type(), query ); return true; } let forward = match $rec.data() { RData::A(ip) => acl.check_ip_in_proxy_list(&IpAddr::V4((*ip).into())), RData::AAAA(ip) => acl.check_ip_in_proxy_list(&IpAddr::V6((*ip).into())), // MX records cause type A additional section processing for the host specified by EXCHANGE. RData::MX(mx) => examine_name!(mx.exchange(), $is_answer), // NS records cause both the usual additional section processing to locate a type A record... RData::NS(name) => examine_name!(name, $is_answer), RData::PTR(_) => unreachable!(), _ => acl.is_default_in_proxy_list(), }; if !forward { return false; } }; } for rec in local_response.answers() { if !names.contains(rec.name()) { warn!( "local DNS response contains unexpected name {} for query {}", rec.name(), query ); return true; } examine_record!(rec, true); } for rec in local_response.additionals() { if names.contains(rec.name()) { examine_record!(rec, false); } } } true } else { unreachable!() } } struct DnsClient { context: Arc, client_cache: DnsClientCache, mode: Mode, balancer: PingBalancer, attempts: usize, } impl DnsClient { fn new(context: Arc, balancer: PingBalancer, mode: Mode, client_cache_size: usize) -> Self { Self { context, client_cache: DnsClientCache::new(client_cache_size), mode, balancer, attempts: 2, } } async fn resolve( &self, request: Message, local_addr: &NameServerAddr, remote_addr: &Address, ) -> io::Result { let mut message = Message::new(); message.set_id(request.id()); message.set_recursion_desired(true); message.set_recursion_available(true); message.set_message_type(MessageType::Response); if !request.recursion_desired() { // RD is required by default. Otherwise it may not get valid respond from remote servers message.set_recursion_desired(false); message.set_response_code(ResponseCode::NotImp); } else if request.op_code() != OpCode::Query || request.message_type() != MessageType::Query { // Other ops are not supported message.set_response_code(ResponseCode::NotImp); } else if request.query_count() > 0 { // Make queries according to ACL rules let (r, forward) = self.acl_lookup(&request.queries()[0], local_addr, remote_addr).await; if let Ok(result) = r { for rec in result.answers() { trace!("dns answer: {:?}", rec); match rec.data() { RData::A(ip) => { self.context .add_to_reverse_lookup_cache(Ipv4Addr::from(*ip).into(), forward) .await } RData::AAAA(ip) => { self.context .add_to_reverse_lookup_cache(Ipv6Addr::from(*ip).into(), forward) .await } _ => (), } } message = result; message.set_id(request.id()); } else { message.set_response_code(ResponseCode::ServFail); } } Ok(message) } async fn acl_lookup( &self, query: &Query, local_addr: &NameServerAddr, remote_addr: &Address, ) -> (io::Result, bool) { // Start querying name servers debug!("DNS lookup {:?} {}", query.query_type(), query.name()); match should_forward_by_query(&self.context, &self.balancer, query) { Some(true) => { let remote_response = self.lookup_remote(query, remote_addr).await; trace!("pick remote response (query): {:?}", remote_response); return (remote_response, true); } Some(false) => { let local_response = self.lookup_local(query, local_addr).await; trace!("pick local response (query): {:?}", local_response); return (local_response, false); } None => (), } let decider = async { let local_response = self.lookup_local(query, local_addr).await; if should_forward_by_response(self.context.acl(), &local_response, query) { None } else { Some(local_response) } }; let remote_response_fut = self.lookup_remote(query, remote_addr); tokio::pin!(remote_response_fut, decider); let mut use_remote = false; let mut remote_response = None; loop { tokio::select! { response = &mut remote_response_fut, if remote_response.is_none() => { if use_remote { trace!("pick remote response (response): {:?}", response); return (response, true); } else { remote_response = Some(response); } } decision = &mut decider, if !use_remote => { if let Some(local_response) = decision { trace!("pick local response (response): {:?}", local_response); return (local_response, false); } else if let Some(remote_response) = remote_response { trace!("pick remote response (response): {:?}", remote_response); return (remote_response, true); } else { use_remote = true; } } else => unreachable!(), } } } async fn lookup_remote(&self, query: &Query, remote_addr: &Address) -> io::Result { let mut last_err = io::Error::new(ErrorKind::InvalidData, "resolve empty"); for _ in 0..self.attempts { match self.lookup_remote_inner(query, remote_addr).await { Ok(m) => { return Ok(m); } Err(err) => last_err = err, } } Err(last_err) } async fn lookup_remote_inner(&self, query: &Query, remote_addr: &Address) -> io::Result { let mut message = Message::new(); message.set_id(rand::random()); message.set_recursion_desired(true); message.add_query(query.clone()); // Query UDP and TCP match self.mode { Mode::TcpOnly => { let server = self.balancer.best_tcp_server(); self.client_cache .lookup_remote(&self.context, server.server_config(), remote_addr, message, false) .await .map_err(From::from) } Mode::UdpOnly => { let server = self.balancer.best_udp_server(); self.client_cache .lookup_remote(&self.context, server.server_config(), remote_addr, message, true) .await .map_err(From::from) } Mode::TcpAndUdp => { // Query TCP & UDP simultaneously let message2 = message.clone(); let tcp_fut = async { // For most cases UDP query will return in 1s, // Then this future will be disabled and have no effect // // Randomly choose from 500ms ~ 1.5s for preventing obvious request pattern let sleep_time = rand::random_range(500..=1500); time::sleep(Duration::from_millis(sleep_time)).await; let server = self.balancer.best_tcp_server(); self.client_cache .lookup_remote(&self.context, server.server_config(), remote_addr, message2, false) .await }; let udp_fut = async { let server = self.balancer.best_udp_server(); self.client_cache .lookup_remote(&self.context, server.server_config(), remote_addr, message, true) .await }; tokio::pin!(tcp_fut); tokio::pin!(udp_fut); match future::select(tcp_fut, udp_fut).await { Either::Left((res, next)) => match res { Ok(o) => Ok(o), Err(..) => next.await.map_err(From::from), }, Either::Right((res, next)) => match res { Ok(o) => Ok(o), Err(..) => next.await.map_err(From::from), }, } } } } async fn lookup_local(&self, query: &Query, local_addr: &NameServerAddr) -> io::Result { let mut last_err = io::Error::new(ErrorKind::InvalidData, "resolve empty"); for _ in 0..self.attempts { match self.lookup_local_inner(query, local_addr).await { Ok(m) => { return Ok(m); } Err(err) => last_err = err, } } Err(last_err) } async fn lookup_local_inner(&self, query: &Query, local_addr: &NameServerAddr) -> io::Result { let mut message = Message::new(); message.set_id(rand::random()); message.set_recursion_desired(true); message.add_query(query.clone()); match *local_addr { NameServerAddr::SocketAddr(ns) => { // Query UDP then TCP let udp_query = self.client_cache .lookup_local(ns, message.clone(), self.context.connect_opts_ref(), true); let tcp_query = async move { // Send TCP query after 500ms, because UDP will always return faster than TCP, there is no need to send queries simultaneously time::sleep(Duration::from_millis(500)).await; self.client_cache .lookup_local(ns, message, self.context.connect_opts_ref(), false) .await }; tokio::pin!(udp_query); tokio::pin!(tcp_query); match future::select(udp_query, tcp_query).await { Either::Left((Ok(m), ..)) => Ok(m), Either::Left((Err(..), next)) => next.await.map_err(From::from), Either::Right((Ok(m), ..)) => Ok(m), Either::Right((Err(..), next)) => next.await.map_err(From::from), } } #[cfg(unix)] NameServerAddr::UnixSocketAddr(ref path) => self .client_cache .lookup_unix_stream(path, message) .await .map_err(From::from), } } } ================================================ FILE: crates/shadowsocks-service/src/local/dns/upstream.rs ================================================ //! DNS Relay Upstream #[cfg(unix)] use std::path::Path; use std::{ cmp::Ordering, io::{self, ErrorKind}, net::SocketAddr, sync::Arc, time::Duration, }; use byteorder::{BigEndian, ByteOrder}; use bytes::{BufMut, BytesMut}; use hickory_resolver::proto::{ProtoError, ProtoErrorKind, op::Message}; use log::{error, trace}; use lru_time_cache::{Entry, LruCache}; use shadowsocks::{ config::ServerConfig, context::SharedContext, net::{ConnectOpts, TcpStream as ShadowTcpStream, UdpSocket as ShadowUdpSocket}, relay::{ Address, tcprelay::ProxyClientStream, udprelay::{ProxySocket, options::UdpSocketControlData}, }, }; #[cfg(unix)] use tokio::net::UnixStream; use tokio::{ io::{AsyncRead, AsyncReadExt, AsyncWrite, AsyncWriteExt}, net::UdpSocket, time, }; use crate::{ DEFAULT_UDP_EXPIRY_DURATION, local::net::udp::generate_client_session_id, net::{FlowStat, MonProxySocket, MonProxyStream, packet_window::PacketWindowFilter}, }; /// Collection of various DNS connections #[allow(clippy::large_enum_variant)] pub enum DnsClient { TcpLocal { stream: ShadowTcpStream, }, UdpLocal { socket: UdpSocket, }, #[cfg(unix)] #[allow(dead_code)] UnixStream { stream: UnixStream, }, TcpRemote { stream: ProxyClientStream>, }, UdpRemote { socket: MonProxySocket, ns: Address, control: UdpSocketControlData, server_windows: LruCache, }, } impl DnsClient { /// Connect to local provided TCP DNS server pub async fn connect_tcp_local(ns: SocketAddr, connect_opts: &ConnectOpts) -> io::Result { let stream = ShadowTcpStream::connect_with_opts(&ns, connect_opts).await?; Ok(Self::TcpLocal { stream }) } /// Connect to local provided UDP DNS server pub async fn connect_udp_local(ns: SocketAddr, connect_opts: &ConnectOpts) -> io::Result { let socket = ShadowUdpSocket::connect_with_opts(&ns, connect_opts).await?.into(); Ok(Self::UdpLocal { socket }) } #[cfg(unix)] /// Connect to local provided Unix Domain Socket DNS server, in TCP-like protocol pub async fn connect_unix_stream>(path: &P) -> io::Result { let stream = UnixStream::connect(path).await?; Ok(Self::UnixStream { stream }) } /// Connect to remote DNS server through proxy in TCP pub async fn connect_tcp_remote( context: SharedContext, svr_cfg: &ServerConfig, ns: &Address, connect_opts: &ConnectOpts, flow_stat: Arc, ) -> io::Result { let stream = ProxyClientStream::connect_with_opts_map(context, svr_cfg, ns, connect_opts, |s| { MonProxyStream::from_stream(s, flow_stat) }) .await?; Ok(Self::TcpRemote { stream }) } /// Connect to remote DNS server through proxy in UDP pub async fn connect_udp_remote( context: SharedContext, svr_cfg: &ServerConfig, ns: Address, connect_opts: &ConnectOpts, flow_stat: Arc, ) -> io::Result { let socket = ProxySocket::connect_with_opts(context.clone(), svr_cfg, connect_opts).await?; let socket = MonProxySocket::from_socket(socket, flow_stat.clone()); let mut control = UdpSocketControlData::default(); control.client_session_id = generate_client_session_id(); control.packet_id = 0; // AEAD-2022 Packet ID starts from 1 Ok(Self::UdpRemote { socket, ns, control, // NOTE: expiry duration should be configurable. But the Client is held by DnsClientCache, which expires very quickly. server_windows: LruCache::with_expiry_duration(DEFAULT_UDP_EXPIRY_DURATION), }) } /// Make a DNS lookup #[allow(dead_code)] pub async fn lookup(&mut self, mut msg: Message) -> Result { self.inner_lookup(&mut msg).await } /// Make a DNS lookup with timeout pub async fn lookup_timeout(&mut self, mut msg: Message, timeout: Duration) -> Result { match time::timeout(timeout, self.inner_lookup(&mut msg)).await { Ok(Ok(msg)) => Ok(msg), Ok(Err(error)) => Err(error), Err(..) => Err(ProtoErrorKind::Timeout.into()), } } async fn inner_lookup(&mut self, msg: &mut Message) -> Result { // Make a random ID msg.set_id(rand::random()); trace!("DNS lookup {:?}", msg); match *self { Self::TcpLocal { ref mut stream } => stream_query(stream, msg).await, Self::UdpLocal { ref socket } => { let bytes = msg.to_vec()?; socket.send(&bytes).await?; let mut recv_buf = [0u8; 512]; let n = socket.recv(&mut recv_buf).await?; Message::from_vec(&recv_buf[..n]) } #[cfg(unix)] Self::UnixStream { ref mut stream } => stream_query(stream, msg).await, Self::TcpRemote { ref mut stream } => stream_query(stream, msg).await, Self::UdpRemote { ref mut socket, ref ns, ref mut control, ref mut server_windows, } => { control.packet_id = match control.packet_id.checked_add(1) { Some(i) => i, None => return Err(ProtoErrorKind::Message("packet id overflows").into()), }; let bytes = msg.to_vec()?; socket.send_with_ctrl(ns, control, &bytes).await?; let mut recv_buf = [0u8; 512]; let (n, _, recv_control) = socket.recv_with_ctrl(&mut recv_buf).await?; if let Some(server_control) = recv_control { let filter = match server_windows.entry(server_control.server_session_id) { Entry::Occupied(occ) => occ.into_mut(), Entry::Vacant(vac) => vac.insert(PacketWindowFilter::new()), }; if !filter.validate_packet_id(server_control.packet_id, u64::MAX) { error!( "dns client for {} packet_id {} out of window", ns, server_control.packet_id ); return Err(ProtoErrorKind::Message("packet id out of window").into()); } } Message::from_vec(&recv_buf[..n]) } } } /// Check if the underlying connection is still connecting /// /// This will only work for TCP and UNIX Stream connections. /// UDP clients will always return `true`. pub async fn check_connected(&mut self) -> bool { #[cfg(unix)] fn check_peekable(fd: &mut F) -> bool { let fd = fd.as_raw_fd(); unsafe { let mut peek_buf = [0u8; 1]; let ret = libc::recv( fd, peek_buf.as_mut_ptr() as *mut libc::c_void, peek_buf.len(), libc::MSG_PEEK | libc::MSG_DONTWAIT, ); match ret.cmp(&0) { // EOF, connection lost Ordering::Equal => false, // Data in buffer Ordering::Greater => true, Ordering::Less => { let err = io::Error::last_os_error(); // EAGAIN, EWOULDBLOCK // Still connected. err.kind() == ErrorKind::WouldBlock } } } } #[cfg(windows)] fn check_peekable(s: &mut F) -> bool { use windows_sys::{ Win32::Networking::WinSock::{MSG_PEEK, SOCKET, recv}, core::PSTR, }; let sock = s.as_raw_socket() as SOCKET; unsafe { let mut peek_buf = [0u8; 1]; let ret = recv(sock, peek_buf.as_mut_ptr() as PSTR, peek_buf.len() as i32, MSG_PEEK); match ret.cmp(&0) { // EOF, connection lost Ordering::Equal => false, // Data in buffer Ordering::Greater => true, Ordering::Less => { let err = io::Error::last_os_error(); // I have to trust the `s` have already set to non-blocking mode // Because windows doesn't have MSG_DONTWAIT err.kind() == ErrorKind::WouldBlock } } } } match *self { Self::TcpLocal { ref mut stream } => check_peekable(stream), Self::UdpLocal { .. } => true, #[cfg(unix)] Self::UnixStream { ref mut stream } => check_peekable(stream), Self::TcpRemote { ref mut stream } => check_peekable(stream.get_mut().get_mut()), Self::UdpRemote { .. } => true, } } } pub async fn stream_query(stream: &mut S, r: &Message) -> Result where S: AsyncRead + AsyncWrite + Unpin, { let mut req_bytes = r.to_vec()?; // Prepend length let length = req_bytes.len(); req_bytes.resize(length + 2, 0); req_bytes.copy_within(..length, 2); BigEndian::write_u16(&mut req_bytes[0..2], length as u16); stream.write_all(&req_bytes).await?; // Read response, [LENGTH][Message] let mut length_buf = [0u8; 2]; stream.read_exact(&mut length_buf).await?; let length = BigEndian::read_u16(&length_buf); let mut rsp_bytes = BytesMut::with_capacity(length as usize); unsafe { rsp_bytes.advance_mut(length as usize); } stream.read_exact(&mut rsp_bytes).await?; Message::from_vec(&rsp_bytes) } ================================================ FILE: crates/shadowsocks-service/src/local/fake_dns/manager.rs ================================================ //! Fake DNS manager use std::{ io, iter::Cycle, net::{IpAddr, Ipv4Addr, Ipv6Addr}, path::Path, time::{Duration, SystemTime}, }; use hickory_resolver::proto::rr::Name; use ipnet::{Ipv4AddrRange, Ipv4Net, Ipv6AddrRange, Ipv6Net}; use log::{error, trace, warn}; use rocksdb::DB as RocksDB; use tokio::sync::Mutex; use super::proto; const FAKE_DNS_MANAGER_STORAGE_VERSION: u32 = 3; /// Error type of FakeDns manager #[derive(thiserror::Error, Debug)] pub enum FakeDnsError { /// std::io::Error wrapper #[error("{0}")] IoError(#[from] io::Error), /// rocksdb::Error #[error("{0}")] RocksDBError(#[from] rocksdb::Error), } impl From for io::Error { fn from(value: FakeDnsError) -> Self { match value { FakeDnsError::IoError(e) => e, FakeDnsError::RocksDBError(e) => Self::other(e), } } } /// FakeDns Api Result type pub type FakeDnsResult = Result; /// Fake DNS manager pub struct FakeDnsManager { db: Mutex, ipv4_network: Mutex>, ipv6_network: Mutex>, expire_duration: Duration, } macro_rules! map_domain_ip { ($self:ident, $domain:ident, $addr_ty:ty, $addr_field:ident, $network_field:ident) => {{ let db = $self.db.lock().await; let name2ip_key = FakeDnsManager::get_name2ip_key($domain); loop { let mut domain_name_mapping = proto::DomainNameMapping::default(); if let Some(v) = db.get(&name2ip_key)? { domain_name_mapping = proto::DomainNameMapping::decode(&v)?; if !domain_name_mapping.$addr_field.is_empty() { match domain_name_mapping.$addr_field.parse::<$addr_ty>() { Ok(i) => { let now = FakeDnsManager::get_current_timestamp(); let expire_secs = FakeDnsManager::get_current_timestamp() + $self.expire_duration.as_secs() as i64; if domain_name_mapping.expire_time >= now { // Not expired yet. domain_name_mapping.expire_time = expire_secs; let nv = domain_name_mapping.encode_to_vec()?; db.put(&name2ip_key, nv)?; trace!( "fakedns mapping {} -> {}, expires {}", $domain, i, domain_name_mapping.expire_time ); return Ok((i, $self.expire_duration)); } else { // Expired. Try to reuse. let ip2name_key = FakeDnsManager::get_ip2name_key(i.into()); if let Some(v) = db.get(&ip2name_key)? { let mut ip_mapping = proto::IpAddrMapping::decode(&v)?; if ip_mapping.domain_name == $domain.to_string() { // Try to extend its expire time ip_mapping.expire_time = expire_secs; let nv = ip_mapping.encode_to_vec()?; db.put(&ip2name_key, nv)?; trace!( "fakedns mapping {} -> {}, expires {}", $domain, i, domain_name_mapping.expire_time ); return Ok((i, $self.expire_duration)); } } } } Err(..) => { warn!("failed to parse {}, going to replace", domain_name_mapping.$addr_field); } } } } // Allocate a new IPv4 address for this domain while let Some(ip) = $self.$network_field.lock().await.next() { let ip2name_key = FakeDnsManager::get_ip2name_key(ip.into()); if let Some(v) = db.get(&ip2name_key)? { let ip_mapping = proto::IpAddrMapping::decode(&v)?; let now = FakeDnsManager::get_current_timestamp(); if ip_mapping.expire_time > now { continue; } } let mut ip_mapping = proto::IpAddrMapping::default(); let expire_secs = FakeDnsManager::get_current_timestamp() + $self.expire_duration.as_secs() as i64; ip_mapping.expire_time = expire_secs; ip_mapping.domain_name = $domain.to_string(); let nv = ip_mapping.encode_to_vec()?; db.put(&ip2name_key, nv)?; // Replace name2ip domain_name_mapping.$addr_field = ip.to_string(); domain_name_mapping.expire_time = ip_mapping.expire_time; let nv = domain_name_mapping.encode_to_vec()?; db.put(&name2ip_key, nv)?; trace!( "fakedns mapping {} -> {}, expires {} created", $domain, ip, domain_name_mapping.expire_time ); return Ok((ip, $self.expire_duration)); } } }}; } impl FakeDnsManager { pub fn open>( db_path: P, ipv4_network: Ipv4Net, ipv6_network: Ipv6Net, expire_duration: Duration, ) -> FakeDnsResult { let db_path = db_path.as_ref(); // https://github.com/facebook/rocksdb/wiki/Setup-Options-and-Basic-Tuning let mut db_options = rocksdb::Options::default(); db_options.create_if_missing(true); db_options.set_compression_type(rocksdb::DBCompressionType::Zstd); db_options.set_bottommost_compression_type(rocksdb::DBCompressionType::Zstd); db_options.set_bottommost_zstd_max_train_bytes(0, true); db_options.set_max_background_jobs(6); db_options.set_bytes_per_sync(1048576); db_options.set_compaction_pri(rocksdb::CompactionPri::MinOverlappingRatio); let mut db = match RocksDB::open(&db_options, db_path) { Ok(db) => db, Err(err) => { error!("failed to open rocksdb, path: {}, error: {}", db_path.display(), err); return Err(err.into()); } }; let ipv4_network_str = ipv4_network.to_string(); let ipv6_network_str = ipv6_network.to_string(); let mut recreate_database = true; let key = "shadowsocks_fakedns_meta"; match db.get(key) { Ok(Some(v)) => { if let Ok(c) = proto::StorageMeta::decode(&v) { if c.version == FAKE_DNS_MANAGER_STORAGE_VERSION { if ipv4_network_str != c.ipv4_network || ipv6_network_str != c.ipv6_network { warn!( "IPv4 network {} (storage {}), IPv6 network {} (storage {}) not match", ipv4_network_str, c.ipv4_network, ipv6_network_str, c.ipv6_network ); } else { recreate_database = false; } } else { warn!("storage version {} not match, recreating database", c.version); } } else { warn!("storage meta parse failed. recreating database"); } } Ok(None) => { // New DB without an META } Err(err) => { error!("failed to get {}, error: {}", key, err); return Err(err.into()); } } if recreate_database { drop(db); let _ = RocksDB::destroy(&db_options, db_path); // Re-create by Open db = match RocksDB::open(&db_options, db_path) { Ok(db) => db, Err(err) => { error!( "failed to recreate rocksdb, path: {}, error: {}", db_path.display(), err ); return Err(err.into()); } }; let c = proto::StorageMeta { ipv4_network: ipv4_network_str, ipv6_network: ipv6_network_str, version: FAKE_DNS_MANAGER_STORAGE_VERSION, }; let v = c.encode_to_vec()?; if let Err(err) = db.put(key, v) { error!("failed to init storage, key: {}, error: {}", key, err); return Err(err.into()); } trace!("FakeDNS database created. {:?}", c); } Ok(Self { db: Mutex::new(db), ipv4_network: Mutex::new(ipv4_network.hosts().cycle()), ipv6_network: Mutex::new(ipv6_network.hosts().cycle()), expire_duration, }) } #[inline] fn get_current_timestamp() -> i64 { SystemTime::now() .duration_since(SystemTime::UNIX_EPOCH) .expect("SystemTime") .as_secs() as i64 } #[inline] fn get_name2ip_key(domain: &Name) -> String { format!("shadowsocks_fakedns_name2ip_{domain}") } #[inline] fn get_ip2name_key(ip: IpAddr) -> String { format!("shadowsocks_fakedns_ip2name_{ip}") } /// Get or create an IPv4 mapping for `domain` pub async fn map_domain_ipv4(&self, domain: &Name) -> FakeDnsResult<(Ipv4Addr, Duration)> { map_domain_ip!(self, domain, Ipv4Addr, ipv4_addr, ipv4_network) } /// Get or create an IPv6 mapping for `domain` pub async fn map_domain_ipv6(&self, domain: &Name) -> FakeDnsResult<(Ipv6Addr, Duration)> { map_domain_ip!(self, domain, Ipv6Addr, ipv6_addr, ipv6_network) } /// Get IP mapped domain name pub async fn map_ip_domain(&self, ip: IpAddr) -> FakeDnsResult> { let db = self.db.lock().await; // ip -> domain_name let ip2name_key = Self::get_ip2name_key(ip); match db.get(&ip2name_key)? { None => Ok(None), Some(v) => { // Got ip -> domain_name let mut ip_mapping = proto::IpAddrMapping::decode(&v)?; let now = Self::get_current_timestamp(); if ip_mapping.expire_time >= now { // Ok. It is not expired yet. Try to extend its expire time. ip_mapping.expire_time = now + self.expire_duration.as_secs() as i64; let nv = ip_mapping.encode_to_vec()?; db.put(&ip2name_key, nv)?; // Update name2ip's expire time let name = match ip_mapping.domain_name.parse::() { Ok(n) => n, Err(..) => return Ok(None), }; { let name2ip_key = Self::get_name2ip_key(&name); match db.get(&name2ip_key)? { Some(v) => { let mut domain_name_mapping = proto::DomainNameMapping::decode(&v)?; domain_name_mapping.expire_time = ip_mapping.expire_time; let nv = domain_name_mapping.encode_to_vec()?; db.put(&name2ip_key, nv)?; } None => { // Interesting. No name2ip. return Ok(None); } } } Ok(Some(name)) } else { Ok(None) } } } } } ================================================ FILE: crates/shadowsocks-service/src/local/fake_dns/mod.rs ================================================ //! Fake DNS //! //! Start a DNS resolver server, mapping requested names to local private network addresses. //! When local server receives proxy request with those mapped addresses, it could translate //! it back to the original domain names. //! //! It normally cooperates with `local-redir` and `local-tun`. pub use self::server::{FakeDns, FakeDnsBuilder}; pub mod manager; mod processor; mod proto; pub mod server; mod tcp_server; mod udp_server; ================================================ FILE: crates/shadowsocks-service/src/local/fake_dns/processor.rs ================================================ //! DNS request processor use std::io; use hickory_resolver::proto::{ op::{Header, Message, OpCode, header::MessageType, response_code::ResponseCode}, rr::{ DNSClass, RData, Record, RecordType, rdata::{A, AAAA}, }, }; use log::{debug, trace, warn}; use super::manager::FakeDnsManager; pub async fn handle_dns_request(req_message: &Message, manager: &FakeDnsManager) -> io::Result { let mut rsp_message = Message::new(); let rsp_header = Header::response_from_request(req_message.header()); rsp_message.set_header(rsp_header); if req_message.op_code() != OpCode::Query || req_message.message_type() != MessageType::Query { rsp_message.set_response_code(ResponseCode::NotImp); } else { for query in req_message.queries() { // Copy all the queries into response. rsp_message.add_query(query.clone()); if query.query_class() != DNSClass::IN { // let record = Record::::from_rdata(query.name().clone(), 0, query.query_type()); // rsp_message.add_answer(record); warn!( "Query class: {:?} is not supported. Full {:?}", query.query_class(), req_message ); continue; } match query.query_type() { RecordType::A => { let (ip_addr, expire_duration) = manager.map_domain_ipv4(query.name()).await?; let mut record = Record::::from_rdata( query.name().clone(), expire_duration.as_secs() as u32, RData::A(A(ip_addr)), ); record.set_dns_class(query.query_class()); rsp_message.add_answer(record); } RecordType::AAAA => { let (ip_addr, expire_duration) = manager.map_domain_ipv6(query.name()).await?; let mut record = Record::::from_rdata( query.name().clone(), expire_duration.as_secs() as u32, RData::AAAA(AAAA(ip_addr)), ); record.set_dns_class(query.query_class()); rsp_message.add_answer(record); } _ => { debug!("fakedns {} not supported. {:?}", query.query_type(), query); } } } } trace!("QUERY {:?} ANSWER {:?}", req_message, rsp_message); Ok(rsp_message) } ================================================ FILE: crates/shadowsocks-service/src/local/fake_dns/proto.rs ================================================ //! Data representation in Database use std::io; use serde::{Deserialize, Serialize}; #[derive(Serialize, Deserialize, Default, Clone, Debug)] pub struct StorageMeta { pub ipv4_network: String, pub ipv6_network: String, pub version: u32, } impl StorageMeta { pub fn decode(v: &[u8]) -> io::Result { bson::deserialize_from_slice(v).map_err(io::Error::other) } pub fn encode_to_vec(&self) -> io::Result> { bson::serialize_to_vec(self).map_err(io::Error::other) } } #[derive(Serialize, Deserialize, Default, Clone, Debug)] pub struct IpAddrMapping { pub domain_name: String, pub expire_time: i64, } impl IpAddrMapping { pub fn decode(v: &[u8]) -> io::Result { bson::deserialize_from_slice(v).map_err(io::Error::other) } pub fn encode_to_vec(&self) -> io::Result> { bson::serialize_to_vec(self).map_err(io::Error::other) } } #[derive(Serialize, Deserialize, Default, Clone, Debug)] pub struct DomainNameMapping { pub ipv4_addr: String, pub ipv6_addr: String, pub expire_time: i64, } impl DomainNameMapping { pub fn decode(v: &[u8]) -> io::Result { bson::deserialize_from_slice(v).map_err(io::Error::other) } pub fn encode_to_vec(&self) -> io::Result> { bson::serialize_to_vec(self).map_err(io::Error::other) } } ================================================ FILE: crates/shadowsocks-service/src/local/fake_dns/server.rs ================================================ //! Fake DNS server use std::{ io, net::{Ipv4Addr, Ipv6Addr}, path::{Path, PathBuf}, sync::Arc, time::Duration, }; use futures::{FutureExt, future}; use ipnet::{Ipv4Net, Ipv6Net}; use shadowsocks::config::{Mode, ServerAddr}; use crate::local::context::ServiceContext; use super::{manager::FakeDnsManager, tcp_server::FakeDnsTcpServer, udp_server::FakeDnsUdpServer}; /// Fake DNS builder pub struct FakeDnsBuilder { context: Arc, mode: Mode, client_addr: ServerAddr, database_path: PathBuf, ipv4_network: Ipv4Net, ipv6_network: Ipv6Net, expire_duration: Duration, } impl FakeDnsBuilder { /// Create a new Fake DNS server pub fn new(client_addr: ServerAddr) -> Self { let context = ServiceContext::new(); Self::with_context(Arc::new(context), client_addr) } /// Create a new Fake DNS server with context pub fn with_context(context: Arc, client_addr: ServerAddr) -> Self { Self { context, mode: Mode::TcpAndUdp, client_addr, database_path: "shadowsocks-fakedns.sled".into(), ipv4_network: Ipv4Net::new(Ipv4Addr::new(172, 16, 0, 0), 12).unwrap(), ipv6_network: Ipv6Net::new(Ipv6Addr::new(0xfc00, 0, 0, 0, 0, 0, 0, 0), 7).unwrap(), expire_duration: Duration::from_secs(10), } } /// Set IPv4 network pub fn set_ipv4_network(&mut self, ipv4_network: Ipv4Net) { self.ipv4_network = ipv4_network; } /// Set IPv6 network pub fn set_ipv6_network(&mut self, ipv6_network: Ipv6Net) { self.ipv6_network = ipv6_network; } /// Set expire duration pub fn set_expire_duration(&mut self, expire: Duration) { self.expire_duration = expire; } /// Set database path pub fn set_database_path>(&mut self, database_path: P) { self.database_path = database_path.as_ref().to_path_buf(); } /// Build Fake DNS server pub async fn build(self) -> io::Result { let manager = FakeDnsManager::open( &self.database_path, self.ipv4_network, self.ipv6_network, self.expire_duration, )?; let manager = Arc::new(manager); let mut tcp_server = None; if self.mode.enable_tcp() { let server = FakeDnsTcpServer::new(self.context.clone(), &self.client_addr, manager.clone()).await?; tcp_server = Some(server); } let mut udp_server = None; if self.mode.enable_udp() { let server = FakeDnsUdpServer::new(self.context.clone(), &self.client_addr, manager.clone()).await?; udp_server = Some(server); } Ok(FakeDns { tcp_server, udp_server, manager, }) } } /// Fake DNS server instance pub struct FakeDns { tcp_server: Option, udp_server: Option, manager: Arc, } impl FakeDns { /// TCP Server instance pub fn tcp_server(&self) -> Option<&FakeDnsTcpServer> { self.tcp_server.as_ref() } /// UDP Server instance pub fn udp_server(&self) -> Option<&FakeDnsUdpServer> { self.udp_server.as_ref() } /// Get the manager pub fn clone_manager(&self) -> Arc { self.manager.clone() } /// Run server pub async fn run(self) -> io::Result<()> { let mut vfut = Vec::new(); if let Some(tcp_server) = self.tcp_server { vfut.push(tcp_server.run().boxed()); } if let Some(udp_server) = self.udp_server { vfut.push(udp_server.run().boxed()); } let (res, ..) = future::select_all(vfut).await; res } } ================================================ FILE: crates/shadowsocks-service/src/local/fake_dns/tcp_server.rs ================================================ //! Fake DNS TCP server use std::{ io::{self, ErrorKind}, net::SocketAddr, sync::Arc, time::Duration, }; use byteorder::{BigEndian, ByteOrder}; use bytes::{BufMut, BytesMut}; use hickory_resolver::proto::{ op::{Message, response_code::ResponseCode}, serialize::binary::{BinEncodable, BinEncoder, EncodeMode}, }; use log::{error, trace}; use shadowsocks::{ServerAddr, lookup_then, net::TcpListener as ShadowTcpListener}; use tokio::{ io::{AsyncReadExt, AsyncWriteExt}, net::TcpStream, time, }; use crate::local::context::ServiceContext; use super::{manager::FakeDnsManager, processor::handle_dns_request}; /// Fake DNS TCP server pub struct FakeDnsTcpServer { context: Arc, listener: ShadowTcpListener, manager: Arc, } impl FakeDnsTcpServer { pub(crate) async fn new( context: Arc, client_config: &ServerAddr, manager: Arc, ) -> io::Result { let listener = match *client_config { ServerAddr::SocketAddr(ref saddr) => { ShadowTcpListener::bind_with_opts(saddr, context.accept_opts()).await? } ServerAddr::DomainName(ref dname, port) => { lookup_then!(context.context_ref(), dname, port, |addr| { ShadowTcpListener::bind_with_opts(&addr, context.accept_opts()).await })? .1 } }; Ok(Self { context, listener, manager, }) } /// Get TCP local address pub fn local_addr(&self) -> io::Result { self.listener.local_addr() } /// Run TCP server loop pub async fn run(self) -> io::Result<()> { loop { let (stream, peer_addr) = match self.listener.accept().await { Ok(s) => s, Err(err) => { error!("failed to accept Fake DNS connection, err: {}", err); time::sleep(Duration::from_secs(1)).await; continue; } }; trace!("Fake DNS accepted TCP client {}", peer_addr); let context = self.context.clone(); let manager = self.manager.clone(); tokio::spawn(async move { if let Err(err) = Self::handle_client(context, peer_addr, stream, manager).await { error!( "failed to handle Fake DNS tcp client, peer: {}, err: {}", peer_addr, err ); } }); } } async fn handle_client( _context: Arc, peer_addr: SocketAddr, mut stream: TcpStream, manager: Arc, ) -> io::Result<()> { let mut length_buf = [0u8; 2]; let mut message_buf = BytesMut::new(); loop { match stream.read_exact(&mut length_buf).await { Ok(..) => {} Err(ref err) if err.kind() == ErrorKind::UnexpectedEof => { break; } Err(err) => { error!("udp tcp {} read length failed, error: {}", peer_addr, err); return Err(err); } } let length = BigEndian::read_u16(&length_buf) as usize; message_buf.clear(); message_buf.reserve(length); unsafe { message_buf.advance_mut(length); } match stream.read_exact(&mut message_buf).await { Ok(..) => {} Err(err) => { error!("dns tcp {} read message failed, error: {}", peer_addr, err); return Err(err); } } let req_message = match Message::from_vec(&message_buf) { Ok(m) => m, Err(err) => { error!("dns tcp {} parse message failed, error: {}", peer_addr, err); return Err(err.into()); } }; let rsp_message = match handle_dns_request(&req_message, &manager).await { Ok(m) => m, Err(err) => { error!("failed to handle DNS request, error: {}", err); Message::error_msg(req_message.id(), req_message.op_code(), ResponseCode::ServFail) } }; let mut rsp_buffer = Vec::with_capacity(2 + 512); rsp_buffer.resize(2, 0); let mut rsp_encoder = BinEncoder::with_offset(&mut rsp_buffer, 2, EncodeMode::Normal); rsp_message.emit(&mut rsp_encoder)?; let rsp_length = (rsp_buffer.len() - 2) as u16; BigEndian::write_u16(&mut rsp_buffer[0..2], rsp_length); stream.write_all(&rsp_buffer).await?; } Ok(()) } } ================================================ FILE: crates/shadowsocks-service/src/local/fake_dns/udp_server.rs ================================================ //! Fake DNS UDP server use std::{io, net::SocketAddr, sync::Arc, time::Duration}; use hickory_resolver::proto::op::{Message, response_code::ResponseCode}; use log::error; use shadowsocks::{ServerAddr, lookup_then, net::UdpSocket as ShadowUdpSocket}; use tokio::time; use crate::local::context::ServiceContext; use super::{manager::FakeDnsManager, processor::handle_dns_request}; /// Fake DNS UDP server instance pub struct FakeDnsUdpServer { listener: ShadowUdpSocket, manager: Arc, } impl FakeDnsUdpServer { pub(crate) async fn new( context: Arc, client_config: &ServerAddr, manager: Arc, ) -> io::Result { let listener = match *client_config { ServerAddr::SocketAddr(ref saddr) => { ShadowUdpSocket::listen_with_opts(saddr, context.accept_opts()).await? } ServerAddr::DomainName(ref dname, port) => { lookup_then!(context.context_ref(), dname, port, |addr| { ShadowUdpSocket::listen_with_opts(&addr, context.accept_opts()).await })? .1 } }; Ok(Self { listener, manager }) } /// Get UDP local address pub fn local_addr(&self) -> io::Result { self.listener.local_addr() } /// Start server accept loop pub async fn run(self) -> io::Result<()> { let mut buffer = [0u8; 65535]; loop { let (n, peer_addr) = match self.listener.recv_from(&mut buffer).await { Ok(n) => n, Err(err) => { error!("fakedns UDP recv_from failed, error: {}", err); time::sleep(Duration::from_secs(1)).await; continue; } }; let req_message = match Message::from_vec(&buffer[..n]) { Ok(m) => m, Err(err) => { error!("failed to parse DNS request, error: {}", err); continue; } }; let rsp_message = match handle_dns_request(&req_message, &self.manager).await { Ok(m) => m, Err(err) => { error!("failed to handle DNS request, error: {}", err); Message::error_msg(req_message.id(), req_message.op_code(), ResponseCode::ServFail) } }; let rsp_buffer = rsp_message.to_vec()?; let _ = self.listener.send_to(&rsp_buffer, peer_addr).await; } } } ================================================ FILE: crates/shadowsocks-service/src/local/http/config.rs ================================================ //! HTTP protocol configuration use std::{ collections::HashMap, fs::OpenOptions, io::{self, Read}, path::Path, }; use base64::Engine as _; use log::trace; use serde::Deserialize; const BASIC_AUTH_BASE64_ENGINE: base64::engine::GeneralPurpose = base64::engine::GeneralPurpose::new( &base64::alphabet::STANDARD, base64::engine::GeneralPurposeConfig::new() .with_encode_padding(true) .with_decode_padding_mode(base64::engine::DecodePaddingMode::Indifferent), ); #[derive(Deserialize, Debug)] struct SSHttpAuthBasicUserConfig { user_name: String, password: String, } #[derive(Deserialize, Debug)] struct SSHttpAuthBasicConfig { users: Vec, } #[derive(Deserialize, Debug)] struct SSHttpAuthConfig { #[serde(skip_serializing_if = "Option::is_none")] basic: Option, } /// HTTP Authentication method #[derive(Debug, Clone)] pub struct HttpAuthConfig { pub basic: HttpAuthBasicConfig, } impl HttpAuthConfig { /// Create a new HTTP Authentication configuration pub fn new() -> Self { Self { basic: HttpAuthBasicConfig::new(), } } /// Load from configuration file /// /// ```json /// { /// "basic": { /// "users": [ /// { /// "user_name": "USER_NAME", /// "password": "PASSWORD" /// } /// ] /// } /// } pub fn load_from_file + ?Sized>(filename: &P) -> io::Result { let filename = filename.as_ref(); trace!( "loading socks5 authentication configuration from {}", filename.display() ); let mut reader = OpenOptions::new().read(true).open(filename)?; let mut content = String::new(); reader.read_to_string(&mut content)?; let jconf: SSHttpAuthConfig = match json5::from_str(&content) { Ok(c) => c, Err(err) => return Err(io::Error::other(err)), }; let mut basic = HttpAuthBasicConfig::new(); if let Some(p) = jconf.basic { for user in p.users { basic.add_user(user.user_name, user.password); } } Ok(Self { basic }) } /// Check if authentication is required pub fn auth_required(&self) -> bool { self.basic.total_users() > 0 } /// Check Basic Authentication pub fn verify_basic_auth(&self, header_value: &str) -> bool { const BASIC_PREFIX: &str = "Basic "; if !header_value.starts_with(BASIC_PREFIX) { return false; } let b64_encoded = &header_value[BASIC_PREFIX.len()..]; let decoded_bytes = match BASIC_AUTH_BASE64_ENGINE.decode(b64_encoded) { Ok(b) => b, Err(_) => return false, }; let decoded_str = match String::from_utf8(decoded_bytes) { Ok(s) => s, Err(_) => return false, }; let (user_name, password) = match decoded_str.split_once(':') { Some((u, p)) => (u, p), None => return false, }; self.basic.check_user(user_name, password) } } impl Default for HttpAuthConfig { fn default() -> Self { Self::new() } } /// HTTP server User/Password Authentication configuration /// /// RFC9110 https://httpwg.org/specs/rfc9110.html#auth.client.proxy #[derive(Debug, Clone)] pub struct HttpAuthBasicConfig { users: HashMap, } impl HttpAuthBasicConfig { /// Create an empty `Passwd` configuration pub fn new() -> Self { Self { users: HashMap::new() } } /// Add a user with password pub fn add_user(&mut self, user_name: U, password: P) where U: Into, P: Into, { self.users.insert(user_name.into(), password.into()); } /// Check if `user_name` exists and validate `password` pub fn check_user(&self, user_name: U, password: P) -> bool where U: AsRef, P: AsRef, { match self.users.get(user_name.as_ref()) { Some(pwd) => pwd == password.as_ref(), None => false, } } /// Total users pub fn total_users(&self) -> usize { self.users.len() } } impl Default for HttpAuthBasicConfig { fn default() -> Self { Self::new() } } ================================================ FILE: crates/shadowsocks-service/src/local/http/http_client.rs ================================================ //! HTTP Client use std::{ borrow::Cow, collections::VecDeque, fmt::Debug, future::Future, io::{self, ErrorKind}, pin::Pin, sync::Arc, task::{Context, Poll}, time::{Duration, Instant}, }; use http::{HeaderValue, Method as HttpMethod, Uri, Version as HttpVersion, header::InvalidHeaderValue}; use hyper::{ Request, Response, body::{self, Body}, client::conn::{TrySendError, http1, http2}, http::uri::Scheme, rt::{Sleep, Timer}, }; use log::{debug, error, trace}; use lru_time_cache::LruCache; use pin_project::pin_project; use shadowsocks::relay::Address; use tokio::sync::Mutex; use crate::local::{context::ServiceContext, loadbalancing::PingBalancer, net::AutoProxyClientStream}; use super::{ http_stream::ProxyHttpStream, tokio_rt::{TokioExecutor, TokioIo}, utils::{check_keep_alive, connect_host, host_addr}, }; const CONNECTION_EXPIRE_DURATION: Duration = Duration::from_secs(20); /// HTTPClient API request errors #[derive(thiserror::Error, Debug)] pub enum HttpClientError { /// Errors from hyper #[error("{0}")] Hyper(#[from] hyper::Error), /// std::io::Error #[error("{0}")] Io(#[from] io::Error), /// Errors from http #[error("{0}")] Http(#[from] http::Error), /// Errors from http header #[error("{0}")] InvalidHeaderValue(#[from] InvalidHeaderValue), } #[allow(clippy::large_enum_variant)] #[derive(thiserror::Error, Debug)] enum SendRequestError { #[error("{0}")] Http(#[from] http::Error), #[error("{0}")] TrySend(#[from] TrySendError>), } #[derive(Clone, Debug)] pub struct TokioTimer; impl Timer for TokioTimer { fn sleep(&self, duration: Duration) -> Pin> { Box::pin(TokioSleep { inner: tokio::time::sleep(duration), }) } fn sleep_until(&self, deadline: Instant) -> Pin> { Box::pin(TokioSleep { inner: tokio::time::sleep_until(deadline.into()), }) } fn reset(&self, sleep: &mut Pin>, new_deadline: Instant) { if let Some(sleep) = sleep.as_mut().downcast_mut_pin::() { sleep.reset(new_deadline) } } } #[pin_project] pub(crate) struct TokioSleep { #[pin] pub(crate) inner: tokio::time::Sleep, } impl Future for TokioSleep { type Output = (); fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { self.project().inner.poll(cx) } } impl Sleep for TokioSleep {} impl TokioSleep { pub fn reset(self: Pin<&mut Self>, deadline: Instant) { self.project().inner.as_mut().reset(deadline.into()); } } /// HTTPClient, supporting HTTP/1.1 and H2, HTTPS. pub struct HttpClient { #[allow(clippy::type_complexity)] cache_conn: Arc, Instant)>>>>, } impl Clone for HttpClient { fn clone(&self) -> Self { Self { cache_conn: self.cache_conn.clone(), } } } impl Default for HttpClient where B: Body + Send + Unpin + Debug + 'static, B::Data: Send, B::Error: Into>, { fn default() -> Self { Self::new() } } impl HttpClient where B: Body + Send + Unpin + Debug + 'static, B::Data: Send, B::Error: Into>, { /// Create a new HttpClient pub fn new() -> Self { Self { cache_conn: Arc::new(Mutex::new(LruCache::with_expiry_duration(CONNECTION_EXPIRE_DURATION))), } } /// Make HTTP requests #[inline] pub async fn send_request( &self, context: Arc, req: Request, balancer: Option<&PingBalancer>, ) -> Result, HttpClientError> { let host = match host_addr(req.uri()) { Some(h) => h, None => panic!("URI missing host: {}", req.uri()), }; // Set Host header if it was missing in the Request let (mut req_parts, req_body) = req.into_parts(); if let Some(authority) = req_parts.uri.authority() { let headers = &mut req_parts.headers; if !headers.contains_key("Host") { let uri = &req_parts.uri; let host_value = if (uri.scheme_str() == Some("http") && matches!(authority.port_u16(), None | Some(80))) || (uri.scheme_str() == Some("https") && matches!(authority.port_u16(), None | Some(443))) { HeaderValue::from_str(authority.host())? } else { HeaderValue::from_str(authority.as_str())? }; headers.insert("Host", host_value); } } let mut req = Request::from_parts(req_parts, req_body); // 1. Check if there is an available client if let Some(c) = self.get_cached_connection(&host).await { trace!("HTTP client for host: {} taken from cache", host); match self.send_request_conn(host.clone(), c, req).await { Ok(response) => return Ok(response), Err(SendRequestError::TrySend(mut err)) => { if let Some(inner_req) = err.take_message() { req = inner_req; // If TrySendError, the connection is probably broken, we should make a new connection debug!( "failed to send request via cached connection to host: {}, error: {}. retry with a new connection", host, err.error() ); } else { error!( "failed to send request via cached connection to host: {}, error: {}. no request to retry", host, err.error() ); return Err(err.into_error().into()); } } Err(SendRequestError::Http(err)) => { error!( "failed to send request via cached connection to host: {}, error: {}", host, err ); return Err(err.into()); } } } // 2. If no. Make a new connection let scheme = match req.uri().scheme() { Some(s) => s, None => &Scheme::HTTP, }; let domain = match host { Address::DomainNameAddress(ref domain, _) => Cow::Borrowed(domain.as_str()), Address::SocketAddress(ref saddr) => Cow::Owned(saddr.ip().to_string()), }; let c = match HttpConnection::connect(context.clone(), scheme, host.clone(), &domain, balancer).await { Ok(c) => c, Err(err) => { error!("failed to connect to host: {}, error: {}", host, err); return Err(err.into()); } }; match self.send_request_conn(host, c, req).await { Ok(response) => Ok(response), Err(SendRequestError::TrySend(err)) => Err(err.into_error().into()), Err(SendRequestError::Http(err)) => Err(err.into()), } } async fn get_cached_connection(&self, host: &Address) -> Option> { if let Some(q) = self.cache_conn.lock().await.get_mut(host) { while let Some((c, inst)) = q.pop_front() { let now = Instant::now(); if now - inst >= CONNECTION_EXPIRE_DURATION { continue; } if c.is_closed() { continue; } if !c.is_ready() { continue; } return Some(c); } } None } async fn send_request_conn( &self, host: Address, mut c: HttpConnection, req: Request, ) -> Result, SendRequestError> { trace!("HTTP making request to host: {}, request: {:?}", host, req); let response = c.send_request(req).await?; trace!("HTTP received response from host: {}, response: {:?}", host, response); // Check keep-alive if check_keep_alive(response.version(), response.headers(), false) { trace!( "HTTP connection keep-alive for host: {}, response: {:?}", host, response ); let cache_conn = self.cache_conn.clone(); tokio::spawn(async move { match c.ready().await { Ok(_) => { trace!("HTTP connection for host: {host} is ready and will be cached"); cache_conn .lock() .await .entry(host) .or_insert_with(VecDeque::new) .push_back((c, Instant::now())); } Err(e) => { trace!("HTTP connection for host: {host} failed to become ready: {}", e); } }; }); } Ok(response) } } enum HttpConnection { Http1(http1::SendRequest), Http2(http2::SendRequest), } impl HttpConnection where B: Body + Send + Unpin + 'static, B::Data: Send, B::Error: Into>, { async fn connect( context: Arc, scheme: &Scheme, host: Address, domain: &str, balancer: Option<&PingBalancer>, ) -> io::Result { if *scheme != Scheme::HTTP && *scheme != Scheme::HTTPS { return Err(io::Error::new(ErrorKind::InvalidInput, "invalid scheme")); } let (stream, _) = connect_host(context, &host, balancer).await?; if *scheme == Scheme::HTTP { Self::connect_http_http1(scheme, host, stream).await } else if *scheme == Scheme::HTTPS { Self::connect_https(scheme, host, domain, stream).await } else { unreachable!() } } async fn connect_http_http1(scheme: &Scheme, host: Address, stream: AutoProxyClientStream) -> io::Result { trace!( "HTTP making new HTTP/1.1 connection to host: {}, scheme: {}", host, scheme ); let stream = ProxyHttpStream::connect_http(stream); // HTTP/1.x let (send_request, connection) = match http1::Builder::new() .preserve_header_case(true) .title_case_headers(true) .handshake(TokioIo::new(stream)) .await { Ok(s) => s, Err(err) => return Err(io::Error::other(err)), }; tokio::spawn(async move { if let Err(err) = connection.await { error!("HTTP/1.x connection to host: {} aborted with error: {}", host, err); } }); Ok(Self::Http1(send_request)) } async fn connect_https( scheme: &Scheme, host: Address, domain: &str, stream: AutoProxyClientStream, ) -> io::Result { trace!("HTTP making new TLS connection to host: {}, scheme: {}", host, scheme); // TLS handshake, check alpn for h2 support. let stream = ProxyHttpStream::connect_https(stream, domain).await?; if stream.negotiated_http2() { // H2 connection let (send_request, connection) = match http2::Builder::new(TokioExecutor) .timer(TokioTimer) .keep_alive_interval(Duration::from_secs(15)) .handshake(TokioIo::new(stream)) .await { Ok(s) => s, Err(err) => return Err(io::Error::other(err)), }; tokio::spawn(async move { if let Err(err) = connection.await { error!("HTTP/2 TLS connection to host: {} aborted with error: {}", host, err); } }); Ok(Self::Http2(send_request)) } else { // HTTP/1.x TLS let (send_request, connection) = match http1::Builder::new() .preserve_header_case(true) .title_case_headers(true) .handshake(TokioIo::new(stream)) .await { Ok(s) => s, Err(err) => return Err(io::Error::other(err)), }; tokio::spawn(async move { if let Err(err) = connection.await { error!("HTTP/1.x TLS connection to host: {} aborted with error: {}", host, err); } }); Ok(Self::Http1(send_request)) } } #[inline] pub async fn send_request(&mut self, mut req: Request) -> Result, SendRequestError> { match self { Self::Http1(r) => { if !matches!( req.version(), HttpVersion::HTTP_09 | HttpVersion::HTTP_10 | HttpVersion::HTTP_11 ) { trace!( "HTTP client changed Request.version to HTTP/1.1 from {:?}", req.version() ); *req.version_mut() = HttpVersion::HTTP_11; } // Remove Scheme, Host part from URI if req.method() != HttpMethod::CONNECT && (req.uri().scheme().is_some() || req.uri().authority().is_some()) { let mut builder = Uri::builder(); match req.uri().path_and_query() { Some(path_and_query) => { builder = builder.path_and_query(path_and_query.as_str()); } _ => { builder = builder.path_and_query("/"); } } *(req.uri_mut()) = builder.build()?; } r.try_send_request(req).await.map_err(Into::into) } Self::Http2(r) => { if !matches!(req.version(), HttpVersion::HTTP_2) { trace!("HTTP client changed Request.version to HTTP/2 from {:?}", req.version()); *req.version_mut() = HttpVersion::HTTP_2; } r.try_send_request(req).await.map_err(Into::into) } } } pub fn is_closed(&self) -> bool { match self { Self::Http1(r) => r.is_closed(), Self::Http2(r) => r.is_closed(), } } pub fn is_ready(&self) -> bool { match self { Self::Http1(r) => r.is_ready(), Self::Http2(r) => r.is_ready(), } } pub async fn ready(&mut self) -> Result<(), hyper::Error> { match self { HttpConnection::Http1(r) => r.ready().await, HttpConnection::Http2(r) => r.ready().await, } } } ================================================ FILE: crates/shadowsocks-service/src/local/http/http_service.rs ================================================ //! Shadowsocks HTTP Proxy server dispatcher use std::{net::SocketAddr, str::FromStr, sync::Arc}; use bytes::Bytes; use http_body_util::{BodyExt, combinators::BoxBody}; use hyper::{ HeaderMap, Method, Request, Response, StatusCode, Uri, Version, body, header::{self, HeaderValue}, http::uri::{Authority, Scheme}, }; use log::{debug, error, trace}; use shadowsocks::relay::Address; use crate::local::{ context::ServiceContext, http::{http_client::HttpClientError, tokio_rt::TokioIo}, loadbalancing::PingBalancer, net::AutoProxyIo, utils::{establish_tcp_tunnel, establish_tcp_tunnel_bypassed}, }; use super::{ config::HttpAuthConfig, http_client::HttpClient, utils::{authority_addr, check_keep_alive, connect_host, host_addr}, }; pub struct HttpService { context: Arc, peer_addr: SocketAddr, http_client: HttpClient, balancer: PingBalancer, http_auth: Arc, } impl HttpService { pub fn new( context: Arc, peer_addr: SocketAddr, http_client: HttpClient, balancer: PingBalancer, http_auth: Arc, ) -> Self { Self { context, peer_addr, http_client, balancer, http_auth, } } pub async fn serve_connection( self, mut req: Request, ) -> hyper::Result>> { trace!("request {} {:?}", self.peer_addr, req); if self.http_auth.auth_required() { // Only support Basic authentication for now match req.headers().get(header::PROXY_AUTHORIZATION) { Some(header_value) => { if let Ok(header_str) = header_value.to_str() { if !self.http_auth.verify_basic_auth(header_str) { error!( "HTTP {} URI {} invalid proxy-authorization: {}", req.method(), req.uri(), header_str ); return make_proxy_authentication_required(); } } else { error!( "HTTP {} URI {} invalid proxy-authorization header encoding: {:?}", req.method(), req.uri(), header_value ); return make_proxy_authentication_required(); } } None => { error!("HTTP {} URI {} missing proxy-authorization", req.method(), req.uri()); return make_proxy_authentication_required(); } } } // Parse URI // // Proxy request URI must contains a host let host = match host_addr(req.uri()) { None => { if req.uri().authority().is_some() { // URI has authority but invalid error!("HTTP {} URI {} doesn't have a valid host", req.method(), req.uri()); return make_bad_request(); } else { trace!("HTTP {} URI {} doesn't have a valid host", req.method(), req.uri()); } match get_addr_from_header(&mut req) { Ok(h) => h, Err(()) => return make_bad_request(), } } Some(h) => h, }; if req.method() == Method::CONNECT { // Establish a TCP tunnel // https://tools.ietf.org/html/draft-luotonen-web-proxy-tunneling-01 debug!("HTTP CONNECT {}", host); // Connect to Shadowsocks' remote // // FIXME: What STATUS should I return for connection error? let (mut stream, server_opt) = match connect_host(self.context, &host, Some(&self.balancer)).await { Ok(s) => s, Err(err) => { error!("failed to CONNECT host: {}, error: {}", host, err); return make_internal_server_error(); } }; debug!( "CONNECT relay connected {} <-> {} ({})", self.peer_addr, host, if stream.is_bypassed() { "bypassed" } else { "proxied" } ); let client_addr = self.peer_addr; tokio::spawn(async move { match hyper::upgrade::on(req).await { Ok(upgraded) => { trace!("CONNECT tunnel upgrade success, {} <-> {}", client_addr, host); let mut upgraded_io = TokioIo::new(upgraded); let _ = match server_opt { Some(server) => { establish_tcp_tunnel( server.server_config(), &mut upgraded_io, &mut stream, client_addr, &host, ) .await } None => { establish_tcp_tunnel_bypassed(&mut upgraded_io, &mut stream, client_addr, &host).await } }; } Err(err) => { error!("failed to upgrade CONNECT request, error: {}", err); } } }); return Ok(Response::new(empty_body())); } // Traditional HTTP Proxy request let method = req.method().clone(); let version = req.version(); debug!("HTTP {} {} {:?}", method, host, version); // Check if client wants us to keep long connection let conn_keep_alive = check_keep_alive(version, req.headers(), true); // Remove non-forwardable headers clear_hop_headers(req.headers_mut()); // Set keep-alive for connection with remote set_conn_keep_alive(version, req.headers_mut(), conn_keep_alive); let mut res = match self .http_client .send_request(self.context, req, Some(&self.balancer)) .await { Ok(resp) => resp, Err(HttpClientError::Hyper(e)) => return Err(e), Err(HttpClientError::Io(err)) => { error!("failed to make request to host: {}, error: {}", host, err); return make_internal_server_error(); } Err(HttpClientError::Http(err)) => { error!("failed to make request to host: {}, error: {}", host, err); return make_bad_request(); } Err(HttpClientError::InvalidHeaderValue(err)) => { error!("failed to make request to host: {}, error: {}", host, err); return make_bad_request(); } }; trace!("received {} <- {} {:?}", self.peer_addr, host, res); let res_keep_alive = conn_keep_alive && check_keep_alive(res.version(), res.headers(), false); // Clear unforwardable headers clear_hop_headers(res.headers_mut()); if res.version() != version { // Reset version to matches req's version trace!("response version {:?} => {:?}", res.version(), version); *res.version_mut() = version; } // Set Connection header set_conn_keep_alive(res.version(), res.headers_mut(), res_keep_alive); trace!("response {} <- {} {:?}", self.peer_addr, host, res); debug!("HTTP {} relay {} <-> {} finished", method, self.peer_addr, host); Ok(res.map(|b| b.boxed())) } } fn empty_body() -> BoxBody { http_body_util::Empty::::new() .map_err(|never| match never {}) .boxed() } fn make_bad_request() -> Result>, hyper::Error> { Ok(Response::builder() .status(StatusCode::BAD_REQUEST) .body(empty_body()) .unwrap()) } fn make_proxy_authentication_required() -> Result>, hyper::Error> { Ok(Response::builder() .status(StatusCode::PROXY_AUTHENTICATION_REQUIRED) .header(header::PROXY_AUTHENTICATE, "Basic charset=\"UTF-8\"") .body(empty_body()) .unwrap()) } fn make_internal_server_error() -> Result>, hyper::Error> { Ok(Response::builder() .status(StatusCode::INTERNAL_SERVER_ERROR) .body(empty_body()) .unwrap()) } fn get_extra_headers(headers: header::GetAll) -> Vec { let mut extra_headers = Vec::new(); for connection in headers { if let Ok(conn) = connection.to_str() { // close is a command instead of a header if conn.eq_ignore_ascii_case("close") { continue; } for header in conn.split(',') { let header = header.trim(); extra_headers.push(header.to_owned()); } } } extra_headers } fn clear_hop_headers(headers: &mut HeaderMap) { // Clear headers indicated by Connection and Proxy-Connection let mut extra_headers = get_extra_headers(headers.get_all("Connection")); extra_headers.extend(get_extra_headers(headers.get_all("Proxy-Connection"))); for header in extra_headers { while headers.remove(&header).is_some() {} } // https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Connection const HOP_BY_HOP_HEADERS: [&str; 9] = [ "Keep-Alive", "Transfer-Encoding", "TE", "Connection", "Trailer", "Upgrade", "Proxy-Authorization", "Proxy-Authenticate", "Proxy-Connection", // Not standard, but many implementations do send this header ]; for header in &HOP_BY_HOP_HEADERS { while headers.remove(*header).is_some() {} } } fn set_conn_keep_alive(version: Version, headers: &mut HeaderMap, keep_alive: bool) { match version { Version::HTTP_09 | Version::HTTP_10 => { // HTTP/1.0 close connection by default if keep_alive { headers.insert("Connection", HeaderValue::from_static("keep-alive")); } } _ => { // HTTP/1.1, HTTP/2, HTTP/3 keep-alive connection by default if !keep_alive { headers.insert("Connection", HeaderValue::from_static("close")); } } } } fn get_addr_from_header(req: &mut Request) -> Result { // Try to be compatible as a transparent HTTP proxy match req.headers().get("Host") { Some(hhost) => match hhost.to_str() { Ok(shost) => { match Authority::from_str(shost) { Ok(authority) => match authority_addr(req.uri().scheme_str(), &authority) { Some(host) => { trace!("HTTP {} URI {} got host from header: {}", req.method(), req.uri(), host); // Reassemble URI let mut parts = req.uri().clone().into_parts(); if parts.scheme.is_none() { // Use http as default. parts.scheme = Some(Scheme::HTTP); } parts.authority = Some(authority); // Replaces URI *req.uri_mut() = Uri::from_parts(parts).expect("Reassemble URI failed"); debug!("reassembled URI from \"Host\", {}", req.uri()); Ok(host) } None => { error!( "HTTP {} URI {} \"Host\" header invalid, value: {}", req.method(), req.uri(), shost ); Err(()) } }, Err(..) => { error!( "HTTP {} URI {} \"Host\" header is not an Authority, value: {:?}", req.method(), req.uri(), hhost ); Err(()) } } } Err(..) => { error!( "HTTP {} URI {} \"Host\" header invalid encoding, value: {:?}", req.method(), req.uri(), hhost ); Err(()) } }, None => { error!( "HTTP {} URI doesn't have valid host and missing the \"Host\" header, URI: {}", req.method(), req.uri() ); Err(()) } } } ================================================ FILE: crates/shadowsocks-service/src/local/http/http_stream.rs ================================================ //! Proxied HTTP stream use std::{ io::{self, ErrorKind}, pin::Pin, task::{self, Poll}, }; use pin_project::pin_project; use tokio::io::{AsyncRead, AsyncWrite, ReadBuf}; use crate::local::net::AutoProxyClientStream; #[allow(clippy::large_enum_variant)] #[pin_project(project = ProxyHttpStreamProj)] pub enum ProxyHttpStream { Http(#[pin] AutoProxyClientStream), #[cfg(feature = "local-http-native-tls")] Https(#[pin] tokio_native_tls::TlsStream, bool), #[cfg(feature = "local-http-rustls")] Https(#[pin] tokio_rustls::client::TlsStream, bool), } impl ProxyHttpStream { pub fn connect_http(stream: AutoProxyClientStream) -> Self { Self::Http(stream) } #[cfg(feature = "local-http-native-tls")] pub async fn connect_https(stream: AutoProxyClientStream, domain: &str) -> io::Result { use native_tls::TlsConnector; let cx = match TlsConnector::builder().request_alpns(&["h2", "http/1.1"]).build() { Ok(c) => c, Err(err) => { return Err(io::Error::other(format!("tls build: {err}"))); } }; let cx = tokio_native_tls::TlsConnector::from(cx); match cx.connect(domain, stream).await { Ok(s) => { let negotiated_h2 = match s.get_ref().negotiated_alpn() { Ok(Some(alpn)) => alpn == b"h2", Ok(None) => false, Err(err) => { let ierr = io::Error::other(format!("tls alpn negotiate: {err}")); return Err(ierr); } }; Ok(ProxyHttpStream::Https(s, negotiated_h2)) } Err(err) => { let ierr = io::Error::other(format!("tls connect: {err}")); Err(ierr) } } } #[cfg(feature = "local-http-rustls")] pub async fn connect_https(stream: AutoProxyClientStream, domain: &str) -> io::Result { use log::warn; use rustls_native_certs::CertificateResult; use std::sync::{Arc, LazyLock}; use tokio_rustls::{ TlsConnector, rustls::{ClientConfig, RootCertStore, pki_types::ServerName}, }; static TLS_CONFIG: LazyLock> = LazyLock::new(|| { let mut config = ClientConfig::builder() .with_root_certificates({ // Load WebPKI roots (Mozilla's root certificates) let mut store = RootCertStore::empty(); store.extend(webpki_roots::TLS_SERVER_ROOTS.iter().cloned()); let CertificateResult { certs, errors, .. } = rustls_native_certs::load_native_certs(); if !errors.is_empty() { for error in errors { warn!("failed to load cert (native), error: {}", error); } } for cert in certs { if let Err(err) = store.add(cert) { warn!("failed to add cert (native), error: {}", err); } } store }) .with_no_client_auth(); // Try to negotiate HTTP/2 config.alpn_protocols = vec![b"h2".to_vec(), b"http/1.1".to_vec()]; Arc::new(config) }); let connector = TlsConnector::from(TLS_CONFIG.clone()); let host = match ServerName::try_from(domain) { Ok(n) => n, Err(_) => { return Err(io::Error::new( ErrorKind::InvalidInput, format!("invalid dnsname \"{domain}\""), )); } }; let tls_stream = connector.connect(host.to_owned(), stream).await?; let (_, session) = tls_stream.get_ref(); let negotiated_http2 = matches!(session.alpn_protocol(), Some(b"h2")); Ok(Self::Https(tls_stream, negotiated_http2)) } #[cfg(not(any(feature = "local-http-native-tls", feature = "local-http-rustls")))] pub async fn connect_https(_stream: AutoProxyClientStream, _domain: &str) -> io::Result { let err = io::Error::other( "https is not supported, consider enable it by feature \"local-http-native-tls\" or \"local-http-rustls\"", ); Err(err) } pub fn negotiated_http2(&self) -> bool { match *self { Self::Http(..) => false, #[cfg(any(feature = "local-http-native-tls", feature = "local-http-rustls"))] Self::Https(_, n) => n, } } } macro_rules! forward_call { ($self:expr, $method:ident $(, $param:expr)*) => { match $self.as_mut().project() { ProxyHttpStreamProj::Http(stream) => stream.$method($($param),*), #[cfg(any(feature = "local-http-native-tls", feature = "local-http-rustls"))] ProxyHttpStreamProj::Https(stream, ..) => stream.$method($($param),*), } }; } impl AsyncRead for ProxyHttpStream { fn poll_read(mut self: Pin<&mut Self>, cx: &mut task::Context<'_>, buf: &mut ReadBuf<'_>) -> Poll> { forward_call!(self, poll_read, cx, buf) } } impl AsyncWrite for ProxyHttpStream { fn poll_write(mut self: Pin<&mut Self>, cx: &mut task::Context<'_>, buf: &[u8]) -> Poll> { forward_call!(self, poll_write, cx, buf) } fn poll_flush(mut self: Pin<&mut Self>, cx: &mut task::Context<'_>) -> Poll> { forward_call!(self, poll_flush, cx) } fn poll_shutdown(mut self: Pin<&mut Self>, cx: &mut task::Context<'_>) -> Poll> { forward_call!(self, poll_shutdown, cx) } } ================================================ FILE: crates/shadowsocks-service/src/local/http/mod.rs ================================================ //! Shadowsocks Local HTTP proxy server //! //! https://www.ietf.org/rfc/rfc2068.txt pub use self::{ http_client::{HttpClient, HttpClientError}, server::{Http, HttpBuilder, HttpConnectionHandler}, }; pub mod config; mod http_client; mod http_service; mod http_stream; pub mod server; mod tokio_rt; mod utils; ================================================ FILE: crates/shadowsocks-service/src/local/http/server.rs ================================================ //! Shadowsocks Local HTTP proxy server //! //! https://www.ietf.org/rfc/rfc2068.txt use std::{io, net::SocketAddr, sync::Arc, time::Duration}; use hyper::{body, server::conn::http1, service}; use log::{error, info, trace}; use shadowsocks::{config::ServerAddr, net::TcpListener}; use tokio::{ io::{AsyncRead, AsyncWrite}, time, }; use crate::local::{ context::ServiceContext, loadbalancing::PingBalancer, net::tcp::listener::create_standard_tcp_listener, }; use super::{config::HttpAuthConfig, http_client::HttpClient, http_service::HttpService, tokio_rt::TokioIo}; /// HTTP Local server builder pub struct HttpBuilder { context: Arc, client_config: ServerAddr, balancer: PingBalancer, #[cfg(target_os = "macos")] launchd_tcp_socket_name: Option, http_auth: HttpAuthConfig, } impl HttpBuilder { /// Create a new HTTP Local server builder pub fn new(client_config: ServerAddr, balancer: PingBalancer) -> Self { let context = ServiceContext::new(); Self::with_context(Arc::new(context), client_config, balancer) } /// Create with an existed context pub fn with_context(context: Arc, client_config: ServerAddr, balancer: PingBalancer) -> Self { Self { context, client_config, balancer, #[cfg(target_os = "macos")] launchd_tcp_socket_name: None, http_auth: HttpAuthConfig::default(), } } #[cfg(target_os = "macos")] pub fn set_launchd_tcp_socket_name(&mut self, n: String) { self.launchd_tcp_socket_name = Some(n); } pub fn set_http_auth(&mut self, auth: HttpAuthConfig) { self.http_auth = auth; } /// Build HTTP server instance pub async fn build(self) -> io::Result { cfg_if::cfg_if! { if #[cfg(target_os = "macos")] { let listener = match self.launchd_tcp_socket_name { Some(launchd_socket_name) => { use tokio::net::TcpListener as TokioTcpListener; use crate::net::launch_activate_socket::get_launch_activate_tcp_listener; let std_listener = get_launch_activate_tcp_listener(&launchd_socket_name, true)?; let tokio_listener = TokioTcpListener::from_std(std_listener)?; TcpListener::from_listener(tokio_listener, self.context.accept_opts())? } _ => { create_standard_tcp_listener(&self.context, &self.client_config).await? } }; } else { let listener = create_standard_tcp_listener(&self.context, &self.client_config).await?; } } // let proxy_client_cache = Arc::new(ProxyClientCache::new(self.context.clone())); Ok(Http { context: self.context, listener, balancer: self.balancer, http_auth: Arc::new(self.http_auth), }) } } /// HTTP Local server pub struct Http { context: Arc, listener: TcpListener, balancer: PingBalancer, http_auth: Arc, } impl Http { /// Server's local address pub fn local_addr(&self) -> io::Result { self.listener.local_addr() } /// Run server pub async fn run(self) -> io::Result<()> { // https://www.ietf.org/rfc/rfc2068.txt // HTTP Proxy is based on HTTP/1.1 info!( "shadowsocks HTTP listening on {}", self.listener.local_addr().expect("http local_addr") ); let handler = HttpConnectionHandler::new(self.context, self.balancer, self.http_auth); loop { let (stream, peer_addr) = match self.listener.accept().await { Ok(s) => s, Err(err) => { error!("failed to accept HTTP clients, err: {}", err); time::sleep(Duration::from_secs(1)).await; continue; } }; trace!("HTTP accepted client from {}", peer_addr); let handler = handler.clone(); tokio::spawn(async move { if let Err(err) = handler.serve_connection(stream, peer_addr).await { error!("HTTP connection {} handler failed with error: {}", peer_addr, err); } }); } } } /// HTTP Proxy handler for `accept()`ed HTTP clients /// /// It should be created once and then `clone()` for every individual TCP connections #[derive(Clone)] pub struct HttpConnectionHandler { context: Arc, balancer: PingBalancer, http_client: HttpClient, http_auth: Arc, } impl HttpConnectionHandler { /// Create a new Handler pub fn new(context: Arc, balancer: PingBalancer, http_auth: Arc) -> Self { Self { context, balancer, http_client: HttpClient::new(), http_auth, } } /// Handle a TCP HTTP connection pub async fn serve_connection(self, stream: S, peer_addr: SocketAddr) -> hyper::Result<()> where S: AsyncRead + AsyncWrite + Unpin + Send + 'static, { let Self { context, balancer, http_client, http_auth, } = self; let io = TokioIo::new(stream); // NOTE: Some stupid clients requires HTTP header keys to be case-sensitive. // For example: Nintendo Switch http1::Builder::new() .keep_alive(true) .title_case_headers(true) .preserve_header_case(true) .serve_connection( io, service::service_fn(move |req| { HttpService::new( context.clone(), peer_addr, http_client.clone(), balancer.clone(), http_auth.clone(), ) .serve_connection(req) }), ) .with_upgrades() .await } } ================================================ FILE: crates/shadowsocks-service/src/local/http/tokio_rt.rs ================================================ use std::{ future::Future, pin::Pin, task::{Context, Poll}, }; use pin_project::pin_project; #[derive(Debug)] #[pin_project] pub struct TokioIo { #[pin] inner: T, } impl TokioIo { pub fn new(inner: T) -> Self { Self { inner } } // pub fn inner(self) -> T { // self.inner // } } impl hyper::rt::Read for TokioIo where T: tokio::io::AsyncRead, { fn poll_read( self: Pin<&mut Self>, cx: &mut Context<'_>, mut buf: hyper::rt::ReadBufCursor<'_>, ) -> Poll> { let n = unsafe { let mut tbuf = tokio::io::ReadBuf::uninit(buf.as_mut()); match tokio::io::AsyncRead::poll_read(self.project().inner, cx, &mut tbuf) { Poll::Ready(Ok(())) => tbuf.filled().len(), other => return other, } }; unsafe { buf.advance(n); } Poll::Ready(Ok(())) } } impl hyper::rt::Write for TokioIo where T: tokio::io::AsyncWrite, { fn poll_write(self: Pin<&mut Self>, cx: &mut Context<'_>, buf: &[u8]) -> Poll> { tokio::io::AsyncWrite::poll_write(self.project().inner, cx, buf) } fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { tokio::io::AsyncWrite::poll_flush(self.project().inner, cx) } fn poll_shutdown(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { tokio::io::AsyncWrite::poll_shutdown(self.project().inner, cx) } fn is_write_vectored(&self) -> bool { tokio::io::AsyncWrite::is_write_vectored(&self.inner) } fn poll_write_vectored( self: Pin<&mut Self>, cx: &mut Context<'_>, bufs: &[std::io::IoSlice<'_>], ) -> Poll> { tokio::io::AsyncWrite::poll_write_vectored(self.project().inner, cx, bufs) } } impl tokio::io::AsyncRead for TokioIo where T: hyper::rt::Read, { fn poll_read( self: Pin<&mut Self>, cx: &mut Context<'_>, tbuf: &mut tokio::io::ReadBuf<'_>, ) -> Poll> { // let init = tbuf.initialized().len(); let filled = tbuf.filled().len(); let sub_filled = unsafe { let mut buf = hyper::rt::ReadBuf::uninit(tbuf.unfilled_mut()); match hyper::rt::Read::poll_read(self.project().inner, cx, buf.unfilled()) { Poll::Ready(Ok(())) => buf.filled().len(), other => return other, } }; let n_filled = filled + sub_filled; // At least sub_filled bytes had to have been initialized. let n_init = sub_filled; unsafe { tbuf.assume_init(n_init); tbuf.set_filled(n_filled); } Poll::Ready(Ok(())) } } impl tokio::io::AsyncWrite for TokioIo where T: hyper::rt::Write, { fn poll_write(self: Pin<&mut Self>, cx: &mut Context<'_>, buf: &[u8]) -> Poll> { hyper::rt::Write::poll_write(self.project().inner, cx, buf) } fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { hyper::rt::Write::poll_flush(self.project().inner, cx) } fn poll_shutdown(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { hyper::rt::Write::poll_shutdown(self.project().inner, cx) } fn is_write_vectored(&self) -> bool { hyper::rt::Write::is_write_vectored(&self.inner) } fn poll_write_vectored( self: Pin<&mut Self>, cx: &mut Context<'_>, bufs: &[std::io::IoSlice<'_>], ) -> Poll> { hyper::rt::Write::poll_write_vectored(self.project().inner, cx, bufs) } } #[derive(Clone)] pub struct TokioExecutor; impl hyper::rt::Executor for TokioExecutor where F: Future + Send + 'static, F::Output: Send + 'static, { fn execute(&self, future: F) { tokio::spawn(future); } } ================================================ FILE: crates/shadowsocks-service/src/local/http/utils.rs ================================================ //! HTTP Utilities use std::{ io, net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr}, sync::Arc, }; use hyper::{ HeaderMap, Uri, Version, header::{self, HeaderValue}, http::uri::Authority, }; use log::error; use shadowsocks::relay::socks5::Address; use crate::local::{ context::ServiceContext, loadbalancing::{PingBalancer, ServerIdent}, net::AutoProxyClientStream, }; pub fn authority_addr(scheme_str: Option<&str>, authority: &Authority) -> Option
{ // RFC7230 indicates that we should ignore userinfo // https://tools.ietf.org/html/rfc7230#section-5.3.3 // Check if URI has port let port = match authority.port_u16() { Some(port) => port, None => { match scheme_str { None => 80, // Assume it is http Some("http") => 80, Some("https") => 443, _ => return None, // Not supported } } }; let host_str = authority.host(); // RFC3986 indicates that IPv6 address should be wrapped in [ and ] // https://tools.ietf.org/html/rfc3986#section-3.2.2 // // Example: [::1] without port if host_str.starts_with('[') && host_str.ends_with(']') { // Must be a IPv6 address let addr = &host_str[1..host_str.len() - 1]; match addr.parse::() { Ok(a) => Some(Address::from(SocketAddr::new(IpAddr::V6(a), port))), // Ignore invalid IPv6 address Err(..) => None, } } else { // It must be a IPv4 address match host_str.parse::() { Ok(a) => Some(Address::from(SocketAddr::new(IpAddr::V4(a), port))), // Should be a domain name, or a invalid IP address. // Let DNS deal with it. Err(..) => Some(Address::DomainNameAddress(host_str.to_owned(), port)), } } } pub fn host_addr(uri: &Uri) -> Option
{ match uri.authority() { None => None, Some(authority) => authority_addr(uri.scheme_str(), authority), } } fn get_keep_alive_val(values: header::GetAll) -> Option { let mut conn_keep_alive = None; for value in values { if let Ok(value) = value.to_str() { if value.eq_ignore_ascii_case("close") { conn_keep_alive = Some(false); } else { for part in value.split(',') { let part = part.trim(); if part.eq_ignore_ascii_case("keep-alive") { conn_keep_alive = Some(true); break; } } } } } conn_keep_alive } pub fn check_keep_alive(version: Version, headers: &HeaderMap, check_proxy: bool) -> bool { // HTTP/1.1, HTTP/2, HTTP/3 keeps alive by default let mut conn_keep_alive = !matches!(version, Version::HTTP_09 | Version::HTTP_10); if check_proxy { // Modern browsers will send Proxy-Connection instead of Connection // for HTTP/1.0 proxies which blindly forward Connection to remote // // https://tools.ietf.org/html/rfc7230#appendix-A.1.2 if let Some(b) = get_keep_alive_val(headers.get_all("Proxy-Connection")) { conn_keep_alive = b } } // Connection will replace Proxy-Connection // // But why client sent both Connection and Proxy-Connection? That's not standard! if let Some(b) = get_keep_alive_val(headers.get_all("Connection")) { conn_keep_alive = b } conn_keep_alive } pub async fn connect_host( context: Arc, host: &Address, balancer: Option<&PingBalancer>, ) -> io::Result<(AutoProxyClientStream, Option>)> { match balancer { None => match AutoProxyClientStream::connect_bypassed(context, host).await { Ok(s) => Ok((s, None)), Err(err) => { error!("failed to connect host {} bypassed, err: {}", host, err); Err(err) } }, Some(balancer) if balancer.is_empty() => match AutoProxyClientStream::connect_bypassed(context, host).await { Ok(s) => Ok((s, None)), Err(err) => { error!("failed to connect host {} bypassed, err: {}", host, err); Err(err) } }, Some(balancer) => { let server = balancer.best_tcp_server(); match AutoProxyClientStream::connect_with_opts(context, server.as_ref(), host, server.connect_opts_ref()) .await { Ok(s) => Ok((s, Some(server))), Err(err) => { error!( "failed to connect host {} proxied, svr_cfg: {}, error: {}", host, server.server_config().addr(), err ); Err(err) } } } } } ================================================ FILE: crates/shadowsocks-service/src/local/loadbalancing/mod.rs ================================================ //! Load balancer pub use self::{ ping_balancer::{PingBalancer, PingBalancerBuilder, ServerType}, server_data::{ServerIdent, ServerScore}, }; pub mod ping_balancer; pub mod server_data; pub mod server_stat; ================================================ FILE: crates/shadowsocks-service/src/local/loadbalancing/ping_balancer.rs ================================================ //! Load Balancer chooses server by statistic latency data collected from active probing use std::{ cmp, fmt::{self, Debug, Display}, io, iter::Iterator, net::{Ipv4Addr, SocketAddr}, sync::{ Arc, atomic::{AtomicUsize, Ordering}, }, time::{Duration, Instant}, }; use arc_swap::ArcSwap; use byte_string::ByteStr; use futures::future; use log::{debug, error, info, trace, warn}; use shadowsocks::{ ServerConfig, config::{Mode, ServerSource}, plugin::{Plugin, PluginMode}, relay::{ socks5::Address, tcprelay::proxy_stream::ProxyClientStream, udprelay::{MAXIMUM_UDP_PAYLOAD_SIZE, options::UdpSocketControlData, proxy_socket::ProxySocket}, }, }; use spin::Mutex as SpinMutex; use tokio::{ io::{AsyncBufReadExt, AsyncWriteExt, BufReader}, sync::Notify, task::JoinHandle, time, }; use crate::{config::ServerInstanceConfig, local::context::ServiceContext}; use super::{ server_data::ServerIdent, server_stat::{DEFAULT_CHECK_INTERVAL_SEC, DEFAULT_CHECK_TIMEOUT_SEC, Score}, }; const EXPECTED_CHECK_POINTS_IN_CHECK_WINDOW: u32 = 67; /// Remote Server Type #[derive(Debug, Clone, Copy)] pub enum ServerType { Tcp, Udp, } impl fmt::Display for ServerType { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { Self::Tcp => f.write_str("TCP"), Self::Udp => f.write_str("UDP"), } } } /// Build a `PingBalancer` pub struct PingBalancerBuilder { servers: Vec>, context: Arc, mode: Mode, max_server_rtt: Duration, check_interval: Duration, check_best_interval: Option, } impl PingBalancerBuilder { pub fn new(context: Arc, mode: Mode) -> Self { Self { servers: Vec::new(), context, mode, max_server_rtt: Duration::from_secs(DEFAULT_CHECK_TIMEOUT_SEC), check_interval: Duration::from_secs(DEFAULT_CHECK_INTERVAL_SEC), check_best_interval: None, } } pub fn add_server(&mut self, server: ServerInstanceConfig) { let ident = ServerIdent::new( self.context.clone(), server, self.max_server_rtt, self.check_interval * EXPECTED_CHECK_POINTS_IN_CHECK_WINDOW, ); self.servers.push(Arc::new(ident)); } pub fn max_server_rtt(&mut self, rtt: Duration) { self.max_server_rtt = rtt; } pub fn check_interval(&mut self, intv: Duration) { self.check_interval = intv; } pub fn check_best_interval(&mut self, intv: Duration) { self.check_best_interval = Some(intv); } fn find_best_idx(servers: &[Arc], mode: Mode) -> (usize, usize) { if servers.is_empty() { trace!("init without any TCP and UDP servers"); return (0, 0); } let mut best_tcp_idx = 0; let mut best_udp_idx = 0; if mode.enable_tcp() { let mut found_tcp_idx = false; for (idx, server) in servers.iter().enumerate() { if PingBalancerContext::check_server_tcp_enabled(server.server_config()) { best_tcp_idx = idx; found_tcp_idx = true; break; } } if !found_tcp_idx { warn!( "no valid TCP server serving for TCP clients, consider disable TCP with \"mode\": \"udp_only\", currently chose {}", ServerConfigFormatter::new(servers[best_tcp_idx].server_config()) ); } else { trace!( "init chose TCP server {}", ServerConfigFormatter::new(servers[best_tcp_idx].server_config()) ); } } if mode.enable_udp() { let mut found_udp_idx = false; for (idx, server) in servers.iter().enumerate() { if PingBalancerContext::check_server_udp_enabled(server.server_config()) { best_udp_idx = idx; found_udp_idx = true; break; } } if !found_udp_idx { warn!( "no valid UDP server serving for UDP clients, consider disable UDP with \"mode\": \"tcp_only\", currently chose {}", ServerConfigFormatter::new(servers[best_udp_idx].server_config()) ); } else { trace!( "init chose UDP server {}", ServerConfigFormatter::new(servers[best_udp_idx].server_config()) ); } } (best_tcp_idx, best_udp_idx) } pub async fn build(self) -> io::Result { if let Some(intv) = self.check_best_interval && intv > self.check_interval { return Err(io::Error::other("check_interval must be >= check_best_interval")); } let (shared_context, task_abortable) = PingBalancerContext::new( self.servers, self.context, self.mode, self.max_server_rtt, self.check_interval, self.check_best_interval, ) .await?; Ok(PingBalancer { inner: Arc::new(PingBalancerInner { context: ArcSwap::new(shared_context), task_abortable: SpinMutex::new(task_abortable), }), }) } } struct PingBalancerContextTask { checker_abortable: JoinHandle<()>, plugin_abortable: Option>, } impl Drop for PingBalancerContextTask { fn drop(&mut self) { self.checker_abortable.abort(); if let Some(ref p) = self.plugin_abortable { p.abort(); } } } struct PingBalancerContext { servers: Vec>, best_tcp_idx: AtomicUsize, best_udp_idx: AtomicUsize, context: Arc, mode: Mode, max_server_rtt: Duration, check_interval: Duration, check_best_interval: Option, best_task_notify: Notify, } impl PingBalancerContext { fn best_tcp_server(&self) -> Arc { assert!(!self.is_empty(), "no available server"); self.servers[self.best_tcp_idx.load(Ordering::Relaxed)].clone() } fn best_udp_server(&self) -> Arc { assert!(!self.is_empty(), "no available server"); self.servers[self.best_udp_idx.load(Ordering::Relaxed)].clone() } #[inline] fn is_empty(&self) -> bool { self.servers.is_empty() } } impl PingBalancerContext { pub(crate) async fn new( mut servers: Vec>, context: Arc, mode: Mode, max_server_rtt: Duration, check_interval: Duration, check_best_interval: Option, ) -> io::Result<(Arc, PingBalancerContextTask)> { let plugin_abortable = { // Start plugins for TCP proxies let mut plugins = Vec::with_capacity(servers.len()); for server in &mut servers { let server = Arc::get_mut(server).unwrap(); let svr_cfg = server.server_config_mut(); if let Some(p) = svr_cfg.plugin() { // Start Plugin Process let plugin = Plugin::start(p, svr_cfg.addr(), PluginMode::Client)?; svr_cfg.set_plugin_addr(plugin.local_addr().into()); plugins.push(plugin); } } if plugins.is_empty() { None } else { // Load balancer will check all servers' score before server's actual start. // So we have to ensure all plugins have been started before that. let mut check_fut = Vec::with_capacity(plugins.len()); for plugin in &plugins { // 3 seconds is not a carefully selected value // I choose that because any values bigger will make me felt too long. check_fut.push(plugin.wait_started(Duration::from_secs(3))); } // Run all of them simultaneously let _ = future::join_all(check_fut).await; let plugin_abortable = tokio::spawn(async move { let mut vfut = Vec::with_capacity(plugins.len()); for plugin in plugins { vfut.push(async move { match plugin.join().await { Ok(status) => { error!("plugin exited with status: {}", status); Ok(()) } Err(err) => { error!("plugin exited with error: {}", err); Err(err) } } }); } let _ = future::join_all(vfut).await; panic!("all plugins are exited. all connections may fail, check your configuration"); }); Some(plugin_abortable) } }; let (best_tcp_idx, best_udp_idx) = PingBalancerBuilder::find_best_idx(&servers, mode); let balancer_context = Self { servers, best_tcp_idx: AtomicUsize::new(best_tcp_idx), best_udp_idx: AtomicUsize::new(best_udp_idx), context, mode, max_server_rtt, check_interval, check_best_interval, best_task_notify: Notify::new(), }; balancer_context.init_score().await; let shared_context = Arc::new(balancer_context); let checker_abortable = { let shared_context = shared_context.clone(); tokio::spawn(async move { shared_context.checker_task().await }) }; Ok(( shared_context, PingBalancerContextTask { checker_abortable, plugin_abortable, }, )) } async fn init_score(&self) { if self.servers.is_empty() { return; } self.check_once(true).await; } fn check_server_tcp_enabled(svr_cfg: &ServerConfig) -> bool { svr_cfg.mode().enable_tcp() && svr_cfg.weight().tcp_weight() > 0.0 } fn check_server_udp_enabled(svr_cfg: &ServerConfig) -> bool { svr_cfg.mode().enable_udp() && svr_cfg.weight().udp_weight() > 0.0 } fn probing_required(&self) -> bool { if self.servers.is_empty() { return false; } let mut tcp_count = 0; let mut udp_count = 0; for server in self.servers.iter() { let svr_cfg = server.server_config(); if self.mode.enable_tcp() && Self::check_server_tcp_enabled(svr_cfg) { tcp_count += 1; } if self.mode.enable_udp() && Self::check_server_udp_enabled(svr_cfg) { udp_count += 1; } } tcp_count > 1 || udp_count > 1 } async fn checker_task(self: Arc) { if !self.probing_required() { self.checker_task_dummy().await } else { self.checker_task_real().await } } /// Dummy task that will do nothing if there only have one server in the balancer async fn checker_task_dummy(self: Arc) { future::pending().await } /// Check each servers' score and update the best server's index async fn check_once(&self, first_run: bool) { let servers = &self.servers; if servers.is_empty() { return; } let mut vfut_tcp = Vec::with_capacity(servers.len()); let mut vfut_udp = Vec::with_capacity(servers.len()); for server in servers.iter() { let svr_cfg = server.server_config(); if self.mode.enable_tcp() && Self::check_server_tcp_enabled(svr_cfg) { let checker = PingChecker { server: server.clone(), server_type: ServerType::Tcp, context: self.context.clone(), max_server_rtt: self.max_server_rtt, }; vfut_tcp.push(checker.check_update_score()); } if self.mode.enable_udp() && Self::check_server_udp_enabled(svr_cfg) { let checker = PingChecker { server: server.clone(), server_type: ServerType::Udp, context: self.context.clone(), max_server_rtt: self.max_server_rtt, }; vfut_udp.push(checker.check_update_score()); } } let check_tcp = vfut_tcp.len() > 1; let check_udp = vfut_udp.len() > 1; if !check_tcp && !check_udp { return; } let vfut = if !check_tcp { vfut_udp } else if !check_udp { vfut_tcp } else { vfut_tcp.append(&mut vfut_udp); vfut_tcp }; future::join_all(vfut).await; if self.mode.enable_tcp() && check_tcp { let old_best_idx = self.best_tcp_idx.load(Ordering::Acquire); let mut best_idx = 0; let mut best_score = u32::MAX; for (idx, server) in servers.iter().enumerate() { let score = server.tcp_score().score(); if score < best_score { best_idx = idx; best_score = score; } } self.best_tcp_idx.store(best_idx, Ordering::Release); if first_run { info!( "chose best TCP server {}", ServerConfigFormatter::new(servers[best_idx].server_config()) ); } else if best_idx != old_best_idx { info!( "switched best TCP server from {} to {}", ServerConfigFormatter::new(servers[old_best_idx].server_config()), ServerConfigFormatter::new(servers[best_idx].server_config()) ); } else { debug!( "kept best TCP server {}", ServerConfigFormatter::new(servers[old_best_idx].server_config()) ); } } if self.mode.enable_udp() && check_udp { let old_best_idx = self.best_udp_idx.load(Ordering::Acquire); let mut best_idx = 0; let mut best_score = u32::MAX; for (idx, server) in servers.iter().enumerate() { let score = server.udp_score().score(); if score < best_score { best_idx = idx; best_score = score; } } self.best_udp_idx.store(best_idx, Ordering::Release); if first_run { info!( "chose best UDP server {}", ServerConfigFormatter::new(servers[best_idx].server_config()) ); } else if best_idx != old_best_idx { info!( "switched best UDP server from {} to {}", ServerConfigFormatter::new(servers[old_best_idx].server_config()), ServerConfigFormatter::new(servers[best_idx].server_config()) ); } else { debug!( "kept best UDP server {}", ServerConfigFormatter::new(servers[old_best_idx].server_config()) ); } } } /// Check the best server only async fn check_best_server(&self) { let servers = &self.servers; if servers.is_empty() { return; } let mut vfut = Vec::new(); let best_tcp_idx = self.best_tcp_idx.load(Ordering::Acquire); let best_udp_idx = self.best_udp_idx.load(Ordering::Acquire); let best_tcp_server = &servers[best_tcp_idx]; let best_tcp_svr_cfg = best_tcp_server.server_config(); let best_udp_server = &servers[best_udp_idx]; let best_udp_svr_cfg = best_udp_server.server_config(); let mut check_tcp = false; let mut check_udp = false; if self.mode.enable_tcp() && Self::check_server_tcp_enabled(best_tcp_svr_cfg) { let checker = PingChecker { server: best_tcp_server.clone(), server_type: ServerType::Tcp, context: self.context.clone(), max_server_rtt: self.max_server_rtt, }; vfut.push(checker.check_update_score()); check_tcp = true; } if self.mode.enable_udp() && Self::check_server_udp_enabled(best_udp_svr_cfg) { let checker = PingChecker { server: best_udp_server.clone(), server_type: ServerType::Udp, context: self.context.clone(), max_server_rtt: self.max_server_rtt, }; vfut.push(checker.check_update_score()); check_udp = true; } future::join_all(vfut).await; if self.mode.enable_tcp() && check_tcp { let old_best_idx = self.best_tcp_idx.load(Ordering::Acquire); let mut best_idx = 0; let mut best_score = u32::MAX; for (idx, server) in servers.iter().enumerate() { let score = server.tcp_score().score(); if score < best_score { best_idx = idx; best_score = score; } } self.best_tcp_idx.store(best_idx, Ordering::Release); if best_idx != old_best_idx { info!( "switched best TCP server from {} to {} (best check)", ServerConfigFormatter::new(servers[old_best_idx].server_config()), ServerConfigFormatter::new(servers[best_idx].server_config()) ); } else { debug!( "kept best TCP server {} (best check)", ServerConfigFormatter::new(servers[old_best_idx].server_config()) ); } } if self.mode.enable_udp() && check_udp { let old_best_idx = self.best_udp_idx.load(Ordering::Acquire); let mut best_idx = 0; let mut best_score = u32::MAX; for (idx, server) in servers.iter().enumerate() { let score = server.udp_score().score(); if score < best_score { best_idx = idx; best_score = score; } } self.best_udp_idx.store(best_idx, Ordering::Release); if best_idx != old_best_idx { info!( "switched best UDP server from {} to {} (best check)", ServerConfigFormatter::new(servers[old_best_idx].server_config()), ServerConfigFormatter::new(servers[best_idx].server_config()) ); } else { debug!( "kept best UDP server {} (best check)", ServerConfigFormatter::new(servers[old_best_idx].server_config()) ); } } } async fn checker_task_real(&self) { if self.check_best_interval.is_none() { return self.checker_task_all_servers().await; } let best = self.checker_task_best_server(); let all = self.checker_task_all_servers(); futures::join!(best, all); } async fn checker_task_all_servers(&self) { if let Some(check_best_interval) = self.check_best_interval { // Get at least 10 points to get the precise scores let interval = cmp::min(check_best_interval, self.check_interval); let mut count = 0; while count < EXPECTED_CHECK_POINTS_IN_CHECK_WINDOW { time::sleep(interval).await; // Sleep before check. // PingBalancer already checked once when constructing self.check_once(false).await; count += 1; } self.best_task_notify.notify_one(); trace!("finished initializing server scores"); } loop { time::sleep(self.check_interval).await; // Sleep before check. // PingBalancer already checked once when constructing self.check_once(false).await; } } async fn checker_task_best_server(&self) { // Wait until checker_task_all_servers notify. // Because when server starts, the scores are unstable, so we have to run check_all for multiple times self.best_task_notify.notified().await; let check_best_interval = self.check_best_interval.unwrap(); loop { time::sleep(check_best_interval).await; // Sleep before check. // PingBalancer already checked once when constructing self.check_best_server().await; } } } struct PingBalancerInner { context: ArcSwap, task_abortable: SpinMutex, } impl Drop for PingBalancerInner { fn drop(&mut self) { trace!("ping balancer stopped"); } } /// Balancer with active probing #[derive(Clone)] pub struct PingBalancer { inner: Arc, } impl PingBalancer { /// Get service context pub fn context(&self) -> Arc { let context = self.inner.context.load(); context.context.clone() } /// Pick the best TCP server pub fn best_tcp_server(&self) -> Arc { let context = self.inner.context.load(); context.best_tcp_server() } /// Pick the best UDP server pub fn best_udp_server(&self) -> Arc { let context = self.inner.context.load(); context.best_udp_server() } /// Check if there is no available server #[inline] pub fn is_empty(&self) -> bool { let context = self.inner.context.load(); context.is_empty() } /// Get the server list pub fn servers(&self) -> PingServerIter<'_> { let context = self.inner.context.load(); let servers: &Vec> = unsafe { &*(&context.servers as *const _) }; PingServerIter { context: context.clone(), iter: servers.iter(), } } /// Reset servers in load balancer. Designed for auto-reloading configuration file. pub async fn reset_servers( &self, servers: Vec, replace_server_sources: &[ServerSource], ) -> io::Result<()> { let old_context = self.inner.context.load(); let mut old_servers = old_context.servers.clone(); let mut idx = 0; while idx < old_servers.len() { let source_match = replace_server_sources .iter() .any(|src| *src == old_servers[idx].server_config().source()); if source_match { old_servers.swap_remove(idx); } else { idx += 1; } } trace!( "ping balancer going to replace {} servers (total: {}) with {} servers, sources: {:?}", old_context.servers.len() - old_servers.len(), old_context.servers.len(), servers.len(), replace_server_sources ); let mut servers = servers .into_iter() .map(|s| { Arc::new(ServerIdent::new( old_context.context.clone(), s, old_context.max_server_rtt, old_context.check_interval * EXPECTED_CHECK_POINTS_IN_CHECK_WINDOW, )) }) .collect::>>(); // Recreate a new instance for old servers (old server instance may still being held by clients) for old_server in old_servers { servers.push(Arc::new(ServerIdent::new( old_context.context.clone(), old_server.server_instance_config().clone(), old_context.max_server_rtt, old_context.check_interval * EXPECTED_CHECK_POINTS_IN_CHECK_WINDOW, ))); } trace!("ping balancer merged {} new servers", servers.len()); let (shared_context, task_abortable) = PingBalancerContext::new( servers, old_context.context.clone(), old_context.mode, old_context.max_server_rtt, old_context.check_interval, old_context.check_best_interval, ) .await?; { // Stop the previous task and replace with the new task let mut abortable = self.inner.task_abortable.lock(); *abortable = task_abortable; } // Replace with the new context self.inner.context.store(shared_context); Ok(()) } } impl Debug for PingBalancer { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let context = self.inner.context.load(); f.debug_struct("PingBalancer") .field("servers", &context.servers) .field("best_tcp_idx", &context.best_tcp_idx.load(Ordering::Relaxed)) .field("best_udp_idx", &context.best_udp_idx.load(Ordering::Relaxed)) .finish() } } struct PingChecker { server: Arc, server_type: ServerType, context: Arc, max_server_rtt: Duration, } impl PingChecker { /// Checks server's score and update into `ServerScore` async fn check_update_score(self) { let server_score = match self.server_type { ServerType::Tcp => self.server.tcp_score(), ServerType::Udp => self.server.udp_score(), }; let (score, stat_data) = match self.check_delay().await { Ok(d) => server_score.push_score_fetch_statistic(Score::Latency(d)).await, // Penalty Err(..) => server_score.push_score_fetch_statistic(Score::Errored).await, }; if stat_data.fail_rate > 0.8 { warn!( "balancer: checked & updated remote {} server {} (score: {}), {:?}", self.server_type, ServerConfigFormatter::new(self.server.server_config()), score, stat_data, ); } else { debug!( "balancer: checked & updated remote {} server {} (score: {}), {:?}", self.server_type, ServerConfigFormatter::new(self.server.server_config()), score, stat_data, ); } } /// Detect TCP connectivity with Chromium [Network Portal Detection](https://www.chromium.org/chromium-os/chromiumos-design-docs/network-portal-detection) #[allow(dead_code)] async fn check_request_tcp_chromium(&self) -> io::Result<()> { use std::io::{Error, ErrorKind}; const GET_BODY: &[u8] = b"GET /generate_204 HTTP/1.1\r\nHost: clients3.google.com\r\nConnection: close\r\nAccept: */*\r\n\r\n"; let addr = Address::DomainNameAddress("clients3.google.com".to_owned(), 80); let mut stream = ProxyClientStream::connect_with_opts( self.context.context(), self.server.server_config(), &addr, self.server.connect_opts_ref(), ) .await?; stream.write_all(GET_BODY).await?; let mut reader = BufReader::new(stream); let mut buf = Vec::new(); reader.read_until(b'\n', &mut buf).await?; let mut headers = [httparse::EMPTY_HEADER; 1]; let mut response = httparse::Response::new(&mut headers); if response.parse(&buf).is_ok() && matches!(response.code, Some(204)) { return Ok(()); } Err(Error::new( ErrorKind::InvalidData, format!( "unexpected response from http://clients3.google.com/generate_204, {:?}", ByteStr::new(&buf) ), )) } /// Detect TCP connectivity with Firefox's http://detectportal.firefox.com/success.txt async fn check_request_tcp_firefox(&self) -> io::Result<()> { use std::io::{Error, ErrorKind}; const GET_BODY: &[u8] = b"GET /success.txt HTTP/1.1\r\nHost: detectportal.firefox.com\r\nConnection: close\r\nAccept: */*\r\n\r\n"; let addr = Address::DomainNameAddress("detectportal.firefox.com".to_owned(), 80); let mut stream = ProxyClientStream::connect_with_opts( self.context.context(), self.server.server_config(), &addr, self.server.connect_opts_ref(), ) .await?; stream.write_all(GET_BODY).await?; let mut reader = BufReader::new(stream); let mut buf = Vec::new(); reader.read_until(b'\n', &mut buf).await?; let mut headers = [httparse::EMPTY_HEADER; 1]; let mut response = httparse::Response::new(&mut headers); if response.parse(&buf).is_ok() && matches!(response.code, Some(200) | Some(204)) { return Ok(()); } Err(Error::new( ErrorKind::InvalidData, format!( "unexpected response from http://detectportal.firefox.com/success.txt, {:?}", ByteStr::new(&buf) ), )) } async fn check_request_udp(&self) -> io::Result<()> { // TransactionID: 0x1234 // Flags: 0x0100 RD // Questions: 0x0001 // Answer RRs: 0x0000 // Authority RRs: 0x0000 // Additional RRs: 0x0000 // Queries // - QNAME: \x07 firefox \x03 com \x00 // - QTYPE: 0x0001 A // - QCLASS: 0x0001 IN const DNS_QUERY: &[u8] = b"\x12\x34\x01\x00\x00\x01\x00\x00\x00\x00\x00\x00\x07firefox\x03com\x00\x00\x01\x00\x01"; let addr = Address::SocketAddress(SocketAddr::new(Ipv4Addr::new(8, 8, 8, 8).into(), 53)); let client = ProxySocket::connect_with_opts( self.context.context(), self.server.server_config(), self.server.connect_opts_ref(), ) .await?; let mut control = UdpSocketControlData::default(); control.client_session_id = rand::random::(); control.packet_id = 1; client.send_with_ctrl(&addr, &control, DNS_QUERY).await?; let mut buffer = [0u8; MAXIMUM_UDP_PAYLOAD_SIZE]; let (n, ..) = client.recv(&mut buffer).await?; let dns_answer = &buffer[..n]; // DNS packet must have at least 6 * 2 bytes if dns_answer.len() < 12 || &dns_answer[0..2] != b"\x12\x34" { use std::io::{Error, ErrorKind}; debug!("unexpected response from 8.8.8.8:53, {:?}", ByteStr::new(dns_answer)); let err = Error::new(ErrorKind::InvalidData, "unexpected response from 8.8.8.8:53"); return Err(err); } Ok(()) } async fn check_request(&self) -> io::Result<()> { match self.server_type { ServerType::Tcp => self.check_request_tcp_firefox().await, ServerType::Udp => self.check_request_udp().await, } } async fn check_delay(&self) -> io::Result { let start = Instant::now(); // Send HTTP GET and read the first byte let res = time::timeout(self.max_server_rtt, self.check_request()).await; let elapsed = Instant::now() - start; let elapsed = elapsed.as_secs() as u32 * 1000 + elapsed.subsec_millis(); // Converted to ms match res { Ok(Ok(..)) => { // Got the result ... record its time trace!( "checked remote {} server {} latency with {} ms", self.server_type, ServerConfigFormatter::new(self.server.server_config()), elapsed ); Ok(elapsed) } Ok(Err(err)) => { debug!( "failed to check {} server {}, error: {}", self.server_type, ServerConfigFormatter::new(self.server.server_config()), err ); // NOTE: connection / handshake error, server is down Err(err) } Err(..) => { use std::io::ErrorKind; // Timeout trace!( "checked remote {} server {} latency timeout, elapsed {} ms", self.server_type, ServerConfigFormatter::new(self.server.server_config()), elapsed ); // NOTE: timeout exceeded. Count as error. Err(ErrorKind::TimedOut.into()) } } } } struct ServerConfigFormatter<'a> { server_config: &'a ServerConfig, } impl<'a> ServerConfigFormatter<'a> { fn new(server_config: &'a ServerConfig) -> Self { ServerConfigFormatter { server_config } } } impl Display for ServerConfigFormatter<'_> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self.server_config.remarks() { None => Display::fmt(self.server_config.addr(), f), Some(remarks) => { if remarks.is_empty() { Display::fmt(self.server_config.addr(), f) } else { write!(f, "{} ({})", self.server_config.addr(), remarks) } } } } } /// Server Iterator pub struct PingServerIter<'a> { #[allow(dead_code)] context: Arc, iter: std::slice::Iter<'a, Arc>, } impl<'a> Iterator for PingServerIter<'a> { type Item = &'a ServerIdent; fn next(&mut self) -> Option { self.iter.next().map(AsRef::as_ref) } } ================================================ FILE: crates/shadowsocks-service/src/local/loadbalancing/server_data.rs ================================================ //! Identifier of server use std::{ fmt::{self, Debug}, net::SocketAddr, sync::{ Arc, atomic::{AtomicU32, Ordering}, }, time::Duration, }; use shadowsocks::{ServerConfig, net::ConnectOpts}; use tokio::sync::Mutex; use crate::{config::ServerInstanceConfig, local::context::ServiceContext}; use super::server_stat::{Score, ServerStat, ServerStatData}; /// Server's statistic score pub struct ServerScore { stat_data: Mutex, score: AtomicU32, } impl ServerScore { /// Create a `ServerScore` pub fn new(user_weight: f32, max_server_rtt: Duration, check_window: Duration) -> Self { let max_server_rtt = max_server_rtt.as_millis() as u32; assert!(max_server_rtt > 0); Self { stat_data: Mutex::new(ServerStat::new(user_weight, max_server_rtt, check_window)), score: AtomicU32::new(u32::MAX), } } /// Get server's current statistic scores pub fn score(&self) -> u32 { self.score.load(Ordering::Acquire) } /// Append a `Score` into statistic and recalculate score of the server pub async fn push_score(&self, score: Score) -> u32 { let updated_score = { let mut stat = self.stat_data.lock().await; stat.push_score(score) }; self.score.store(updated_score, Ordering::Release); updated_score } /// Append a `Score` into statistic and recalculate score of the server pub async fn push_score_fetch_statistic(&self, score: Score) -> (u32, ServerStatData) { let (updated_score, data) = { let mut stat = self.stat_data.lock().await; (stat.push_score(score), *stat.data()) }; self.score.store(updated_score, Ordering::Release); (updated_score, data) } /// Report request failure of this server, which will eventually records an `Errored` score pub async fn report_failure(&self) -> u32 { self.push_score(Score::Errored).await } /// Get statistic data pub async fn stat_data(&self) -> ServerStatData { *self.stat_data.lock().await.data() } } impl Debug for ServerScore { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("ServerScore").field("score", &self.score()).finish() } } /// Identifier for a server #[derive(Debug)] pub struct ServerIdent { tcp_score: ServerScore, udp_score: ServerScore, svr_cfg: ServerInstanceConfig, connect_opts: ConnectOpts, } impl ServerIdent { /// Create a `ServerIdent` pub fn new( context: Arc, svr_cfg: ServerInstanceConfig, max_server_rtt: Duration, check_window: Duration, ) -> Self { let mut connect_opts = context.connect_opts_ref().clone(); #[cfg(any(target_os = "linux", target_os = "android"))] if let Some(fwmark) = svr_cfg.outbound_fwmark { connect_opts.fwmark = Some(fwmark); } #[cfg(target_os = "freebsd")] if let Some(user_cookie) = svr_cfg.outbound_user_cookie { connect_opts.user_cookie = Some(user_cookie); } if let Some(bind_local_addr) = svr_cfg.outbound_bind_addr { connect_opts.bind_local_addr = Some(SocketAddr::new(bind_local_addr, 0)); } if let Some(ref bind_interface) = svr_cfg.outbound_bind_interface { connect_opts.bind_interface = Some(bind_interface.clone()); } Self { tcp_score: ServerScore::new(svr_cfg.config.weight().tcp_weight(), max_server_rtt, check_window), udp_score: ServerScore::new(svr_cfg.config.weight().udp_weight(), max_server_rtt, check_window), svr_cfg, connect_opts, } } pub fn connect_opts_ref(&self) -> &ConnectOpts { &self.connect_opts } pub fn server_config(&self) -> &ServerConfig { &self.svr_cfg.config } pub fn server_config_mut(&mut self) -> &mut ServerConfig { &mut self.svr_cfg.config } pub fn server_instance_config(&self) -> &ServerInstanceConfig { &self.svr_cfg } pub fn tcp_score(&self) -> &ServerScore { &self.tcp_score } pub fn udp_score(&self) -> &ServerScore { &self.udp_score } } ================================================ FILE: crates/shadowsocks-service/src/local/loadbalancing/server_stat.rs ================================================ //! Server latency statistic use std::{ collections::VecDeque, time::{Duration, Instant}, }; /// Interval between each check pub const DEFAULT_CHECK_INTERVAL_SEC: u64 = 10; /// Timeout of each check pub const DEFAULT_CHECK_TIMEOUT_SEC: u64 = 5; // A common connection timeout of 5 seconds. /// Statistic score #[derive(Debug, Copy, Clone)] pub enum Score { /// Unified latency Latency(u32), /// Request error Errored, } /// Server statistic data #[derive(Debug, Clone, Copy)] pub struct ServerStatData { /// Median of latency time (in millisec) /// /// Use median instead of average time, /// because probing result may have some really bad cases pub latency_median: u32, /// Total_Fail / Total_Probe pub fail_rate: f64, /// Score's standard deviation pub latency_stdev: f64, /// Score's average pub latency_mean: f64, /// Score's median absolute deviation pub latency_mad: u32, } /// Statistic of a remote server #[derive(Debug)] pub struct ServerStat { /// MAX server's RTT, normally the check timeout milliseconds max_server_rtt: u32, /// Recently probe data latency_queue: VecDeque<(Score, Instant)>, /// Score's standard deviation MAX max_latency_stdev: f64, /// User's customized weight user_weight: f32, /// Checking window size check_window: Duration, /// Statistic Data data: ServerStatData, } fn max_latency_stdev(max_server_rtt: u32) -> f64 { let mrtt = max_server_rtt as f64; let avg = (0.0 + mrtt) / 2.0; let diff1 = (0.0 - avg) * (0.0 - avg); let diff2 = (mrtt - avg) * (mrtt - avg); // (1.0 / (2.0 - 1.0)) * (diff1 + diff2).sqrt() (diff1 + diff2).sqrt() } impl ServerStat { pub fn new(user_weight: f32, max_server_rtt: u32, check_window: Duration) -> Self { assert!((0.0..=1.0).contains(&user_weight)); let max_latency_stdev = max_latency_stdev(max_server_rtt); Self { max_server_rtt, latency_queue: VecDeque::new(), max_latency_stdev, user_weight, check_window, data: ServerStatData { latency_median: max_server_rtt, fail_rate: 1.0, latency_stdev: max_latency_stdev, latency_mean: max_server_rtt as f64, latency_mad: max_server_rtt, }, } } fn score(&self) -> u32 { // Normalize rtt let nrtt = self.data.latency_median as f64 / self.max_server_rtt as f64; // Normalize stdev // let nstdev = self.data.latency_stdev / self.max_latency_stdev; // Normalize mad let nmad = self.data.latency_mad as f64 / self.max_server_rtt as f64; const SCORE_RTT_WEIGHT: f64 = 1.0; const SCORE_FAIL_WEIGHT: f64 = 3.0; // const SCORE_STDEV_WEIGHT: f64 = 0.0; const SCORE_MAD_WEIGHT: f64 = 1.0; // [EPSILON, 1] // Just for avoiding divide by 0 let user_weight = self.user_weight.max(f32::EPSILON); // Score = (norm_lat * 1.0 + prop_err * 3.0 + (stdev || mad) * 1.0) / 5.0 / user_weight // // 1. The lower latency, the better // 2. The lower errored count, the better // 3. The lower latency's stdev / mad, the better // 4. The higher user's weight, the better let score = (nrtt * SCORE_RTT_WEIGHT + self.data.fail_rate * SCORE_FAIL_WEIGHT + nmad * SCORE_MAD_WEIGHT) / (SCORE_RTT_WEIGHT + SCORE_FAIL_WEIGHT + SCORE_MAD_WEIGHT) / user_weight as f64; // Times 10000 converts to u32, for 0.0001 precision (score * 10000.0) as u32 } pub fn push_score(&mut self, score: Score) -> u32 { let now = Instant::now(); self.latency_queue.push_back((score, now)); // Removes stats that are not in the check window while let Some((_, inst)) = self.latency_queue.front() { if now - *inst > self.check_window { self.latency_queue.pop_front(); } else { break; } } self.recalculate_score() } fn recalculate_score(&mut self) -> u32 { if self.latency_queue.is_empty() { return self.score(); } let mut vlat = Vec::with_capacity(self.latency_queue.len()); let mut cerr = 0; for (s, _) in &self.latency_queue { match *s { Score::Errored => cerr += 1, Score::Latency(lat) => vlat.push(lat), } } // Error rate self.data.fail_rate = cerr as f64 / self.latency_queue.len() as f64; self.data.latency_median = self.max_server_rtt; self.data.latency_stdev = self.max_latency_stdev; self.data.latency_mean = self.max_server_rtt as f64; self.data.latency_mad = self.max_server_rtt; if !vlat.is_empty() { vlat.sort_unstable(); // Find median of latency let mid = vlat.len() / 2; self.data.latency_median = if vlat.len() % 2 == 0 { (vlat[mid] + vlat[mid - 1]) / 2 } else { vlat[mid] }; if vlat.len() > 1 { let n = vlat.len() as f64; // mean let total_lat: u32 = vlat.iter().sum(); self.data.latency_mean = total_lat as f64 / n; // STDEV let acc_mean_diff_square: f64 = vlat .iter() .map(|s| { let diff = *s as f64 - self.data.latency_mean; diff * diff }) .sum(); // Corrected Sample Standard Deviation self.data.latency_stdev = (acc_mean_diff_square / (n - 1.0)).sqrt(); // MAD let mut vlat_abs_diff: Vec = vlat .iter() .map(|s| (*s as i32 - self.data.latency_median as i32).unsigned_abs()) .collect(); vlat_abs_diff.sort_unstable(); let abs_diff_median_mid = vlat_abs_diff.len() / 2; self.data.latency_mad = if vlat_abs_diff.len().is_multiple_of(2) { (vlat_abs_diff[abs_diff_median_mid] + vlat_abs_diff[abs_diff_median_mid - 1]) / 2 } else { vlat_abs_diff[abs_diff_median_mid] }; } else { self.data.latency_mean = vlat[0] as f64; self.data.latency_mad = 0; } } self.score() } pub fn data(&self) -> &ServerStatData { &self.data } } ================================================ FILE: crates/shadowsocks-service/src/local/mod.rs ================================================ //! Shadowsocks Local Server use std::{io, net::SocketAddr, sync::Arc, time::Duration}; use futures::future; use log::trace; use shadowsocks::{ config::Mode, net::{AcceptOpts, ConnectOpts}, }; #[cfg(feature = "local-flow-stat")] use crate::{config::LocalFlowStatAddress, net::FlowStat}; use crate::{ config::{Config, ConfigType, ProtocolType}, dns::build_dns_resolver, utils::ServerHandle, }; use self::{ context::ServiceContext, loadbalancing::{PingBalancer, PingBalancerBuilder}, }; #[cfg(feature = "local-dns")] use self::dns::{Dns, DnsBuilder}; #[cfg(feature = "local-fake-dns")] use self::fake_dns::{FakeDns, FakeDnsBuilder}; #[cfg(feature = "local-http")] use self::http::{Http, HttpBuilder}; #[cfg(feature = "local-online-config")] use self::online_config::{OnlineConfigService, OnlineConfigServiceBuilder}; #[cfg(feature = "local-redir")] use self::redir::{Redir, RedirBuilder}; use self::socks::{Socks, SocksBuilder}; #[cfg(feature = "local-tun")] use self::tun::{Tun, TunBuilder}; #[cfg(feature = "local-tunnel")] use self::tunnel::{Tunnel, TunnelBuilder}; pub mod context; #[cfg(feature = "local-dns")] pub mod dns; #[cfg(feature = "local-fake-dns")] pub mod fake_dns; #[cfg(feature = "local-http")] pub mod http; pub mod loadbalancing; pub mod net; #[cfg(feature = "local-online-config")] pub mod online_config; #[cfg(feature = "local-redir")] pub mod redir; pub mod socks; #[cfg(feature = "local-tun")] pub mod tun; #[cfg(feature = "local-tunnel")] pub mod tunnel; pub mod utils; /// Default TCP Keep Alive timeout /// /// This is borrowed from Go's `net` library's default setting pub(crate) const LOCAL_DEFAULT_KEEPALIVE_TIMEOUT: Duration = Duration::from_secs(15); /// Local Server instance pub struct Server { balancer: PingBalancer, socks_servers: Vec, #[cfg(feature = "local-tunnel")] tunnel_servers: Vec, #[cfg(feature = "local-http")] http_servers: Vec, #[cfg(feature = "local-tun")] tun_servers: Vec, #[cfg(feature = "local-dns")] dns_servers: Vec, #[cfg(feature = "local-redir")] redir_servers: Vec, #[cfg(feature = "local-fake-dns")] fake_dns_servers: Vec, #[cfg(feature = "local-flow-stat")] local_stat_addr: Option, #[cfg(feature = "local-flow-stat")] flow_stat: Arc, #[cfg(feature = "local-online-config")] online_config: Option, } impl Server { /// Create a shadowsocks local server pub async fn new(config: Config) -> io::Result { assert!(config.config_type == ConfigType::Local && !config.local.is_empty()); trace!("{:?}", config); // Warning for Stream Ciphers // NOTE: This will only check servers in config. #[cfg(feature = "stream-cipher")] for inst in config.server.iter() { let server = &inst.config; if server.method().is_stream() { log::warn!( "stream cipher {} for server {} have inherent weaknesses (see discussion in https://github.com/shadowsocks/shadowsocks-org/issues/36). \ DO NOT USE. It will be removed in the future.", server.method(), server.addr() ); } } #[cfg(all(unix, not(target_os = "android")))] if let Some(nofile) = config.nofile { use crate::sys::set_nofile; if let Err(err) = set_nofile(nofile) { log::warn!("set_nofile {} failed, error: {}", nofile, err); } } // Global ServiceContext template // Each Local instance will hold a copy of its fields let mut context = ServiceContext::new(); let mut connect_opts = ConnectOpts { #[cfg(any(target_os = "linux", target_os = "android"))] fwmark: config.outbound_fwmark, #[cfg(target_os = "freebsd")] user_cookie: config.outbound_user_cookie, #[cfg(target_os = "android")] vpn_protect_path: config.outbound_vpn_protect_path, bind_interface: config.outbound_bind_interface, bind_local_addr: config.outbound_bind_addr.map(|ip| SocketAddr::new(ip, 0)), ..Default::default() }; connect_opts.tcp.send_buffer_size = config.outbound_send_buffer_size; connect_opts.tcp.recv_buffer_size = config.outbound_recv_buffer_size; connect_opts.tcp.nodelay = config.no_delay; connect_opts.tcp.fastopen = config.fast_open; connect_opts.tcp.keepalive = config.keep_alive.or(Some(LOCAL_DEFAULT_KEEPALIVE_TIMEOUT)); connect_opts.tcp.mptcp = config.mptcp; connect_opts.udp.mtu = config.udp_mtu; connect_opts.udp.allow_fragmentation = config.outbound_udp_allow_fragmentation; context.set_connect_opts(connect_opts); let mut accept_opts = AcceptOpts { ipv6_only: config.ipv6_only, ..Default::default() }; accept_opts.tcp.send_buffer_size = config.inbound_send_buffer_size; accept_opts.tcp.recv_buffer_size = config.inbound_recv_buffer_size; accept_opts.tcp.nodelay = config.no_delay; accept_opts.tcp.fastopen = config.fast_open; accept_opts.tcp.keepalive = config.keep_alive.or(Some(LOCAL_DEFAULT_KEEPALIVE_TIMEOUT)); accept_opts.tcp.mptcp = config.mptcp; accept_opts.udp.mtu = config.udp_mtu; context.set_accept_opts(accept_opts); if let Some(resolver) = build_dns_resolver( config.dns, config.ipv6_first, config.dns_cache_size, context.connect_opts_ref(), ) .await { context.set_dns_resolver(Arc::new(resolver)); } if config.ipv6_first { context.set_ipv6_first(config.ipv6_first); } if let Some(acl) = config.acl { context.set_acl(Arc::new(acl)); } context.set_security_config(&config.security); assert!(!config.local.is_empty(), "no valid local server configuration"); // Create a service balancer for choosing between multiple servers let balancer = { let mut mode: Option = None; for local in &config.local { mode = Some(match mode { None => local.config.mode, Some(m) => m.merge(local.config.mode), }); } let mode = mode.unwrap_or(Mode::TcpOnly); // Load balancer will hold an individual ServiceContext let mut balancer_builder = PingBalancerBuilder::new(Arc::new(context.clone()), mode); // max_server_rtt have to be set before add_server if let Some(rtt) = config.balancer.max_server_rtt { balancer_builder.max_server_rtt(rtt); } if let Some(intv) = config.balancer.check_interval { balancer_builder.check_interval(intv); } if let Some(intv) = config.balancer.check_best_interval { balancer_builder.check_best_interval(intv); } for server in config.server { balancer_builder.add_server(server); } balancer_builder.build().await? }; let mut local_server = Self { balancer: balancer.clone(), socks_servers: Vec::new(), #[cfg(feature = "local-tunnel")] tunnel_servers: Vec::new(), #[cfg(feature = "local-http")] http_servers: Vec::new(), #[cfg(feature = "local-tun")] tun_servers: Vec::new(), #[cfg(feature = "local-dns")] dns_servers: Vec::new(), #[cfg(feature = "local-redir")] redir_servers: Vec::new(), #[cfg(feature = "local-fake-dns")] fake_dns_servers: Vec::new(), #[cfg(feature = "local-flow-stat")] local_stat_addr: config.local_stat_addr, #[cfg(feature = "local-flow-stat")] flow_stat: context.flow_stat(), #[cfg(feature = "local-online-config")] online_config: match config.online_config { None => None, Some(online_config) => { let mut builder = OnlineConfigServiceBuilder::new( Arc::new(context.clone()), online_config.config_url, balancer.clone(), ); if let Some(update_interval) = online_config.update_interval { builder.set_update_interval(update_interval); } Some(builder.build().await?) } }, }; for local_instance in config.local { let local_config = local_instance.config; // Clone from global ServiceContext instance // It will shares Shadowsocks' global context, and FlowStat, DNS reverse cache let mut context = context.clone(); // Private ACL if let Some(acl) = local_instance.acl { context.set_acl(Arc::new(acl)) } let context = Arc::new(context); let balancer = balancer.clone(); match local_config.protocol { ProtocolType::Socks => { let client_addr = match local_config.addr { Some(a) => a, None => return Err(io::Error::other("socks requires local address")), }; let mut server_builder = SocksBuilder::with_context(context.clone(), client_addr, balancer); server_builder.set_mode(local_config.mode); server_builder.set_socks5_auth(local_config.socks5_auth); #[cfg(feature = "local-http")] server_builder.set_http_auth(local_config.http_auth); if let Some(c) = config.udp_max_associations { server_builder.set_udp_capacity(c); } if let Some(d) = config.udp_timeout { server_builder.set_udp_expiry_duration(d); } if let Some(b) = local_config.udp_addr { server_builder.set_udp_bind_addr(b.clone()); } if let Some(b) = local_config.udp_associate_addr { server_builder.set_udp_associate_addr(b.clone()); } #[cfg(target_os = "macos")] if let Some(n) = local_config.launchd_tcp_socket_name { server_builder.set_launchd_tcp_socket_name(n); } #[cfg(target_os = "macos")] if let Some(n) = local_config.launchd_udp_socket_name { server_builder.set_launchd_udp_socket_name(n); } let server = server_builder.build().await?; local_server.socks_servers.push(server); } #[cfg(feature = "local-tunnel")] ProtocolType::Tunnel => { let client_addr = match local_config.addr { Some(a) => a, None => return Err(io::Error::other("tunnel requires local address")), }; let forward_addr = local_config.forward_addr.expect("tunnel requires forward address"); let mut server_builder = TunnelBuilder::with_context(context.clone(), forward_addr.clone(), client_addr, balancer); if let Some(c) = config.udp_max_associations { server_builder.set_udp_capacity(c); } if let Some(d) = config.udp_timeout { server_builder.set_udp_expiry_duration(d); } server_builder.set_mode(local_config.mode); if let Some(udp_addr) = local_config.udp_addr { server_builder.set_udp_bind_addr(udp_addr); } #[cfg(target_os = "macos")] if let Some(n) = local_config.launchd_tcp_socket_name { server_builder.set_launchd_tcp_socket_name(n); } #[cfg(target_os = "macos")] if let Some(n) = local_config.launchd_udp_socket_name { server_builder.set_launchd_udp_socket_name(n); } let server = server_builder.build().await?; local_server.tunnel_servers.push(server); } #[cfg(feature = "local-http")] ProtocolType::Http => { let client_addr = match local_config.addr { Some(a) => a, None => return Err(io::Error::other("http requires local address")), }; #[allow(unused_mut)] let mut builder = HttpBuilder::with_context(context.clone(), client_addr, balancer); builder.set_http_auth(local_config.http_auth); #[cfg(target_os = "macos")] if let Some(n) = local_config.launchd_tcp_socket_name { builder.set_launchd_tcp_socket_name(n); } let server = builder.build().await?; local_server.http_servers.push(server); } #[cfg(feature = "local-redir")] ProtocolType::Redir => { let client_addr = match local_config.addr { Some(a) => a, None => return Err(io::Error::other("redir requires local address")), }; let mut server_builder = RedirBuilder::with_context(context.clone(), client_addr, balancer); if let Some(c) = config.udp_max_associations { server_builder.set_udp_capacity(c); } if let Some(d) = config.udp_timeout { server_builder.set_udp_expiry_duration(d); } server_builder.set_mode(local_config.mode); server_builder.set_tcp_redir(local_config.tcp_redir); server_builder.set_udp_redir(local_config.udp_redir); if let Some(udp_addr) = local_config.udp_addr { server_builder.set_udp_bind_addr(udp_addr); } let server = server_builder.build().await?; local_server.redir_servers.push(server); } #[cfg(feature = "local-dns")] ProtocolType::Dns => { let client_addr = match local_config.addr { Some(a) => a, None => return Err(io::Error::other("dns requires local address")), }; let mut server_builder = { let local_addr = local_config.local_dns_addr.expect("missing local_dns_addr"); let remote_addr = local_config.remote_dns_addr.expect("missing remote_dns_addr"); let client_cache_size = local_config.client_cache_size.unwrap_or(5); DnsBuilder::with_context( context.clone(), client_addr, local_addr.clone(), remote_addr.clone(), balancer, client_cache_size, ) }; server_builder.set_mode(local_config.mode); #[cfg(target_os = "macos")] if let Some(n) = local_config.launchd_tcp_socket_name { server_builder.set_launchd_tcp_socket_name(n); } #[cfg(target_os = "macos")] if let Some(n) = local_config.launchd_udp_socket_name { server_builder.set_launchd_udp_socket_name(n); } let server = server_builder.build().await?; local_server.dns_servers.push(server); } #[cfg(feature = "local-tun")] ProtocolType::Tun => { let mut builder = TunBuilder::new(context.clone(), balancer); if let Some(address) = local_config.tun_interface_address { builder.address(address); } if let Some(address) = local_config.tun_interface_destination { builder.destination(address); } if let Some(name) = local_config.tun_interface_name { builder.name(&name); } if let Some(c) = config.udp_max_associations { builder.udp_capacity(c); } if let Some(d) = config.udp_timeout { builder.udp_expiry_duration(d); } builder.mode(local_config.mode); #[cfg(unix)] if let Some(fd) = local_config.tun_device_fd { builder.file_descriptor(fd); } else if let Some(ref fd_path) = local_config.tun_device_fd_from_path { use std::fs; use log::info; use shadowsocks::net::UnixListener; let _ = fs::remove_file(fd_path); let listener = match UnixListener::bind(fd_path) { Ok(l) => l, Err(err) => { log::error!("failed to bind uds path \"{}\", error: {}", fd_path.display(), err); return Err(err); } }; info!("waiting tun's file descriptor from {}", fd_path.display()); loop { let (mut stream, peer_addr) = listener.accept().await?; trace!("accepted {:?} for receiving tun file descriptor", peer_addr); let mut buffer = [0u8; 1024]; let mut fd_buffer = [0]; match stream.recv_with_fd(&mut buffer, &mut fd_buffer).await { Ok((n, fd_size)) => { if fd_size == 0 { log::error!( "client {:?} didn't send file descriptors with buffer.size {} bytes", peer_addr, n ); continue; } info!("got file descriptor {} for tun from {:?}", fd_buffer[0], peer_addr); builder.file_descriptor(fd_buffer[0]); break; } Err(err) => { log::error!( "failed to receive file descriptors from {:?}, error: {}", peer_addr, err ); } } } } let server = builder.build().await?; local_server.tun_servers.push(server); } #[cfg(feature = "local-fake-dns")] ProtocolType::FakeDns => { let client_addr = match local_config.addr { Some(a) => a, None => return Err(io::Error::other("dns requires local address")), }; let mut builder = FakeDnsBuilder::new(client_addr); if let Some(n) = local_config.fake_dns_ipv4_network { builder.set_ipv4_network(n); } if let Some(n) = local_config.fake_dns_ipv6_network { builder.set_ipv6_network(n); } if let Some(exp) = local_config.fake_dns_record_expire_duration { builder.set_expire_duration(exp); } if let Some(p) = local_config.fake_dns_database_path { builder.set_database_path(p); } let server = builder.build().await?; #[cfg(feature = "local-fake-dns")] context.add_fake_dns_manager(server.clone_manager()).await; local_server.fake_dns_servers.push(server); } } } Ok(local_server) } /// Run local server pub async fn run(self) -> io::Result<()> { let mut vfut = Vec::new(); for svr in self.socks_servers { vfut.push(ServerHandle(tokio::spawn(svr.run()))); } #[cfg(feature = "local-tunnel")] for svr in self.tunnel_servers { vfut.push(ServerHandle(tokio::spawn(svr.run()))); } #[cfg(feature = "local-http")] for svr in self.http_servers { vfut.push(ServerHandle(tokio::spawn(svr.run()))); } #[cfg(feature = "local-tun")] for svr in self.tun_servers { vfut.push(ServerHandle(tokio::spawn(svr.run()))); } #[cfg(feature = "local-dns")] for svr in self.dns_servers { vfut.push(ServerHandle(tokio::spawn(svr.run()))); } #[cfg(feature = "local-redir")] for svr in self.redir_servers { vfut.push(ServerHandle(tokio::spawn(svr.run()))); } #[cfg(feature = "local-fake-dns")] for svr in self.fake_dns_servers { vfut.push(ServerHandle(tokio::spawn(svr.run()))); } #[cfg(feature = "local-flow-stat")] if let Some(stat_addr) = self.local_stat_addr { // For Android's flow statistic let report_fut = flow_report_task(stat_addr, self.flow_stat); vfut.push(ServerHandle(tokio::spawn(report_fut))); } #[cfg(feature = "local-online-config")] if let Some(online_config) = self.online_config { vfut.push(ServerHandle(tokio::spawn(online_config.run()))); } let (res, ..) = future::select_all(vfut).await; res } /// Get the internal server balancer pub fn server_balancer(&self) -> &PingBalancer { &self.balancer } /// Get SOCKS server instances pub fn socks_servers(&self) -> &[Socks] { &self.socks_servers } /// Get Tunnel server instances #[cfg(feature = "local-tunnel")] pub fn tunnel_servers(&self) -> &[Tunnel] { &self.tunnel_servers } /// Get HTTP server instances #[cfg(feature = "local-http")] pub fn http_servers(&self) -> &[Http] { &self.http_servers } /// Get Tun server instances #[cfg(feature = "local-tun")] pub fn tun_servers(&self) -> &[Tun] { &self.tun_servers } /// Get DNS server instances #[cfg(feature = "local-dns")] pub fn dns_servers(&self) -> &[Dns] { &self.dns_servers } /// Get Redir server instances #[cfg(feature = "local-redir")] pub fn redir_servers(&self) -> &[Redir] { &self.redir_servers } /// Get Fake DNS instances #[cfg(feature = "local-fake-dns")] pub fn fake_dns_servers(&self) -> &[FakeDns] { &self.fake_dns_servers } } #[cfg(feature = "local-flow-stat")] async fn flow_report_task(stat_addr: LocalFlowStatAddress, flow_stat: Arc) -> io::Result<()> { use std::slice; use log::debug; use tokio::{io::AsyncWriteExt, time}; // Local flow statistic report RPC let timeout = Duration::from_secs(1); loop { // keep it as libev's default, 0.5 seconds time::sleep(Duration::from_millis(500)).await; let tx = flow_stat.tx(); let rx = flow_stat.rx(); let buf: [u64; 2] = [tx, rx]; let buf = unsafe { slice::from_raw_parts(buf.as_ptr() as *const _, 16) }; match stat_addr { #[cfg(unix)] LocalFlowStatAddress::UnixStreamPath(ref stat_path) => { use tokio::net::UnixStream; let mut stream = match time::timeout(timeout, UnixStream::connect(stat_path)).await { Ok(Ok(s)) => s, Ok(Err(err)) => { debug!("send client flow statistic error: {}", err); continue; } Err(..) => { debug!("send client flow statistic error: timeout"); continue; } }; match time::timeout(timeout, stream.write_all(buf)).await { Ok(Ok(..)) => {} Ok(Err(err)) => { debug!("send client flow statistic error: {}", err); } Err(..) => { debug!("send client flow statistic error: timeout"); } } } LocalFlowStatAddress::TcpStreamAddr(stat_addr) => { use tokio::net::TcpStream; let mut stream = match time::timeout(timeout, TcpStream::connect(stat_addr)).await { Ok(Ok(s)) => s, Ok(Err(err)) => { debug!("send client flow statistic error: {}", err); continue; } Err(..) => { debug!("send client flow statistic error: timeout"); continue; } }; match time::timeout(timeout, stream.write_all(buf)).await { Ok(Ok(..)) => {} Ok(Err(err)) => { debug!("send client flow statistic error: {}", err); } Err(..) => { debug!("send client flow statistic error: timeout"); } } } } } } /// Create then run a Local Server pub async fn run(config: Config) -> io::Result<()> { Server::new(config).await?.run().await } ================================================ FILE: crates/shadowsocks-service/src/local/net/mod.rs ================================================ //! Shadowsocks Local Network Utilities pub use self::{ tcp::{auto_proxy_io::AutoProxyIo, auto_proxy_stream::AutoProxyClientStream}, udp::{UdpAssociationManager, UdpInboundWrite}, }; pub(crate) mod tcp; pub(crate) mod udp; ================================================ FILE: crates/shadowsocks-service/src/local/net/tcp/auto_proxy_io.rs ================================================ //! Trait of auto-proxy I/O /// Proxy I/O chooses bypass or proxy automatically pub trait AutoProxyIo { /// Check if the current connection is proxied fn is_proxied(&self) -> bool; /// Check if the current connection is bypassed fn is_bypassed(&self) -> bool { !self.is_proxied() } } ================================================ FILE: crates/shadowsocks-service/src/local/net/tcp/auto_proxy_stream.rs ================================================ //! A `ProxyStream` that bypasses or proxies data through proxy server automatically use std::{ io::{self, IoSlice}, net::SocketAddr, pin::Pin, sync::Arc, task::{self, Poll}, }; use log::trace; use pin_project::pin_project; use shadowsocks::{ net::{ConnectOpts, TcpStream}, relay::{socks5::Address, tcprelay::proxy_stream::ProxyClientStream}, }; use tokio::io::{AsyncRead, AsyncWrite, ReadBuf}; use crate::{ local::{context::ServiceContext, loadbalancing::ServerIdent}, net::MonProxyStream, }; use super::auto_proxy_io::AutoProxyIo; /// Unified stream for bypassed and proxied connections #[allow(clippy::large_enum_variant)] #[pin_project(project = AutoProxyClientStreamProj)] pub enum AutoProxyClientStream { Proxied(#[pin] ProxyClientStream>), Bypassed(#[pin] TcpStream), } impl AutoProxyClientStream { /// Connect to target `addr` via shadowsocks' server configured by `svr_cfg` pub async fn connect(context: Arc, server: &ServerIdent, addr: A) -> io::Result where A: Into
, { Self::connect_with_opts(context.clone(), server, addr, context.connect_opts_ref()).await } /// Connect to target `addr` via shadowsocks' server configured by `svr_cfg` pub async fn connect_with_opts( context: Arc, server: &ServerIdent, addr: A, opts: &ConnectOpts, ) -> io::Result where A: Into
, { #[cfg_attr(not(feature = "local-fake-dns"), allow(unused_mut))] let mut addr = addr.into(); #[cfg(feature = "local-fake-dns")] if let Some(mapped_addr) = context.try_map_fake_address(&addr).await { addr = mapped_addr; } if context.check_target_bypassed(&addr).await { trace!("Bypassing target address {addr}"); Self::connect_bypassed_with_opts_inner(context, addr, opts).await } else { trace!("Proxying target address {addr}"); Self::connect_proxied_with_opts_inner(context, server, addr, opts).await } } /// Connect directly to target `addr` pub async fn connect_bypassed(context: Arc, addr: A) -> io::Result where A: Into
, { Self::connect_bypassed_with_opts(context.clone(), addr, context.connect_opts_ref()).await } /// Connect directly to target `addr` pub async fn connect_bypassed_with_opts( context: Arc, addr: A, connect_opts: &ConnectOpts, ) -> io::Result where A: Into
, { // Connect directly. #[cfg_attr(not(feature = "local-fake-dns"), allow(unused_mut))] let mut addr = addr.into(); #[cfg(feature = "local-fake-dns")] if let Some(mapped_addr) = context.try_map_fake_address(&addr).await { addr = mapped_addr; } Self::connect_bypassed_with_opts_inner(context, addr, connect_opts).await } async fn connect_bypassed_with_opts_inner( context: Arc, addr: A, connect_opts: &ConnectOpts, ) -> io::Result where A: Into
, { let addr = addr.into(); let stream = TcpStream::connect_remote_with_opts(context.context_ref(), &addr, connect_opts).await?; Ok(Self::Bypassed(stream)) } /// Connect to target `addr` via shadowsocks' server configured by `svr_cfg` pub async fn connect_proxied(context: Arc, server: &ServerIdent, addr: A) -> io::Result where A: Into
, { Self::connect_proxied_with_opts(context.clone(), server, addr, context.connect_opts_ref()).await } /// Connect to target `addr` via shadowsocks' server configured by `svr_cfg` pub async fn connect_proxied_with_opts( context: Arc, server: &ServerIdent, addr: A, connect_opts: &ConnectOpts, ) -> io::Result where A: Into
, { #[cfg_attr(not(feature = "local-fake-dns"), allow(unused_mut))] let mut addr = addr.into(); #[cfg(feature = "local-fake-dns")] if let Some(mapped_addr) = context.try_map_fake_address(&addr).await { addr = mapped_addr; } Self::connect_proxied_with_opts_inner(context, server, addr, connect_opts).await } async fn connect_proxied_with_opts_inner( context: Arc, server: &ServerIdent, addr: A, connect_opts: &ConnectOpts, ) -> io::Result where A: Into
, { let flow_stat = context.flow_stat(); let stream = match ProxyClientStream::connect_with_opts_map( context.context(), server.server_config(), addr, connect_opts, |stream| MonProxyStream::from_stream(stream, flow_stat), ) .await { Ok(s) => s, Err(err) => { server.tcp_score().report_failure().await; return Err(err); } }; Ok(Self::Proxied(stream)) } pub fn local_addr(&self) -> io::Result { match *self { Self::Proxied(ref s) => s.get_ref().get_ref().local_addr(), Self::Bypassed(ref s) => s.local_addr(), } } pub fn set_nodelay(&self, nodelay: bool) -> io::Result<()> { match *self { Self::Proxied(ref s) => s.get_ref().get_ref().set_nodelay(nodelay), Self::Bypassed(ref s) => s.set_nodelay(nodelay), } } } impl AutoProxyIo for AutoProxyClientStream { fn is_proxied(&self) -> bool { matches!(*self, Self::Proxied(..)) } } impl AsyncRead for AutoProxyClientStream { fn poll_read(self: Pin<&mut Self>, cx: &mut task::Context<'_>, buf: &mut ReadBuf<'_>) -> Poll> { match self.project() { AutoProxyClientStreamProj::Proxied(s) => s.poll_read(cx, buf), AutoProxyClientStreamProj::Bypassed(s) => s.poll_read(cx, buf), } } } impl AsyncWrite for AutoProxyClientStream { fn poll_write(self: Pin<&mut Self>, cx: &mut task::Context<'_>, buf: &[u8]) -> Poll> { match self.project() { AutoProxyClientStreamProj::Proxied(s) => s.poll_write(cx, buf), AutoProxyClientStreamProj::Bypassed(s) => s.poll_write(cx, buf), } } fn poll_flush(self: Pin<&mut Self>, cx: &mut task::Context<'_>) -> Poll> { match self.project() { AutoProxyClientStreamProj::Proxied(s) => s.poll_flush(cx), AutoProxyClientStreamProj::Bypassed(s) => s.poll_flush(cx), } } fn poll_shutdown(self: Pin<&mut Self>, cx: &mut task::Context<'_>) -> Poll> { match self.project() { AutoProxyClientStreamProj::Proxied(s) => s.poll_shutdown(cx), AutoProxyClientStreamProj::Bypassed(s) => s.poll_shutdown(cx), } } fn poll_write_vectored( self: Pin<&mut Self>, cx: &mut task::Context<'_>, bufs: &[IoSlice<'_>], ) -> Poll> { match self.project() { AutoProxyClientStreamProj::Proxied(s) => s.poll_write_vectored(cx, bufs), AutoProxyClientStreamProj::Bypassed(s) => s.poll_write_vectored(cx, bufs), } } } impl From>> for AutoProxyClientStream { fn from(s: ProxyClientStream>) -> Self { Self::Proxied(s) } } ================================================ FILE: crates/shadowsocks-service/src/local/net/tcp/listener.rs ================================================ //! Local instance listener helpers use std::io; use shadowsocks::{config::ServerAddr, lookup_then, net::TcpListener}; use crate::local::context::ServiceContext; /// Create a standard TCP listener listening on `client_config` pub async fn create_standard_tcp_listener( context: &ServiceContext, client_config: &ServerAddr, ) -> io::Result { match client_config { ServerAddr::SocketAddr(saddr) => TcpListener::bind_with_opts(saddr, context.accept_opts()).await, ServerAddr::DomainName(dname, port) => lookup_then!(context.context_ref(), dname, *port, |addr| { TcpListener::bind_with_opts(&addr, context.accept_opts()).await }) .map(|(_, l)| l), } } ================================================ FILE: crates/shadowsocks-service/src/local/net/tcp/mod.rs ================================================ pub mod auto_proxy_io; pub mod auto_proxy_stream; pub mod listener; ================================================ FILE: crates/shadowsocks-service/src/local/net/udp/association.rs ================================================ //! UDP Association Managing use std::{ cell::RefCell, io, marker::PhantomData, net::{SocketAddr, SocketAddrV6}, sync::Arc, time::Duration, }; use bytes::Bytes; use futures::future; use log::{debug, error, trace, warn}; use lru_time_cache::LruCache; use rand::{RngExt, rngs::SmallRng}; use tokio::{sync::mpsc, task::JoinHandle, time}; use shadowsocks::{ lookup_then, net::{AddrFamily, UdpSocket as ShadowUdpSocket}, relay::{ Address, udprelay::{MAXIMUM_UDP_PAYLOAD_SIZE, ProxySocket, options::UdpSocketControlData}, }, }; use crate::{ local::{context::ServiceContext, loadbalancing::PingBalancer}, net::{ MonProxySocket, UDP_ASSOCIATION_KEEP_ALIVE_CHANNEL_SIZE, UDP_ASSOCIATION_SEND_CHANNEL_SIZE, packet_window::PacketWindowFilter, }, }; /// Writer for sending packets back to client #[trait_variant::make(Send)] pub trait UdpInboundWrite { /// Sends packet `data` received from `remote_addr` back to `peer_addr` async fn send_to(&self, peer_addr: SocketAddr, remote_addr: &Address, data: &[u8]) -> io::Result<()>; } type AssociationMap = LruCache>; /// UDP association manager pub struct UdpAssociationManager where W: UdpInboundWrite + Clone + Send + Sync + Unpin + 'static, { respond_writer: W, context: Arc, assoc_map: AssociationMap, keepalive_tx: mpsc::Sender, balancer: PingBalancer, server_session_expire_duration: Duration, } impl UdpAssociationManager where W: UdpInboundWrite + Clone + Send + Sync + Unpin + 'static, { /// Create a new `UdpAssociationManager` /// /// Returns (`UdpAssociationManager`, Cleanup Interval, Keep-alive Receiver) pub fn new( context: Arc, respond_writer: W, time_to_live: Option, capacity: Option, balancer: PingBalancer, ) -> (Self, Duration, mpsc::Receiver) { let time_to_live = time_to_live.unwrap_or(crate::DEFAULT_UDP_EXPIRY_DURATION); let assoc_map = match capacity { Some(capacity) => LruCache::with_expiry_duration_and_capacity(time_to_live, capacity), None => LruCache::with_expiry_duration(time_to_live), }; let (keepalive_tx, keepalive_rx) = mpsc::channel(UDP_ASSOCIATION_KEEP_ALIVE_CHANNEL_SIZE); ( Self { respond_writer, context, assoc_map, keepalive_tx, balancer, server_session_expire_duration: time_to_live, }, time_to_live, keepalive_rx, ) } /// Sends `data` from `peer_addr` to `target_addr` #[cfg_attr(not(feature = "local-fake-dns"), allow(unused_mut))] pub async fn send_to(&mut self, peer_addr: SocketAddr, mut target_addr: Address, data: &[u8]) -> io::Result<()> { #[cfg(feature = "local-fake-dns")] if let Some(mapped_addr) = self.context.try_map_fake_address(&target_addr).await { target_addr = mapped_addr; } // Check or (re)create an association if let Some(assoc) = self.assoc_map.get(&peer_addr) { return assoc.try_send((target_addr, Bytes::copy_from_slice(data))); } let assoc = UdpAssociation::new( self.context.clone(), peer_addr, self.keepalive_tx.clone(), self.balancer.clone(), self.respond_writer.clone(), self.server_session_expire_duration, ); debug!("created udp association for {}", peer_addr); assoc.try_send((target_addr, Bytes::copy_from_slice(data)))?; self.assoc_map.insert(peer_addr, assoc); Ok(()) } /// Cleanup expired associations pub async fn cleanup_expired(&mut self) { self.assoc_map.iter(); } /// Keep-alive association pub async fn keep_alive(&mut self, peer_addr: &SocketAddr) { self.assoc_map.get(peer_addr); } } struct UdpAssociation where W: UdpInboundWrite + Send + Sync + Unpin + 'static, { assoc_handle: JoinHandle<()>, sender: mpsc::Sender<(Address, Bytes)>, writer: PhantomData, } impl Drop for UdpAssociation where W: UdpInboundWrite + Send + Sync + Unpin + 'static, { fn drop(&mut self) { self.assoc_handle.abort(); } } impl UdpAssociation where W: UdpInboundWrite + Send + Sync + Unpin + 'static, { fn new( context: Arc, peer_addr: SocketAddr, keepalive_tx: mpsc::Sender, balancer: PingBalancer, respond_writer: W, server_session_expire_duration: Duration, ) -> Self { let (assoc_handle, sender) = UdpAssociationContext::create( context, peer_addr, keepalive_tx, balancer, respond_writer, server_session_expire_duration, ); Self { assoc_handle, sender, writer: PhantomData, } } fn try_send(&self, data: (Address, Bytes)) -> io::Result<()> { if self.sender.try_send(data).is_err() { let err = io::Error::other("udp relay channel full"); return Err(err); } Ok(()) } } #[derive(Debug, Clone)] struct ServerContext { packet_window_filter: PacketWindowFilter, } #[derive(Clone)] struct ServerSessionContext { server_session_map: LruCache, } impl ServerSessionContext { fn new(session_expire_duration: Duration) -> Self { Self { server_session_map: LruCache::with_expiry_duration(session_expire_duration), } } } struct UdpAssociationContext where W: UdpInboundWrite + Send + Sync + Unpin + 'static, { context: Arc, peer_addr: SocketAddr, bypassed_ipv4_socket: Option, bypassed_ipv6_socket: Option, proxied_socket: Option>, keepalive_tx: mpsc::Sender, keepalive_flag: bool, balancer: PingBalancer, respond_writer: W, client_session_id: u64, client_packet_id: u64, server_session: Option, server_session_expire_duration: Duration, } impl Drop for UdpAssociationContext where W: UdpInboundWrite + Send + Sync + Unpin + 'static, { fn drop(&mut self) { debug!("udp association for {} is closed", self.peer_addr); } } thread_local! { static CLIENT_SESSION_RNG: RefCell = RefCell::new(rand::make_rng()); } /// Generate an AEAD-2022 Client SessionID #[inline] pub fn generate_client_session_id() -> u64 { loop { let id = CLIENT_SESSION_RNG.with(|rng| rng.borrow_mut().random()); if id != 0 { break id; } } } impl UdpAssociationContext where W: UdpInboundWrite + Send + Sync + Unpin + 'static, { fn create( context: Arc, peer_addr: SocketAddr, keepalive_tx: mpsc::Sender, balancer: PingBalancer, respond_writer: W, server_session_expire_duration: Duration, ) -> (JoinHandle<()>, mpsc::Sender<(Address, Bytes)>) { // Pending packets UDP_ASSOCIATION_SEND_CHANNEL_SIZE for each association should be good enough for a server. // If there are plenty of packets stuck in the channel, dropping excessive packets is a good way to protect the server from // being OOM. let (sender, receiver) = mpsc::channel(UDP_ASSOCIATION_SEND_CHANNEL_SIZE); let mut assoc = Self { context, peer_addr, bypassed_ipv4_socket: None, bypassed_ipv6_socket: None, proxied_socket: None, keepalive_tx, keepalive_flag: false, balancer, respond_writer, // client_session_id must be random generated, // server use this ID to identify every independent clients. client_session_id: generate_client_session_id(), client_packet_id: 0, server_session: None, server_session_expire_duration, }; let handle = tokio::spawn(async move { assoc.dispatch_packet(receiver).await }); (handle, sender) } async fn dispatch_packet(&mut self, mut receiver: mpsc::Receiver<(Address, Bytes)>) { let mut bypassed_ipv4_buffer = Vec::new(); let mut bypassed_ipv6_buffer = Vec::new(); let mut proxied_buffer = Vec::new(); let mut keepalive_interval = time::interval(Duration::from_secs(1)); loop { tokio::select! { packet_received_opt = receiver.recv() => { let (target_addr, data) = match packet_received_opt { Some(d) => d, None => { trace!("udp association for {} -> ... channel closed", self.peer_addr); break; } }; self.dispatch_received_packet(&target_addr, &data).await; } received_opt = receive_from_bypassed_opt(&self.bypassed_ipv4_socket, &mut bypassed_ipv4_buffer), if self.bypassed_ipv4_socket.is_some() => { let (n, addr) = match received_opt { Ok(r) => r, Err(err) => { error!("udp relay {} <- ... (bypassed) failed, error: {}", self.peer_addr, err); // Socket failure. Reset for recreation. self.bypassed_ipv4_socket = None; continue; } }; let addr = Address::from(addr); self.send_received_respond_packet(&addr, &bypassed_ipv4_buffer[..n], true).await; } received_opt = receive_from_bypassed_opt(&self.bypassed_ipv6_socket, &mut bypassed_ipv6_buffer), if self.bypassed_ipv6_socket.is_some() => { let (n, addr) = match received_opt { Ok(r) => r, Err(err) => { error!("udp relay {} <- ... (bypassed) failed, error: {}", self.peer_addr, err); // Socket failure. Reset for recreation. self.bypassed_ipv6_socket = None; continue; } }; let addr = Address::from(addr); self.send_received_respond_packet(&addr, &bypassed_ipv6_buffer[..n], true).await; } received_opt = receive_from_proxied_opt(&self.proxied_socket, &mut proxied_buffer), if self.proxied_socket.is_some() => { let (n, addr, control_opt) = match received_opt { Ok(r) => r, Err(err) => { error!("udp relay {} <- ... (proxied) failed, error: {}", self.peer_addr, err); // Socket failure. Reset for recreation. self.proxied_socket = None; continue; } }; if let Some(control) = control_opt { // Check if Packet ID is in the window let session = self.server_session.get_or_insert_with(|| { ServerSessionContext::new(self.server_session_expire_duration) }); let packet_id = control.packet_id; let session_context = session .server_session_map .entry(control.server_session_id) .or_insert_with(|| { trace!( "udp server with session {} for {} created", control.client_session_id, self.peer_addr, ); ServerContext { packet_window_filter: PacketWindowFilter::new() } }); if !session_context.packet_window_filter.validate_packet_id(packet_id, u64::MAX) { error!("udp {} packet_id {} out of window", self.peer_addr, packet_id); continue; } } self.send_received_respond_packet(&addr, &proxied_buffer[..n], false).await; } _ = keepalive_interval.tick() => { if self.keepalive_flag { if self.keepalive_tx.try_send(self.peer_addr).is_err() { debug!("udp relay {} keep-alive failed, channel full or closed", self.peer_addr); } else { self.keepalive_flag = false; } } } } } #[inline] async fn receive_from_bypassed_opt( socket: &Option, buf: &mut Vec, ) -> io::Result<(usize, SocketAddr)> { match *socket { None => future::pending().await, Some(ref s) => { if buf.is_empty() { buf.resize(MAXIMUM_UDP_PAYLOAD_SIZE, 0); } s.recv_from(buf).await } } } #[inline] async fn receive_from_proxied_opt( socket: &Option>, buf: &mut Vec, ) -> io::Result<(usize, Address, Option)> { match *socket { None => future::pending().await, Some(ref s) => { if buf.is_empty() { buf.resize(MAXIMUM_UDP_PAYLOAD_SIZE, 0); } s.recv_with_ctrl(buf).await } } } } async fn dispatch_received_packet(&mut self, target_addr: &Address, data: &[u8]) { // Check if target should be bypassed. If so, send packets directly. let bypassed = self.balancer.is_empty() || self.context.check_target_bypassed(target_addr).await; trace!( "udp relay {} -> {} ({}) with {} bytes", self.peer_addr, target_addr, if bypassed { "bypassed" } else { "proxied" }, data.len() ); if bypassed { if let Err(err) = self.dispatch_received_bypassed_packet(target_addr, data).await { error!( "udp relay {} -> {} (bypassed) with {} bytes, error: {}", self.peer_addr, target_addr, data.len(), err ); } } else if let Err(err) = self.dispatch_received_proxied_packet(target_addr, data).await { error!( "udp relay {} -> {} (proxied) with {} bytes, error: {}", self.peer_addr, target_addr, data.len(), err ); } } async fn dispatch_received_bypassed_packet(&mut self, target_addr: &Address, data: &[u8]) -> io::Result<()> { match *target_addr { Address::SocketAddress(sa) => self.send_received_bypassed_packet(sa, data).await, Address::DomainNameAddress(ref dname, port) => { lookup_then!(self.context.context_ref(), dname, port, |sa| { self.send_received_bypassed_packet(sa, data).await }) .map(|_| ()) } } } async fn send_received_bypassed_packet(&mut self, mut target_addr: SocketAddr, data: &[u8]) -> io::Result<()> { const UDP_SOCKET_SUPPORT_DUAL_STACK: bool = cfg!(any( target_os = "linux", target_os = "android", target_os = "macos", target_os = "ios", target_os = "watchos", target_os = "tvos", target_os = "freebsd", target_os = "windows", )); let socket = if UDP_SOCKET_SUPPORT_DUAL_STACK { match self.bypassed_ipv6_socket { Some(ref mut socket) => socket, None => { let socket = ShadowUdpSocket::connect_any_with_opts(AddrFamily::Ipv6, self.context.connect_opts_ref()) .await?; self.bypassed_ipv6_socket.insert(socket) } } } else { match target_addr { SocketAddr::V4(..) => match self.bypassed_ipv4_socket { Some(ref mut socket) => socket, None => { let socket = ShadowUdpSocket::connect_any_with_opts(&target_addr, self.context.connect_opts_ref()) .await?; self.bypassed_ipv4_socket.insert(socket) } }, SocketAddr::V6(..) => match self.bypassed_ipv6_socket { Some(ref mut socket) => socket, None => { let socket = ShadowUdpSocket::connect_any_with_opts(&target_addr, self.context.connect_opts_ref()) .await?; self.bypassed_ipv6_socket.insert(socket) } }, } }; if UDP_SOCKET_SUPPORT_DUAL_STACK && let SocketAddr::V4(saddr) = target_addr { let mapped_ip = saddr.ip().to_ipv6_mapped(); target_addr = SocketAddr::V6(SocketAddrV6::new(mapped_ip, saddr.port(), 0, 0)); } let n = socket.send_to(data, target_addr).await?; if n != data.len() { warn!( "{} -> {} sent {} bytes != expected {} bytes", self.peer_addr, target_addr, n, data.len() ); } Ok(()) } async fn dispatch_received_proxied_packet(&mut self, target_addr: &Address, data: &[u8]) -> io::Result<()> { // Increase Packet ID before send self.client_packet_id = match self.client_packet_id.checked_add(1) { Some(i) => i, None => { // FIXME: client_packet_id overflowed. What's the proper way to handle this? // // Reopen a new session is not perfect, because the remote target will receive packets from a different address. // For most application protocol, like QUIC, it is fine to change client address. // // But it will happen only when a client continuously send 18446744073709551616 packets without renewing the socket. let new_session_id = generate_client_session_id(); warn!( "{} -> {} (proxied) packet id overflowed. socket reset and session renewed ({} -> {})", self.peer_addr, target_addr, self.client_session_id, new_session_id ); self.proxied_socket.take(); self.client_packet_id = 1; self.client_session_id = new_session_id; self.client_packet_id } }; let socket = match self.proxied_socket { Some(ref mut socket) => socket, None => { // Create a new connection to proxy server let server = self.balancer.best_udp_server(); let svr_cfg = server.server_config(); let socket = ProxySocket::connect_with_opts(self.context.context(), svr_cfg, server.connect_opts_ref()).await?; let socket = MonProxySocket::from_socket(socket, self.context.flow_stat()); self.proxied_socket.insert(socket) } }; let mut control = UdpSocketControlData::default(); control.client_session_id = self.client_session_id; control.packet_id = self.client_packet_id; match socket.send_with_ctrl(target_addr, &control, data).await { Ok(..) => return Ok(()), Err(err) => { debug!( "{} -> {} (proxied) sending {} bytes failed, error: {}", self.peer_addr, target_addr, data.len(), err ); // Drop the socket and reconnect to another server. self.proxied_socket = None; } } Ok(()) } async fn send_received_respond_packet(&mut self, addr: &Address, data: &[u8], bypassed: bool) { trace!( "udp relay {} <- {} ({}) received {} bytes", self.peer_addr, addr, if bypassed { "bypassed" } else { "proxied" }, data.len(), ); // Keep association alive in map self.keepalive_flag = true; // Send back to client match self.respond_writer.send_to(self.peer_addr, addr, data).await { Err(err) => { warn!( "udp failed to send back {} bytes to client {}, from target {} ({}), error: {}", data.len(), self.peer_addr, addr, if bypassed { "bypassed" } else { "proxied" }, err ); } Ok(..) => { trace!( "udp relay {} <- {} ({}) with {} bytes", self.peer_addr, addr, if bypassed { "bypassed" } else { "proxied" }, data.len() ); } } } } ================================================ FILE: crates/shadowsocks-service/src/local/net/udp/listener.rs ================================================ //! Local instance listener helpers use std::io; use shadowsocks::{config::ServerAddr, lookup_then, net::UdpSocket}; use crate::local::context::ServiceContext; /// Create a standard UDP listener listening on `client_config` pub async fn create_standard_udp_listener( context: &ServiceContext, client_config: &ServerAddr, ) -> io::Result { match client_config { ServerAddr::SocketAddr(saddr) => UdpSocket::listen_with_opts(saddr, context.accept_opts()).await, ServerAddr::DomainName(dname, port) => lookup_then!(context.context_ref(), dname, *port, |addr| { UdpSocket::listen_with_opts(&addr, context.accept_opts()).await }) .map(|(_, s)| s), } } ================================================ FILE: crates/shadowsocks-service/src/local/net/udp/mod.rs ================================================ #[allow(unused_imports)] pub use self::association::{UdpAssociationManager, UdpInboundWrite, generate_client_session_id}; pub mod association; pub mod listener; ================================================ FILE: crates/shadowsocks-service/src/local/online_config/content_encoding.rs ================================================ //! HTTP Body Content-Encoding use std::io::{self, Cursor, Read}; use futures::StreamExt; use http::HeaderValue; use http_body_util::BodyExt; use hyper::body::Body; /// HTTP Content-Encoding #[derive(Debug, Clone, Copy, Default)] pub enum ContentEncoding { #[default] Identity, Deflate, Gzip, Br, Zstd, } #[derive(Debug, Clone, Copy)] pub struct ContentEncodingError; impl<'a> TryFrom<&'a HeaderValue> for ContentEncoding { type Error = ContentEncodingError; fn try_from(value: &'a HeaderValue) -> Result { if value == HeaderValue::from_static("identity") { Ok(Self::Identity) } else if value == HeaderValue::from_static("deflate") { Ok(Self::Deflate) } else if value == HeaderValue::from_static("gzip") { Ok(Self::Gzip) } else if value == HeaderValue::from_static("br") { Ok(Self::Br) } else if value == HeaderValue::from_static("zstd") { Ok(Self::Zstd) } else { Err(ContentEncodingError) } } } /// Read data from body, decode automatically with specific Content-Encoding pub async fn read_body(encoding: ContentEncoding, body: &mut B) -> io::Result> where B: Body + Sized + Unpin + 'static, B::Data: AsRef<[u8]>, B::Error: Into>, { let mut raw_body = Vec::new(); let mut body_stream = body.into_data_stream(); while let Some(data) = body_stream.next().await { match data { Ok(data) => raw_body.extend_from_slice(data.as_ref()), Err(err) => return Err(io::Error::other(err)), } } match encoding { ContentEncoding::Identity => Ok(raw_body), ContentEncoding::Deflate => { use flate2::read::DeflateDecoder; let mut decoder = DeflateDecoder::new(&raw_body[..]); let mut decoded_body = Vec::new(); decoder.read_to_end(&mut decoded_body)?; Ok(decoded_body) } ContentEncoding::Gzip => { use flate2::read::GzDecoder; let mut decoder = GzDecoder::new(&raw_body[..]); let mut decoded_body = Vec::new(); decoder.read_to_end(&mut decoded_body)?; Ok(decoded_body) } ContentEncoding::Br => { let mut decoded_body = Vec::new(); brotli::BrotliDecompress(&mut Cursor::new(&raw_body[..]), &mut decoded_body)?; Ok(decoded_body) } ContentEncoding::Zstd => zstd::decode_all(Cursor::new(&raw_body[..])), } } ================================================ FILE: crates/shadowsocks-service/src/local/online_config/mod.rs ================================================ //! Online Config (SIP008) //! //! Online Configuration Delivery URL (https://shadowsocks.org/doc/sip008.html) use std::{ collections::HashSet, io, sync::Arc, time::{Duration, Instant}, }; use crate::{ config::{Config, ConfigType}, local::{context::ServiceContext, http::HttpClient, loadbalancing::PingBalancer}, }; use http::StatusCode; use log::{debug, error, trace, warn}; use mime::Mime; use shadowsocks::config::ServerSource; use tokio::time; use self::content_encoding::{ContentEncoding, read_body}; mod content_encoding; /// OnlineConfigService builder pattern pub struct OnlineConfigServiceBuilder { context: Arc, config_url: String, balancer: PingBalancer, config_update_interval: Duration, allowed_plugins: Option>, } impl OnlineConfigServiceBuilder { /// Create a Builder pub fn new(context: Arc, config_url: String, balancer: PingBalancer) -> Self { Self { context, config_url, balancer, config_update_interval: Duration::from_secs(3600), allowed_plugins: None, } } /// Set update interval. Default is 3600s pub fn set_update_interval(&mut self, update_interval: Duration) { self.config_update_interval = update_interval; } /// Allowed plugins (whitelist) from SIP008 server pub fn set_allowed_plugins(&mut self, allowed_plugins: V) where V: Iterator, S: Into, { let mut allowed_plugins_set = HashSet::new(); for plugin in allowed_plugins { allowed_plugins_set.insert(plugin.into()); } self.allowed_plugins = Some(allowed_plugins_set); } /// Build OnlineConfigService pub async fn build(self) -> io::Result { let mut service = OnlineConfigService { context: self.context, http_client: HttpClient::new(), config_url: self.config_url, config_update_interval: self.config_update_interval, balancer: self.balancer, allowed_plugins: self.allowed_plugins, }; // Run once after creation. service.run_once().await?; Ok(service) } } pub struct OnlineConfigService { context: Arc, http_client: HttpClient, config_url: String, config_update_interval: Duration, balancer: PingBalancer, allowed_plugins: Option>, } impl OnlineConfigService { async fn run_once(&mut self) -> io::Result<()> { match time::timeout(Duration::from_secs(30), self.run_once_impl()).await { Ok(o) => o, Err(..) => { error!("server-loader task timeout, url: {}", self.config_url); Err(io::ErrorKind::TimedOut.into()) } } } async fn run_once_impl(&mut self) -> io::Result<()> { const SHADOWSOCKS_USER_AGENT: &str = concat!(env!("CARGO_PKG_NAME"), "/", env!("CARGO_PKG_VERSION")); let start_time = Instant::now(); let req = match hyper::Request::builder() .header("User-Agent", SHADOWSOCKS_USER_AGENT) .header("Accept-Encoding", "deflate, gzip, br, zstd") .method("GET") .uri(&self.config_url) .body(String::new()) { Ok(r) => r, Err(err) => { error!("server-loader task failed to make hyper::Request, error: {}", err); return Err(io::Error::other(err)); } }; let mut rsp = match self.http_client.send_request(self.context.clone(), req, None).await { Ok(r) => r, Err(err) => { error!("server-loader task failed to get {}, error: {}", self.config_url, err); return Err(io::Error::other(err)); } }; trace!("server-loader task fetch response: {:?}", rsp); let fetch_time = Instant::now(); // Check status=200 if rsp.status() != StatusCode::OK { error!( "server-loader task failed to get {}, status: {}", self.config_url, rsp.status() ); return Err(io::Error::other(format!("status: {}", rsp.status()))); } // Content-Type: application/json; charset=utf-8 // mandatory in standard SIP008 match rsp.headers().get("Content-Type") { Some(h) => match h.to_str() { Ok(hstr) => match hstr.parse::() { Ok(content_type) => { if content_type.type_() == mime::APPLICATION && content_type.subtype() == mime::JSON && content_type.get_param(mime::CHARSET) == Some(mime::UTF_8) { trace!("checked Content-Type: {:?}", h); } else { warn!( "Content-Type is not \"application/json; charset=utf-8\", which is mandatory in standard SIP008. found {:?}", h ); } } Err(err) => { warn!("Content-Type parse failed, value: {:?}, error: {}", h, err); } }, Err(..) => { warn!("Content-Type is not a UTF-8 string: {:?}", h); } }, None => { warn!("missing Content-Type in SIP008 response from {}", self.config_url); } } let content_encoding = match rsp.headers().get(http::header::CONTENT_ENCODING) { None => ContentEncoding::Identity, Some(ce) => match ContentEncoding::try_from(ce) { Ok(ce) => ce, Err(..) => { error!("unrecognized Content-Encoding: {:?}", ce); return Err(io::Error::other("unrecognized Content-Encoding")); } }, }; let body = read_body(content_encoding, &mut rsp).await?; let parsed_body = match String::from_utf8(body) { Ok(b) => b, Err(..) => return Err(io::Error::other("body contains non-utf8 bytes")), }; let online_config = match Config::load_from_json_str(&parsed_body, ConfigType::OnlineConfig) { Ok(c) => c, Err(err) => { error!( "server-loader task failed to load from url: {}, error: {}", self.config_url, err ); return Err(io::Error::other(err)); } }; if let Err(err) = online_config.check_integrity() { error!( "server-loader task failed to load from url: {}, error: {}", self.config_url, err ); return Err(io::Error::other(err)); } let after_read_time = Instant::now(); // Check plugin whitelist if let Some(ref allowed_plugins) = self.allowed_plugins { for server in &online_config.server { if let Some(plugin) = server.config.plugin() && !allowed_plugins.contains(&plugin.plugin) { error!( "server-loader task found not allowed plugin: {}, url: {}", plugin.plugin, self.config_url ); return Err(io::Error::other(format!("not allowed plugin: {}", plugin.plugin))); } } } // Merge with static servers let server_len = online_config.server.len(); // Update into ping balancers if let Err(err) = self .balancer .reset_servers(online_config.server, &[ServerSource::OnlineConfig]) .await { error!( "server-loader task failed to reset balancer, url: {}, error: {}", self.config_url, err ); return Err(err); }; let finish_time = Instant::now(); debug!( "server-loader task finished loading {} servers from url: {}, fetch time: {:?}, read time: {:?}, load time: {:?}, total time: {:?}", server_len, self.config_url, fetch_time - start_time, after_read_time - fetch_time, finish_time - after_read_time, finish_time - start_time, ); Ok(()) } /// Start service loop pub async fn run(mut self) -> io::Result<()> { debug!( "server-loader task started, url: {}, update interval: {:?}", self.config_url, self.config_update_interval ); loop { time::sleep(self.config_update_interval).await; let _ = self.run_once().await; } } } ================================================ FILE: crates/shadowsocks-service/src/local/redir/mod.rs ================================================ //! Shadowsocks Local Transparent Proxy pub use self::server::{Redir, RedirBuilder}; mod redir_ext; mod server; mod sys; mod tcprelay; mod udprelay; ================================================ FILE: crates/shadowsocks-service/src/local/redir/redir_ext.rs ================================================ //! Extension trait for `TcpListener` and `UdpSocket` use std::{ future::Future, io, net::SocketAddr, pin::Pin, task::{Context, Poll}, }; use shadowsocks::net::AcceptOpts; use tokio::net::TcpListener; use crate::config::RedirType; /// Extension function for `TcpListener` for setting extra options before `bind()` pub trait TcpListenerRedirExt { // Create a TcpListener for transparent proxy // // Implementation is platform dependent async fn bind_redir(ty: RedirType, addr: SocketAddr, accept_opts: AcceptOpts) -> io::Result; } /// Extension function for `TcpStream` for reading original destination address pub trait TcpStreamRedirExt { // Read destination address for TcpStream // // Implementation is platform dependent fn destination_addr(&self, ty: RedirType) -> io::Result; } /// `UdpSocket` that support transparent proxy pub trait UdpSocketRedir { /// Receive a single datagram from the socket. /// /// On success, the future resolves to the number of bytes read and the source, target address /// /// `(bytes read, source address, target address)` fn poll_recv_dest_from( &self, cx: &mut Context<'_>, buf: &mut [u8], ) -> Poll>; } /// Extension functions for `UdpSocket` to receive data with original destination address pub trait UdpSocketRedirExt { fn recv_dest_from<'a>(&'a self, buf: &'a mut [u8]) -> RecvDestFrom<'a, Self> where Self: Sized, { RecvDestFrom { socket: self, buf } } } impl UdpSocketRedirExt for S where S: UdpSocketRedir {} /// Future for `recv_dest_from` pub struct RecvDestFrom<'a, S: 'a> { socket: &'a S, buf: &'a mut [u8], } impl<'a, S: 'a> Future for RecvDestFrom<'a, S> where S: UdpSocketRedir, { type Output = io::Result<(usize, SocketAddr, SocketAddr)>; fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { self.socket.poll_recv_dest_from(cx, self.buf) } } // sockopts for send-back sockets #[derive(Debug, Clone, Default)] pub struct RedirSocketOpts { /// Linux mark based routing, going to set by `setsockopt` with `SO_MARK` option #[cfg(any(target_os = "linux", target_os = "android"))] pub fwmark: Option, } ================================================ FILE: crates/shadowsocks-service/src/local/redir/server.rs ================================================ //! Shadowsocks Transparent Proxy Local Server use std::{io, sync::Arc, time::Duration}; use futures::{FutureExt, future}; use shadowsocks::{ServerAddr, config::Mode}; use crate::{ config::RedirType, local::{context::ServiceContext, loadbalancing::PingBalancer}, }; use super::{tcprelay::RedirTcpServer, udprelay::RedirUdpServer}; /// Transparent Proxy builder pub struct RedirBuilder { context: Arc, mode: Mode, udp_expiry_duration: Option, udp_capacity: Option, tcp_redir: RedirType, udp_redir: RedirType, client_addr: ServerAddr, udp_bind_addr: Option, balancer: PingBalancer, } impl RedirBuilder { /// Create a new transparent proxy server with default configuration pub fn new(client_addr: ServerAddr, balancer: PingBalancer) -> Self { let context = ServiceContext::new(); Self::with_context(Arc::new(context), client_addr, balancer) } /// Create a new transparent proxy server with context pub fn with_context(context: Arc, client_addr: ServerAddr, balancer: PingBalancer) -> Self { Self { context, mode: Mode::TcpOnly, udp_expiry_duration: None, udp_capacity: None, tcp_redir: RedirType::tcp_default(), udp_redir: RedirType::udp_default(), client_addr, udp_bind_addr: None, balancer, } } /// Set UDP association's expiry duration pub fn set_udp_expiry_duration(&mut self, d: Duration) { self.udp_expiry_duration = Some(d); } /// Set total UDP association to be kept simultaneously in server pub fn set_udp_capacity(&mut self, c: usize) { self.udp_capacity = Some(c); } /// Set server mode pub fn set_mode(&mut self, mode: Mode) { self.mode = mode; } /// Set transparent proxy type of TCP relay, which is platform dependent pub fn set_tcp_redir(&mut self, ty: RedirType) { self.tcp_redir = ty; } /// Set transparent proxy type of UDP relay, which is platform dependent pub fn set_udp_redir(&mut self, ty: RedirType) { self.udp_redir = ty; } /// Set UDP bind address pub fn set_udp_bind_addr(&mut self, addr: ServerAddr) { self.udp_bind_addr = Some(addr); } pub async fn build(self) -> io::Result { let mut tcp_server = None; if self.mode.enable_tcp() { let server = RedirTcpServer::new( self.context.clone(), &self.client_addr, self.balancer.clone(), self.tcp_redir, ) .await?; tcp_server = Some(server); } let mut udp_server = None; if self.mode.enable_udp() { let udp_addr = self.udp_bind_addr.as_ref().unwrap_or(&self.client_addr); let server = RedirUdpServer::new( self.context, self.udp_redir, udp_addr, self.udp_expiry_duration, self.udp_capacity, self.balancer, ) .await?; udp_server = Some(server); } Ok(Redir { tcp_server, udp_server }) } } /// Transparent Proxy pub struct Redir { tcp_server: Option, udp_server: Option, } impl Redir { /// TCP server instance pub fn tcp_server(&self) -> Option<&RedirTcpServer> { self.tcp_server.as_ref() } /// UDP server instance pub fn udp_server(&self) -> Option<&RedirUdpServer> { self.udp_server.as_ref() } /// Start serving pub async fn run(self) -> io::Result<()> { let mut vfut = Vec::new(); if let Some(tcp_server) = self.tcp_server { vfut.push(tcp_server.run().boxed()); } if let Some(udp_server) = self.udp_server { vfut.push(udp_server.run().boxed()); } let (res, ..) = future::select_all(vfut).await; res } } ================================================ FILE: crates/shadowsocks-service/src/local/redir/sys/mod.rs ================================================ use std::io; use cfg_if::cfg_if; use socket2::SockRef; cfg_if! { if #[cfg(unix)] { mod unix; #[allow(unused_imports)] pub use self::unix::*; } } #[cfg(unix)] #[allow(dead_code)] pub fn set_ipv6_only(socket: &S, ipv6_only: bool) -> io::Result<()> where S: std::os::unix::io::AsFd, { let sock = SockRef::from(socket); sock.set_only_v6(ipv6_only) } #[cfg(windows)] #[allow(dead_code)] pub fn set_ipv6_only(socket: &S, ipv6_only: bool) -> io::Result<()> where S: std::os::windows::io::AsSocket, { let sock = SockRef::from(socket); sock.set_only_v6(ipv6_only) } ================================================ FILE: crates/shadowsocks-service/src/local/redir/sys/unix/bsd_pf.rs ================================================ //! PacketFilter implementation for *BSD use std::{ io::{self, Error, ErrorKind}, mem, net::SocketAddr, ptr, sync::LazyLock, }; use cfg_if::cfg_if; use log::trace; use nix::ioctl_readwrite; use socket2::{Protocol, SockAddr}; use super::pfvar::{PF_OUT, in_addr, in6_addr, pfioc_natlook, sockaddr_in, sockaddr_in6}; #[cfg(any(target_os = "macos", target_os = "ios"))] use super::pfvar::{pf_addr, pfioc_states, pfsync_state}; ioctl_readwrite!(ioc_natlook, 'D', 23, pfioc_natlook); #[cfg(any(target_os = "macos", target_os = "ios"))] ioctl_readwrite!(ioc_getstates, 'D', 25, pfioc_states); pub struct PacketFilter { fd: libc::c_int, } impl PacketFilter { fn open() -> io::Result { unsafe { let dev_path = b"/dev/pf\0"; // According to FreeBSD's doc // https://www.freebsd.org/cgi/man.cgi?query=pf&sektion=4&apropos=0&manpath=FreeBSD+12.1-RELEASE+and+Ports let fd = libc::open(dev_path.as_ptr() as *const _, libc::O_RDONLY); if fd < 0 { let err = Error::last_os_error(); return Err(err); } // Set CLOEXEC let ret = libc::fcntl(fd, libc::F_SETFD, libc::fcntl(fd, libc::F_GETFD) | libc::FD_CLOEXEC); if ret != 0 { let err = Error::last_os_error(); let _ = libc::close(fd); return Err(err); } Ok(PacketFilter { fd }) } } pub fn natlook(&self, bind_addr: &SocketAddr, peer_addr: &SocketAddr, proto: Protocol) -> io::Result { match proto { Protocol::TCP => self.tcp_natlook(bind_addr, peer_addr, proto), #[cfg(any(target_os = "macos", target_os = "ios"))] Protocol::UDP => self.udp_natlook(bind_addr, peer_addr, proto), _ => Err(io::ErrorKind::InvalidInput.into()), } } fn tcp_natlook(&self, bind_addr: &SocketAddr, peer_addr: &SocketAddr, proto: Protocol) -> io::Result { trace!("PF natlook peer: {}, bind: {}", peer_addr, bind_addr); unsafe { let mut pnl: pfioc_natlook = mem::zeroed(); match *bind_addr { SocketAddr::V4(ref v4) => { pnl.af = libc::AF_INET as libc::sa_family_t; let sockaddr = SockAddr::from(*v4); let sockaddr = sockaddr.as_ptr() as *const sockaddr_in; let addr: *const in_addr = ptr::addr_of!((*sockaddr).sin_addr) as *const _; let port: libc::in_port_t = (*sockaddr).sin_port; ptr::write_unaligned::(ptr::addr_of_mut!(pnl.daddr.pfa) as *mut _, *addr); cfg_if! { if #[cfg(any(target_os = "macos", target_os = "ios"))] { pnl.dxport.port = port; } else { pnl.dport = port; } } } SocketAddr::V6(ref v6) => { pnl.af = libc::AF_INET6 as libc::sa_family_t; let sockaddr = SockAddr::from(*v6); let sockaddr = sockaddr.as_ptr() as *const sockaddr_in6; let addr: *const in6_addr = ptr::addr_of!((*sockaddr).sin6_addr) as *const _; let port: libc::in_port_t = (*sockaddr).sin6_port; ptr::write_unaligned::(ptr::addr_of_mut!(pnl.daddr.pfa) as *mut _, *addr); cfg_if! { if #[cfg(any(target_os = "macos", target_os = "ios"))] { pnl.dxport.port = port; } else { pnl.dport = port; } } } } match *peer_addr { SocketAddr::V4(ref v4) => { if pnl.af != libc::AF_INET as libc::sa_family_t { return Err(Error::new(ErrorKind::InvalidInput, "client addr must be ipv4")); } let sockaddr = SockAddr::from(*v4); let sockaddr = sockaddr.as_ptr() as *const sockaddr_in; let addr: *const in_addr = ptr::addr_of!((*sockaddr).sin_addr) as *const _; let port: libc::in_port_t = (*sockaddr).sin_port; ptr::write_unaligned::(ptr::addr_of_mut!(pnl.saddr.pfa) as *mut _, *addr); cfg_if! { if #[cfg(any(target_os = "macos", target_os = "ios"))] { pnl.sxport.port = port; } else { pnl.sport = port; } } } SocketAddr::V6(ref v6) => { if pnl.af != libc::AF_INET6 as libc::sa_family_t { return Err(Error::new(ErrorKind::InvalidInput, "client addr must be ipv6")); } let sockaddr = SockAddr::from(*v6); let sockaddr = sockaddr.as_ptr() as *const sockaddr_in6; let addr: *const in6_addr = ptr::addr_of!((*sockaddr).sin6_addr) as *const _; let port: libc::in_port_t = (*sockaddr).sin6_port; ptr::write_unaligned::(ptr::addr_of_mut!(pnl.saddr.pfa) as *mut _, *addr); cfg_if! { if #[cfg(any(target_os = "macos", target_os = "ios"))] { pnl.sxport.port = port; } else { pnl.sport = port; } } } } pnl.proto = i32::from(proto) as u8; pnl.direction = PF_OUT as u8; if let Err(err) = ioc_natlook(self.fd, &mut pnl) { return Err(Error::from_raw_os_error(err as i32)); } let (_, dst_addr) = SockAddr::try_init(|dst_addr, addr_len| { if pnl.af == libc::AF_INET as libc::sa_family_t { let dst_addr: &mut sockaddr_in = &mut *(dst_addr as *mut _); dst_addr.sin_family = pnl.af; cfg_if! { if #[cfg(any(target_os = "macos", target_os = "ios"))] { dst_addr.sin_port = pnl.rdxport.port; } else { dst_addr.sin_port = pnl.rdport; } } ptr::write_unaligned::( ptr::addr_of_mut!(dst_addr.sin_addr), ptr::read::(ptr::addr_of!(pnl.rdaddr.pfa) as *const _), ); *addr_len = mem::size_of_val(&dst_addr.sin_addr) as libc::socklen_t; } else if pnl.af == libc::AF_INET6 as libc::sa_family_t { let dst_addr: &mut sockaddr_in6 = &mut *(dst_addr as *mut _); dst_addr.sin6_family = pnl.af; cfg_if! { if #[cfg(any(target_os = "macos", target_os = "ios"))] { dst_addr.sin6_port = pnl.rdxport.port; } else { dst_addr.sin6_port = pnl.rdport; } } ptr::write_unaligned::( ptr::addr_of_mut!(dst_addr.sin6_addr), ptr::read::(ptr::addr_of!(pnl.rdaddr.pfa) as *const _), ); *addr_len = mem::size_of_val(&dst_addr.sin6_addr) as libc::socklen_t; } else { unreachable!("sockaddr should be either ipv4 or ipv6"); } Ok(()) })?; Ok(dst_addr.as_socket().expect("SocketAddr")) } } #[cfg(any(target_os = "macos", target_os = "ios"))] fn udp_natlook(&self, bind_addr: &SocketAddr, peer_addr: &SocketAddr, _proto: Protocol) -> io::Result { unsafe { // Get all states // https://man.freebsd.org/cgi/man.cgi?query=pf&sektion=4&manpath=OpenBSD // DIOCGETSTATES let mut states: pfioc_states = mem::zeroed(); let mut states_buffer = vec![0u8; 8192]; loop { states.ps_len = states_buffer.len() as _; states.ps_u.psu_buf = states_buffer.as_mut_ptr() as *mut _; if let Err(err) = ioc_getstates(self.fd, &mut states) { return Err(Error::from_raw_os_error(err as i32)); } if states.ps_len as usize <= states_buffer.len() { break; } // Resize to fit all states // > On exit, ps_len is always set to the total size re- // > quired to hold all state table entries states_buffer.resize(states.ps_len as usize, 0); } let bind_addr_sockaddr = SockAddr::from(*bind_addr); let peer_addr_sockaddr = SockAddr::from(*peer_addr); let mut bind_addr_pfaddr: pf_addr = mem::zeroed(); let mut peer_addr_pfaddr: pf_addr = mem::zeroed(); match bind_addr_sockaddr.family() as libc::c_int { libc::AF_INET => { let sockaddr: *const sockaddr_in = bind_addr_sockaddr.as_ptr() as *const _; ptr::write_unaligned::( ptr::addr_of_mut!(bind_addr_pfaddr.pfa) as *mut _, (*sockaddr).sin_addr, ); } libc::AF_INET6 => { let sockaddr: *const sockaddr_in6 = bind_addr_sockaddr.as_ptr() as *const _; ptr::write_unaligned::( ptr::addr_of_mut!(bind_addr_pfaddr.pfa) as *mut _, (*sockaddr).sin6_addr, ); } _ => unreachable!("bind_addr family = {}", bind_addr_sockaddr.family()), } match peer_addr_sockaddr.family() as libc::c_int { libc::AF_INET => { let sockaddr: *const sockaddr_in = peer_addr_sockaddr.as_ptr() as *const _; ptr::write_unaligned::( ptr::addr_of_mut!(peer_addr_pfaddr.pfa) as *mut _, (*sockaddr).sin_addr, ); } libc::AF_INET6 => { let sockaddr: *const sockaddr_in6 = peer_addr_sockaddr.as_ptr() as *const _; ptr::write_unaligned::( ptr::addr_of_mut!(peer_addr_pfaddr.pfa) as *mut _, (*sockaddr).sin6_addr, ); } _ => unreachable!("peer_addr family = {}", peer_addr_sockaddr.family()), } let states_count = states.ps_len as usize / mem::size_of::(); for i in 0..states_count { let state = &*(states.ps_u.psu_states.add(i)); if state.proto == libc::IPPROTO_UDP as u8 { cfg_if! { if #[cfg(any(target_os = "macos", target_os = "ios"))] { let dst_port = state.lan.xport.port; let src_port = state.ext_gwy.xport.port; let actual_dst_port = state.gwy.xport.port; } else { let dst_port = state.lan.port; let src_port = state.ext_gwy.port; let actual_dst_port = state.gwy.port; } } let dst_addr_eq = libc::memcmp( &bind_addr_pfaddr as *const _ as *const _, ptr::addr_of!(state.lan.addr.pfa) as *const _, mem::size_of::(), ) == 0; let src_addr_eq = libc::memcmp( &peer_addr_pfaddr as *const _ as *const _, ptr::addr_of!(state.ext_gwy.addr.pfa) as *const _, mem::size_of::(), ) == 0; if src_addr_eq && src_port == peer_addr.port() && dst_addr_eq && dst_port == bind_addr.port() { let actual_dst_addr = match state.af_gwy as libc::c_int { libc::AF_INET => { let (_, actual_dst_addr) = SockAddr::try_init(|sockaddr, len| { let addr = &mut *(sockaddr as *mut sockaddr_in); addr.sin_family = libc::AF_INET as libc::sa_family_t; ptr::write_unaligned::( ptr::addr_of_mut!(addr.sin_addr), ptr::read_unaligned::(ptr::addr_of!(state.gwy.addr.pfa) as *const _), ); addr.sin_port = actual_dst_port as libc::in_port_t; ptr::write(len, mem::size_of::() as libc::socklen_t); Ok(()) }) .unwrap(); actual_dst_addr } libc::AF_INET6 => { let (_, actual_dst_addr) = SockAddr::try_init(|sockaddr, len| { let addr = &mut *(sockaddr as *mut sockaddr_in6); addr.sin6_family = libc::AF_INET6 as libc::sa_family_t; ptr::write_unaligned::( ptr::addr_of_mut!(addr.sin6_addr), ptr::read_unaligned::(ptr::addr_of!(state.gwy.addr.pfa) as *const _), ); addr.sin6_port = actual_dst_port as libc::in_port_t; ptr::write(len, mem::size_of::() as libc::socklen_t); Ok(()) }) .unwrap(); actual_dst_addr } _ => { return Err(io::Error::other(format!( "state.af_gwy {} is not a valid address family", state.af_gwy ))); } }; return Ok(actual_dst_addr.as_socket().expect("SocketAddr")); } } } } Err(io::Error::other(format!( "natlook UDP binding {}, {} not found", bind_addr, peer_addr ))) } } impl Drop for PacketFilter { fn drop(&mut self) { unsafe { libc::close(self.fd); } } } pub static PF: LazyLock = LazyLock::new(|| match PacketFilter::open() { Ok(pf) => pf, Err(err) if err.kind() == ErrorKind::PermissionDenied => { panic!("open /dev/pf permission denied, consider restart with root user"); } Err(err) => { panic!("open /dev/pf {err}"); } }); ================================================ FILE: crates/shadowsocks-service/src/local/redir/sys/unix/mod.rs ================================================ use cfg_if::cfg_if; cfg_if! { if #[cfg(any(target_os = "macos", target_os = "ios", target_os = "freebsd"))] { pub mod bsd_pf; } } cfg_if! { if #[cfg(any(target_os = "macos", target_os = "ios"))] { #[path = "pfvar_bindgen_macos.rs"] #[allow(dead_code, non_upper_case_globals, non_snake_case, non_camel_case_types)] #[allow(clippy::useless_transmute, clippy::too_many_arguments, clippy::unnecessary_cast)] mod pfvar; } else if #[cfg(target_os = "freebsd")] { #[path = "pfvar_bindgen_freebsd.rs"] #[allow(dead_code, non_upper_case_globals, non_snake_case, non_camel_case_types)] #[allow(clippy::useless_transmute, clippy::too_many_arguments, clippy::unnecessary_cast)] mod pfvar; } else if #[cfg(target_os = "openbsd")] { #[path = "pfvar_bindgen_openbsd.rs"] #[allow(dead_code, non_upper_case_globals, non_snake_case, non_camel_case_types)] #[allow(clippy::useless_transmute, clippy::too_many_arguments, clippy::unnecessary_cast)] mod pfvar; } } ================================================ FILE: crates/shadowsocks-service/src/local/redir/sys/unix/pfvar_bindgen_freebsd.rs ================================================ // automatically generated by rust-bindgen 0.69.2 pub const BSD: u32 = 199506; pub const BSD4_3: u32 = 1; pub const BSD4_4: u32 = 1; pub const __FreeBSD_version: u32 = 1400097; pub const __GNUCLIKE_ASM: u32 = 3; pub const __GNUCLIKE___TYPEOF: u32 = 1; pub const __GNUCLIKE___SECTION: u32 = 1; pub const __GNUCLIKE_CTOR_SECTION_HANDLING: u32 = 1; pub const __GNUCLIKE_BUILTIN_CONSTANT_P: u32 = 1; pub const __GNUCLIKE_BUILTIN_VARARGS: u32 = 1; pub const __GNUCLIKE_BUILTIN_STDARG: u32 = 1; pub const __GNUCLIKE_BUILTIN_VAALIST: u32 = 1; pub const __GNUC_VA_LIST_COMPATIBILITY: u32 = 1; pub const __GNUCLIKE_BUILTIN_NEXT_ARG: u32 = 1; pub const __GNUCLIKE_BUILTIN_MEMCPY: u32 = 1; pub const __CC_SUPPORTS_INLINE: u32 = 1; pub const __CC_SUPPORTS___INLINE: u32 = 1; pub const __CC_SUPPORTS___INLINE__: u32 = 1; pub const __CC_SUPPORTS___FUNC__: u32 = 1; pub const __CC_SUPPORTS_WARNING: u32 = 1; pub const __CC_SUPPORTS_VARADIC_XXX: u32 = 1; pub const __CC_SUPPORTS_DYNAMIC_ARRAY_INIT: u32 = 1; pub const __POSIX_VISIBLE: u32 = 200809; pub const __XSI_VISIBLE: u32 = 700; pub const __BSD_VISIBLE: u32 = 1; pub const __ISO_C_VISIBLE: u32 = 2011; pub const __EXT1_VISIBLE: u32 = 1; pub const __CHAR_BIT: u32 = 8; pub const __SCHAR_MAX: u32 = 127; pub const __SCHAR_MIN: i32 = -128; pub const __UCHAR_MAX: u32 = 255; pub const __USHRT_MAX: u32 = 65535; pub const __SHRT_MAX: u32 = 32767; pub const __SHRT_MIN: i32 = -32768; pub const __UINT_MAX: u32 = 4294967295; pub const __INT_MAX: u32 = 2147483647; pub const __INT_MIN: i32 = -2147483648; pub const __ULONG_MAX: i32 = -1; pub const __LONG_MAX: u64 = 9223372036854775807; pub const __LONG_MIN: i64 = -9223372036854775808; pub const __ULLONG_MAX: i32 = -1; pub const __LLONG_MAX: u64 = 9223372036854775807; pub const __LLONG_MIN: i64 = -9223372036854775808; pub const __SSIZE_MAX: u64 = 9223372036854775807; pub const __SIZE_T_MAX: i32 = -1; pub const __OFF_MAX: u64 = 9223372036854775807; pub const __OFF_MIN: i64 = -9223372036854775808; pub const __UQUAD_MAX: i32 = -1; pub const __QUAD_MAX: u64 = 9223372036854775807; pub const __QUAD_MIN: i64 = -9223372036854775808; pub const __LONG_BIT: u32 = 64; pub const __WORD_BIT: u32 = 32; pub const __MINSIGSTKSZ: u32 = 2048; pub const __WCHAR_MIN: i32 = -2147483648; pub const __WCHAR_MAX: u32 = 2147483647; pub const _QUAD_HIGHWORD: u32 = 1; pub const _QUAD_LOWWORD: u32 = 0; pub const _SIG_WORDS: u32 = 4; pub const _SIG_MAXSIG: u32 = 128; pub const FD_SETSIZE: u32 = 1024; pub const ARG_MAX: u32 = 524288; pub const CHILD_MAX: u32 = 40; pub const MAX_CANON: u32 = 255; pub const MAX_INPUT: u32 = 255; pub const NAME_MAX: u32 = 255; pub const NGROUPS_MAX: u32 = 1023; pub const OPEN_MAX: u32 = 64; pub const PATH_MAX: u32 = 1024; pub const PIPE_BUF: u32 = 512; pub const IOV_MAX: u32 = 1024; pub const MAXCOMLEN: u32 = 19; pub const MAXINTERP: u32 = 1024; pub const MAXLOGNAME: u32 = 33; pub const MAXUPRC: u32 = 40; pub const NCARGS: u32 = 524288; pub const NGROUPS: u32 = 1024; pub const NOFILE: u32 = 64; pub const NOGROUP: u32 = 65535; pub const MAXHOSTNAMELEN: u32 = 256; pub const SPECNAMELEN: u32 = 255; pub const _X86_SIGNAL_H: u32 = 1; pub const SIGHUP: u32 = 1; pub const SIGINT: u32 = 2; pub const SIGQUIT: u32 = 3; pub const SIGILL: u32 = 4; pub const SIGTRAP: u32 = 5; pub const SIGABRT: u32 = 6; pub const SIGIOT: u32 = 6; pub const SIGEMT: u32 = 7; pub const SIGFPE: u32 = 8; pub const SIGKILL: u32 = 9; pub const SIGBUS: u32 = 10; pub const SIGSEGV: u32 = 11; pub const SIGSYS: u32 = 12; pub const SIGPIPE: u32 = 13; pub const SIGALRM: u32 = 14; pub const SIGTERM: u32 = 15; pub const SIGURG: u32 = 16; pub const SIGSTOP: u32 = 17; pub const SIGTSTP: u32 = 18; pub const SIGCONT: u32 = 19; pub const SIGCHLD: u32 = 20; pub const SIGTTIN: u32 = 21; pub const SIGTTOU: u32 = 22; pub const SIGIO: u32 = 23; pub const SIGXCPU: u32 = 24; pub const SIGXFSZ: u32 = 25; pub const SIGVTALRM: u32 = 26; pub const SIGPROF: u32 = 27; pub const SIGWINCH: u32 = 28; pub const SIGINFO: u32 = 29; pub const SIGUSR1: u32 = 30; pub const SIGUSR2: u32 = 31; pub const SIGTHR: u32 = 32; pub const SIGLWP: u32 = 32; pub const SIGLIBRT: u32 = 33; pub const SIGRTMIN: u32 = 65; pub const SIGRTMAX: u32 = 126; pub const SIGEV_NONE: u32 = 0; pub const SIGEV_SIGNAL: u32 = 1; pub const SIGEV_THREAD: u32 = 2; pub const SIGEV_KEVENT: u32 = 3; pub const SIGEV_THREAD_ID: u32 = 4; pub const ILL_ILLOPC: u32 = 1; pub const ILL_ILLOPN: u32 = 2; pub const ILL_ILLADR: u32 = 3; pub const ILL_ILLTRP: u32 = 4; pub const ILL_PRVOPC: u32 = 5; pub const ILL_PRVREG: u32 = 6; pub const ILL_COPROC: u32 = 7; pub const ILL_BADSTK: u32 = 8; pub const BUS_ADRALN: u32 = 1; pub const BUS_ADRERR: u32 = 2; pub const BUS_OBJERR: u32 = 3; pub const BUS_OOMERR: u32 = 100; pub const SEGV_MAPERR: u32 = 1; pub const SEGV_ACCERR: u32 = 2; pub const SEGV_PKUERR: u32 = 100; pub const FPE_INTOVF: u32 = 1; pub const FPE_INTDIV: u32 = 2; pub const FPE_FLTDIV: u32 = 3; pub const FPE_FLTOVF: u32 = 4; pub const FPE_FLTUND: u32 = 5; pub const FPE_FLTRES: u32 = 6; pub const FPE_FLTINV: u32 = 7; pub const FPE_FLTSUB: u32 = 8; pub const FPE_FLTIDO: u32 = 9; pub const TRAP_BRKPT: u32 = 1; pub const TRAP_TRACE: u32 = 2; pub const TRAP_DTRACE: u32 = 3; pub const TRAP_CAP: u32 = 4; pub const CLD_EXITED: u32 = 1; pub const CLD_KILLED: u32 = 2; pub const CLD_DUMPED: u32 = 3; pub const CLD_TRAPPED: u32 = 4; pub const CLD_STOPPED: u32 = 5; pub const CLD_CONTINUED: u32 = 6; pub const POLL_IN: u32 = 1; pub const POLL_OUT: u32 = 2; pub const POLL_MSG: u32 = 3; pub const POLL_ERR: u32 = 4; pub const POLL_PRI: u32 = 5; pub const POLL_HUP: u32 = 6; pub const SA_NOCLDSTOP: u32 = 8; pub const SA_ONSTACK: u32 = 1; pub const SA_RESTART: u32 = 2; pub const SA_RESETHAND: u32 = 4; pub const SA_NODEFER: u32 = 16; pub const SA_NOCLDWAIT: u32 = 32; pub const SA_SIGINFO: u32 = 64; pub const NSIG: u32 = 32; pub const SI_NOINFO: u32 = 0; pub const SI_USER: u32 = 65537; pub const SI_QUEUE: u32 = 65538; pub const SI_TIMER: u32 = 65539; pub const SI_ASYNCIO: u32 = 65540; pub const SI_MESGQ: u32 = 65541; pub const SI_KERNEL: u32 = 65542; pub const SI_LWP: u32 = 65543; pub const SI_UNDEFINED: u32 = 0; pub const SS_ONSTACK: u32 = 1; pub const SS_DISABLE: u32 = 4; pub const MINSIGSTKSZ: u32 = 2048; pub const SIGSTKSZ: u32 = 34816; pub const SV_ONSTACK: u32 = 1; pub const SV_INTERRUPT: u32 = 2; pub const SV_RESETHAND: u32 = 4; pub const SV_NODEFER: u32 = 16; pub const SV_NOCLDSTOP: u32 = 8; pub const SV_SIGINFO: u32 = 64; pub const SIG_BLOCK: u32 = 1; pub const SIG_UNBLOCK: u32 = 2; pub const SIG_SETMASK: u32 = 3; pub const MACHINE: &[u8; 6] = b"amd64\0"; pub const MACHINE_ARCH: &[u8; 6] = b"amd64\0"; pub const MACHINE_ARCH32: &[u8; 5] = b"i386\0"; pub const MAXCPU: u32 = 1; pub const MAXMEMDOM: u32 = 8; pub const CACHE_LINE_SHIFT: u32 = 6; pub const CACHE_LINE_SIZE: u32 = 64; pub const NPTEPGSHIFT: u32 = 9; pub const PAGE_SHIFT: u32 = 12; pub const PAGE_SIZE: u32 = 4096; pub const PAGE_MASK: u32 = 4095; pub const NPDEPGSHIFT: u32 = 9; pub const PDRSHIFT: u32 = 21; pub const NBPDR: u32 = 2097152; pub const PDRMASK: u32 = 2097151; pub const NPDPEPGSHIFT: u32 = 9; pub const PDPSHIFT: u32 = 30; pub const NBPDP: u32 = 1073741824; pub const PDPMASK: u32 = 1073741823; pub const NPML4EPGSHIFT: u32 = 9; pub const PML4SHIFT: u32 = 39; pub const NBPML4: u64 = 549755813888; pub const PML4MASK: u64 = 549755813887; pub const NPML5EPGSHIFT: u32 = 9; pub const PML5SHIFT: u32 = 48; pub const NBPML5: u64 = 281474976710656; pub const PML5MASK: u64 = 281474976710655; pub const MAXPAGESIZES: u32 = 3; pub const IOPAGES: u32 = 2; pub const IOPERM_BITMAP_SIZE: u32 = 8193; pub const KSTACK_PAGES: u32 = 4; pub const KSTACK_GUARD_PAGES: u32 = 1; pub const CHAR_BIT: u32 = 8; pub const SCHAR_MAX: u32 = 127; pub const SCHAR_MIN: i32 = -128; pub const UCHAR_MAX: u32 = 255; pub const CHAR_MAX: u32 = 127; pub const CHAR_MIN: i32 = -128; pub const USHRT_MAX: u32 = 65535; pub const SHRT_MAX: u32 = 32767; pub const SHRT_MIN: i32 = -32768; pub const UINT_MAX: u32 = 4294967295; pub const INT_MAX: u32 = 2147483647; pub const INT_MIN: i32 = -2147483648; pub const ULONG_MAX: i32 = -1; pub const LONG_MAX: u64 = 9223372036854775807; pub const LONG_MIN: i64 = -9223372036854775808; pub const ULLONG_MAX: i32 = -1; pub const LLONG_MAX: u64 = 9223372036854775807; pub const LLONG_MIN: i64 = -9223372036854775808; pub const SSIZE_MAX: u64 = 9223372036854775807; pub const SIZE_T_MAX: i32 = -1; pub const OFF_MAX: u64 = 9223372036854775807; pub const OFF_MIN: i64 = -9223372036854775808; pub const GID_MAX: u32 = 4294967295; pub const UID_MAX: u32 = 4294967295; pub const UQUAD_MAX: i32 = -1; pub const QUAD_MAX: u64 = 9223372036854775807; pub const QUAD_MIN: i64 = -9223372036854775808; pub const LONG_BIT: u32 = 64; pub const WORD_BIT: u32 = 32; pub const MQ_PRIO_MAX: u32 = 64; pub const DEV_BSHIFT: u32 = 9; pub const DEV_BSIZE: u32 = 512; pub const BLKDEV_IOSIZE: u32 = 4096; pub const DFLTPHYS: u32 = 65536; pub const MAXPHYS: u32 = 1048576; pub const MAXDUMPPGS: u32 = 16; pub const MSIZE: u32 = 256; pub const MCLSHIFT: u32 = 11; pub const MCLBYTES: u32 = 2048; pub const MJUMPAGESIZE: u32 = 4096; pub const MJUM9BYTES: u32 = 9216; pub const MJUM16BYTES: u32 = 16384; pub const PRIMASK: u32 = 255; pub const PCATCH: u32 = 256; pub const PDROP: u32 = 512; pub const PNOLOCK: u32 = 1024; pub const PRILASTFLAG: u32 = 1024; pub const NZERO: u32 = 0; pub const NBBY: u32 = 8; pub const CMASK: u32 = 18; pub const MAXBSIZE: u32 = 65536; pub const MAXBCACHEBUF: u32 = 65536; pub const BKVASIZE: u32 = 16384; pub const BKVAMASK: u32 = 16383; pub const MAXPATHLEN: u32 = 1024; pub const MAXSYMLINKS: u32 = 32; pub const FSHIFT: u32 = 11; pub const FSCALE: u32 = 2048; pub const CPU_MAXSIZE: u32 = 1024; pub const CPU_SETSIZE: u32 = 1024; pub const CPU_LEVEL_ROOT: u32 = 1; pub const CPU_LEVEL_CPUSET: u32 = 2; pub const CPU_LEVEL_WHICH: u32 = 3; pub const CPU_WHICH_TID: u32 = 1; pub const CPU_WHICH_PID: u32 = 2; pub const CPU_WHICH_CPUSET: u32 = 3; pub const CPU_WHICH_IRQ: u32 = 4; pub const CPU_WHICH_JAIL: u32 = 5; pub const CPU_WHICH_DOMAIN: u32 = 6; pub const CPU_WHICH_INTRHANDLER: u32 = 7; pub const CPU_WHICH_ITHREAD: u32 = 8; pub const CPU_WHICH_TIDPID: u32 = 9; pub const CPUSET_INVALID: i32 = -1; pub const CPUSET_DEFAULT: u32 = 0; pub const M_NOWAIT: u32 = 1; pub const M_WAITOK: u32 = 2; pub const M_NORECLAIM: u32 = 128; pub const M_ZERO: u32 = 256; pub const M_NOVM: u32 = 512; pub const M_USE_RESERVE: u32 = 1024; pub const M_NODUMP: u32 = 2048; pub const M_FIRSTFIT: u32 = 4096; pub const M_BESTFIT: u32 = 8192; pub const M_EXEC: u32 = 16384; pub const M_NEXTFIT: u32 = 32768; pub const M_VERSION: u32 = 2020110501; pub const DTMALLOC_PROBE_MALLOC: u32 = 0; pub const DTMALLOC_PROBE_FREE: u32 = 1; pub const DTMALLOC_PROBE_MAX: u32 = 2; pub const MALLOC_TYPE_STREAM_VERSION: u32 = 1; pub const MALLOC_MAX_NAME: u32 = 32; pub const __bool_true_false_are_defined: u32 = 1; pub const false_: u32 = 0; pub const true_: u32 = 1; pub const INT8_MIN: i32 = -128; pub const INT16_MIN: i32 = -32768; pub const INT32_MIN: i32 = -2147483648; pub const INT8_MAX: u32 = 127; pub const INT16_MAX: u32 = 32767; pub const INT32_MAX: u32 = 2147483647; pub const UINT8_MAX: u32 = 255; pub const UINT16_MAX: u32 = 65535; pub const UINT32_MAX: u32 = 4294967295; pub const INT64_MIN: i64 = -9223372036854775808; pub const INT64_MAX: u64 = 9223372036854775807; pub const UINT64_MAX: i32 = -1; pub const INT_LEAST8_MIN: i32 = -128; pub const INT_LEAST16_MIN: i32 = -32768; pub const INT_LEAST32_MIN: i32 = -2147483648; pub const INT_LEAST64_MIN: i64 = -9223372036854775808; pub const INT_LEAST8_MAX: u32 = 127; pub const INT_LEAST16_MAX: u32 = 32767; pub const INT_LEAST32_MAX: u32 = 2147483647; pub const INT_LEAST64_MAX: u64 = 9223372036854775807; pub const UINT_LEAST8_MAX: u32 = 255; pub const UINT_LEAST16_MAX: u32 = 65535; pub const UINT_LEAST32_MAX: u32 = 4294967295; pub const UINT_LEAST64_MAX: i32 = -1; pub const INT_FAST8_MIN: i32 = -2147483648; pub const INT_FAST16_MIN: i32 = -2147483648; pub const INT_FAST32_MIN: i32 = -2147483648; pub const INT_FAST64_MIN: i64 = -9223372036854775808; pub const INT_FAST8_MAX: u32 = 2147483647; pub const INT_FAST16_MAX: u32 = 2147483647; pub const INT_FAST32_MAX: u32 = 2147483647; pub const INT_FAST64_MAX: u64 = 9223372036854775807; pub const UINT_FAST8_MAX: u32 = 4294967295; pub const UINT_FAST16_MAX: u32 = 4294967295; pub const UINT_FAST32_MAX: u32 = 4294967295; pub const UINT_FAST64_MAX: i32 = -1; pub const INTPTR_MIN: i64 = -9223372036854775808; pub const INTPTR_MAX: u64 = 9223372036854775807; pub const UINTPTR_MAX: i32 = -1; pub const INTMAX_MIN: i64 = -9223372036854775808; pub const INTMAX_MAX: u64 = 9223372036854775807; pub const UINTMAX_MAX: i32 = -1; pub const PTRDIFF_MIN: i64 = -9223372036854775808; pub const PTRDIFF_MAX: u64 = 9223372036854775807; pub const SIG_ATOMIC_MIN: i64 = -9223372036854775808; pub const SIG_ATOMIC_MAX: u64 = 9223372036854775807; pub const SIZE_MAX: i32 = -1; pub const WINT_MIN: i32 = -2147483648; pub const WINT_MAX: u32 = 2147483647; pub const __WORDSIZE: u32 = 64; pub const WCHAR_MIN: i32 = -2147483648; pub const WCHAR_MAX: u32 = 2147483647; pub const RSIZE_MAX: i32 = -1; pub const __SLBF: u32 = 1; pub const __SNBF: u32 = 2; pub const __SRD: u32 = 4; pub const __SWR: u32 = 8; pub const __SRW: u32 = 16; pub const __SEOF: u32 = 32; pub const __SERR: u32 = 64; pub const __SMBF: u32 = 128; pub const __SAPP: u32 = 256; pub const __SSTR: u32 = 512; pub const __SOPT: u32 = 1024; pub const __SNPT: u32 = 2048; pub const __SOFF: u32 = 4096; pub const __SMOD: u32 = 8192; pub const __SALC: u32 = 16384; pub const __SIGN: u32 = 32768; pub const __S2OAP: u32 = 1; pub const _IOFBF: u32 = 0; pub const _IOLBF: u32 = 1; pub const _IONBF: u32 = 2; pub const BUFSIZ: u32 = 1024; pub const EOF: i32 = -1; pub const FOPEN_MAX: u32 = 20; pub const FILENAME_MAX: u32 = 1024; pub const P_tmpdir: &[u8; 6] = b"/tmp/\0"; pub const L_tmpnam: u32 = 1024; pub const TMP_MAX: u32 = 308915776; pub const SEEK_SET: u32 = 0; pub const SEEK_CUR: u32 = 1; pub const SEEK_END: u32 = 2; pub const L_cuserid: u32 = 17; pub const L_ctermid: u32 = 1024; pub const NV_NAME_MAX: u32 = 2048; pub const NV_TYPE_NONE: u32 = 0; pub const NV_TYPE_NULL: u32 = 1; pub const NV_TYPE_BOOL: u32 = 2; pub const NV_TYPE_NUMBER: u32 = 3; pub const NV_TYPE_STRING: u32 = 4; pub const NV_TYPE_NVLIST: u32 = 5; pub const NV_TYPE_DESCRIPTOR: u32 = 6; pub const NV_TYPE_BINARY: u32 = 7; pub const NV_TYPE_BOOL_ARRAY: u32 = 8; pub const NV_TYPE_NUMBER_ARRAY: u32 = 9; pub const NV_TYPE_STRING_ARRAY: u32 = 10; pub const NV_TYPE_NVLIST_ARRAY: u32 = 11; pub const NV_TYPE_DESCRIPTOR_ARRAY: u32 = 12; pub const NV_FLAG_IGNORE_CASE: u32 = 1; pub const NV_FLAG_NO_UNIQUE: u32 = 2; pub const REFCOUNT_SATURATION_VALUE: u32 = 3221225472; pub const _DTRACE_VERSION: u32 = 1; pub const CTL_MAXNAME: u32 = 24; pub const CTLTYPE: u32 = 15; pub const CTLTYPE_NODE: u32 = 1; pub const CTLTYPE_INT: u32 = 2; pub const CTLTYPE_STRING: u32 = 3; pub const CTLTYPE_S64: u32 = 4; pub const CTLTYPE_OPAQUE: u32 = 5; pub const CTLTYPE_STRUCT: u32 = 5; pub const CTLTYPE_UINT: u32 = 6; pub const CTLTYPE_LONG: u32 = 7; pub const CTLTYPE_ULONG: u32 = 8; pub const CTLTYPE_U64: u32 = 9; pub const CTLTYPE_U8: u32 = 10; pub const CTLTYPE_U16: u32 = 11; pub const CTLTYPE_S8: u32 = 12; pub const CTLTYPE_S16: u32 = 13; pub const CTLTYPE_S32: u32 = 14; pub const CTLTYPE_U32: u32 = 15; pub const CTLFLAG_RD: u32 = 2147483648; pub const CTLFLAG_WR: u32 = 1073741824; pub const CTLFLAG_RW: u32 = 3221225472; pub const CTLFLAG_DORMANT: u32 = 536870912; pub const CTLFLAG_ANYBODY: u32 = 268435456; pub const CTLFLAG_SECURE: u32 = 134217728; pub const CTLFLAG_PRISON: u32 = 67108864; pub const CTLFLAG_DYN: u32 = 33554432; pub const CTLFLAG_SKIP: u32 = 16777216; pub const CTLMASK_SECURE: u32 = 15728640; pub const CTLFLAG_TUN: u32 = 524288; pub const CTLFLAG_RDTUN: u32 = 2148007936; pub const CTLFLAG_RWTUN: u32 = 3221749760; pub const CTLFLAG_MPSAFE: u32 = 262144; pub const CTLFLAG_VNET: u32 = 131072; pub const CTLFLAG_DYING: u32 = 65536; pub const CTLFLAG_CAPRD: u32 = 32768; pub const CTLFLAG_CAPWR: u32 = 16384; pub const CTLFLAG_STATS: u32 = 8192; pub const CTLFLAG_NOFETCH: u32 = 4096; pub const CTLFLAG_CAPRW: u32 = 49152; pub const CTLFLAG_NEEDGIANT: u32 = 2048; pub const CTLSHIFT_SECURE: u32 = 20; pub const CTLFLAG_SECURE1: u32 = 134217728; pub const CTLFLAG_SECURE2: u32 = 135266304; pub const CTLFLAG_SECURE3: u32 = 136314880; pub const OID_AUTO: i32 = -1; pub const CTL_AUTO_START: u32 = 256; pub const CTL_SYSCTL: u32 = 0; pub const CTL_KERN: u32 = 1; pub const CTL_VM: u32 = 2; pub const CTL_VFS: u32 = 3; pub const CTL_NET: u32 = 4; pub const CTL_DEBUG: u32 = 5; pub const CTL_HW: u32 = 6; pub const CTL_MACHDEP: u32 = 7; pub const CTL_USER: u32 = 8; pub const CTL_P1003_1B: u32 = 9; pub const CTL_SYSCTL_DEBUG: u32 = 0; pub const CTL_SYSCTL_NAME: u32 = 1; pub const CTL_SYSCTL_NEXT: u32 = 2; pub const CTL_SYSCTL_NAME2OID: u32 = 3; pub const CTL_SYSCTL_OIDFMT: u32 = 4; pub const CTL_SYSCTL_OIDDESCR: u32 = 5; pub const CTL_SYSCTL_OIDLABEL: u32 = 6; pub const CTL_SYSCTL_NEXTNOSKIP: u32 = 7; pub const KERN_OSTYPE: u32 = 1; pub const KERN_OSRELEASE: u32 = 2; pub const KERN_OSREV: u32 = 3; pub const KERN_VERSION: u32 = 4; pub const KERN_MAXVNODES: u32 = 5; pub const KERN_MAXPROC: u32 = 6; pub const KERN_MAXFILES: u32 = 7; pub const KERN_ARGMAX: u32 = 8; pub const KERN_SECURELVL: u32 = 9; pub const KERN_HOSTNAME: u32 = 10; pub const KERN_HOSTID: u32 = 11; pub const KERN_CLOCKRATE: u32 = 12; pub const KERN_PROC: u32 = 14; pub const KERN_FILE: u32 = 15; pub const KERN_PROF: u32 = 16; pub const KERN_POSIX1: u32 = 17; pub const KERN_NGROUPS: u32 = 18; pub const KERN_JOB_CONTROL: u32 = 19; pub const KERN_SAVED_IDS: u32 = 20; pub const KERN_BOOTTIME: u32 = 21; pub const KERN_NISDOMAINNAME: u32 = 22; pub const KERN_UPDATEINTERVAL: u32 = 23; pub const KERN_OSRELDATE: u32 = 24; pub const KERN_NTP_PLL: u32 = 25; pub const KERN_BOOTFILE: u32 = 26; pub const KERN_MAXFILESPERPROC: u32 = 27; pub const KERN_MAXPROCPERUID: u32 = 28; pub const KERN_DUMPDEV: u32 = 29; pub const KERN_IPC: u32 = 30; pub const KERN_DUMMY: u32 = 31; pub const KERN_PS_STRINGS: u32 = 32; pub const KERN_USRSTACK: u32 = 33; pub const KERN_LOGSIGEXIT: u32 = 34; pub const KERN_IOV_MAX: u32 = 35; pub const KERN_HOSTUUID: u32 = 36; pub const KERN_ARND: u32 = 37; pub const KERN_MAXPHYS: u32 = 38; pub const KERN_LOCKF: u32 = 39; pub const KERN_PROC_ALL: u32 = 0; pub const KERN_PROC_PID: u32 = 1; pub const KERN_PROC_PGRP: u32 = 2; pub const KERN_PROC_SESSION: u32 = 3; pub const KERN_PROC_TTY: u32 = 4; pub const KERN_PROC_UID: u32 = 5; pub const KERN_PROC_RUID: u32 = 6; pub const KERN_PROC_ARGS: u32 = 7; pub const KERN_PROC_PROC: u32 = 8; pub const KERN_PROC_SV_NAME: u32 = 9; pub const KERN_PROC_RGID: u32 = 10; pub const KERN_PROC_GID: u32 = 11; pub const KERN_PROC_PATHNAME: u32 = 12; pub const KERN_PROC_OVMMAP: u32 = 13; pub const KERN_PROC_OFILEDESC: u32 = 14; pub const KERN_PROC_KSTACK: u32 = 15; pub const KERN_PROC_INC_THREAD: u32 = 16; pub const KERN_PROC_VMMAP: u32 = 32; pub const KERN_PROC_FILEDESC: u32 = 33; pub const KERN_PROC_GROUPS: u32 = 34; pub const KERN_PROC_ENV: u32 = 35; pub const KERN_PROC_AUXV: u32 = 36; pub const KERN_PROC_RLIMIT: u32 = 37; pub const KERN_PROC_PS_STRINGS: u32 = 38; pub const KERN_PROC_UMASK: u32 = 39; pub const KERN_PROC_OSREL: u32 = 40; pub const KERN_PROC_SIGTRAMP: u32 = 41; pub const KERN_PROC_CWD: u32 = 42; pub const KERN_PROC_NFDS: u32 = 43; pub const KERN_PROC_SIGFASTBLK: u32 = 44; pub const KERN_PROC_VM_LAYOUT: u32 = 45; pub const KIPC_MAXSOCKBUF: u32 = 1; pub const KIPC_SOCKBUF_WASTE: u32 = 2; pub const KIPC_SOMAXCONN: u32 = 3; pub const KIPC_MAX_LINKHDR: u32 = 4; pub const KIPC_MAX_PROTOHDR: u32 = 5; pub const KIPC_MAX_HDR: u32 = 6; pub const KIPC_MAX_DATALEN: u32 = 7; pub const HW_MACHINE: u32 = 1; pub const HW_MODEL: u32 = 2; pub const HW_NCPU: u32 = 3; pub const HW_BYTEORDER: u32 = 4; pub const HW_PHYSMEM: u32 = 5; pub const HW_USERMEM: u32 = 6; pub const HW_PAGESIZE: u32 = 7; pub const HW_DISKNAMES: u32 = 8; pub const HW_DISKSTATS: u32 = 9; pub const HW_FLOATINGPT: u32 = 10; pub const HW_MACHINE_ARCH: u32 = 11; pub const HW_REALMEM: u32 = 12; pub const USER_CS_PATH: u32 = 1; pub const USER_BC_BASE_MAX: u32 = 2; pub const USER_BC_DIM_MAX: u32 = 3; pub const USER_BC_SCALE_MAX: u32 = 4; pub const USER_BC_STRING_MAX: u32 = 5; pub const USER_COLL_WEIGHTS_MAX: u32 = 6; pub const USER_EXPR_NEST_MAX: u32 = 7; pub const USER_LINE_MAX: u32 = 8; pub const USER_RE_DUP_MAX: u32 = 9; pub const USER_POSIX2_VERSION: u32 = 10; pub const USER_POSIX2_C_BIND: u32 = 11; pub const USER_POSIX2_C_DEV: u32 = 12; pub const USER_POSIX2_CHAR_TERM: u32 = 13; pub const USER_POSIX2_FORT_DEV: u32 = 14; pub const USER_POSIX2_FORT_RUN: u32 = 15; pub const USER_POSIX2_LOCALEDEF: u32 = 16; pub const USER_POSIX2_SW_DEV: u32 = 17; pub const USER_POSIX2_UPE: u32 = 18; pub const USER_STREAM_MAX: u32 = 19; pub const USER_TZNAME_MAX: u32 = 20; pub const USER_LOCALBASE: u32 = 21; pub const CTL_P1003_1B_ASYNCHRONOUS_IO: u32 = 1; pub const CTL_P1003_1B_MAPPED_FILES: u32 = 2; pub const CTL_P1003_1B_MEMLOCK: u32 = 3; pub const CTL_P1003_1B_MEMLOCK_RANGE: u32 = 4; pub const CTL_P1003_1B_MEMORY_PROTECTION: u32 = 5; pub const CTL_P1003_1B_MESSAGE_PASSING: u32 = 6; pub const CTL_P1003_1B_PRIORITIZED_IO: u32 = 7; pub const CTL_P1003_1B_PRIORITY_SCHEDULING: u32 = 8; pub const CTL_P1003_1B_REALTIME_SIGNALS: u32 = 9; pub const CTL_P1003_1B_SEMAPHORES: u32 = 10; pub const CTL_P1003_1B_FSYNC: u32 = 11; pub const CTL_P1003_1B_SHARED_MEMORY_OBJECTS: u32 = 12; pub const CTL_P1003_1B_SYNCHRONIZED_IO: u32 = 13; pub const CTL_P1003_1B_TIMERS: u32 = 14; pub const CTL_P1003_1B_AIO_LISTIO_MAX: u32 = 15; pub const CTL_P1003_1B_AIO_MAX: u32 = 16; pub const CTL_P1003_1B_AIO_PRIO_DELTA_MAX: u32 = 17; pub const CTL_P1003_1B_DELAYTIMER_MAX: u32 = 18; pub const CTL_P1003_1B_MQ_OPEN_MAX: u32 = 19; pub const CTL_P1003_1B_PAGESIZE: u32 = 20; pub const CTL_P1003_1B_RTSIG_MAX: u32 = 21; pub const CTL_P1003_1B_SEM_NSEMS_MAX: u32 = 22; pub const CTL_P1003_1B_SEM_VALUE_MAX: u32 = 23; pub const CTL_P1003_1B_SIGQUEUE_MAX: u32 = 24; pub const CTL_P1003_1B_TIMER_MAX: u32 = 25; pub const KTR_GEN: u32 = 1; pub const KTR_NET: u32 = 2; pub const KTR_DEV: u32 = 4; pub const KTR_LOCK: u32 = 8; pub const KTR_SMP: u32 = 16; pub const KTR_SUBSYS: u32 = 32; pub const KTR_PMAP: u32 = 64; pub const KTR_MALLOC: u32 = 128; pub const KTR_TRAP: u32 = 256; pub const KTR_INTR: u32 = 512; pub const KTR_SIG: u32 = 1024; pub const KTR_SPARE2: u32 = 2048; pub const KTR_PROC: u32 = 4096; pub const KTR_SYSC: u32 = 8192; pub const KTR_INIT: u32 = 16384; pub const KTR_SPARE3: u32 = 32768; pub const KTR_SPARE4: u32 = 65536; pub const KTR_EVH: u32 = 131072; pub const KTR_VFS: u32 = 262144; pub const KTR_VOP: u32 = 524288; pub const KTR_VM: u32 = 1048576; pub const KTR_INET: u32 = 2097152; pub const KTR_RUNQ: u32 = 4194304; pub const KTR_SPARE5: u32 = 8388608; pub const KTR_UMA: u32 = 16777216; pub const KTR_CALLOUT: u32 = 33554432; pub const KTR_GEOM: u32 = 67108864; pub const KTR_BUSDMA: u32 = 134217728; pub const KTR_INET6: u32 = 268435456; pub const KTR_SCHED: u32 = 536870912; pub const KTR_BUF: u32 = 1073741824; pub const KTR_PTRACE: u32 = 2147483648; pub const KTR_ALL: u32 = 4294967295; pub const KTR_COMPILE: u32 = 0; pub const LC_SLEEPLOCK: u32 = 1; pub const LC_SPINLOCK: u32 = 2; pub const LC_SLEEPABLE: u32 = 4; pub const LC_RECURSABLE: u32 = 8; pub const LC_UPGRADABLE: u32 = 16; pub const LO_CLASSFLAGS: u32 = 65535; pub const LO_INITIALIZED: u32 = 65536; pub const LO_WITNESS: u32 = 131072; pub const LO_QUIET: u32 = 262144; pub const LO_RECURSABLE: u32 = 524288; pub const LO_SLEEPABLE: u32 = 1048576; pub const LO_UPGRADABLE: u32 = 2097152; pub const LO_DUPOK: u32 = 4194304; pub const LO_IS_VNODE: u32 = 8388608; pub const LO_CLASSMASK: u32 = 251658240; pub const LO_NOPROFILE: u32 = 268435456; pub const LO_NEW: u32 = 536870912; pub const LO_CLASSSHIFT: u32 = 24; pub const LOCK_CLASS_MAX: u32 = 15; pub const LOP_NEWORDER: u32 = 1; pub const LOP_QUIET: u32 = 2; pub const LOP_TRYLOCK: u32 = 4; pub const LOP_EXCLUSIVE: u32 = 8; pub const LOP_DUPOK: u32 = 16; pub const LOP_NOSLEEP: u32 = 32; pub const LA_MASKASSERT: u32 = 255; pub const LA_UNLOCKED: u32 = 0; pub const LA_LOCKED: u32 = 1; pub const LA_SLOCKED: u32 = 2; pub const LA_XLOCKED: u32 = 4; pub const LA_RECURSED: u32 = 8; pub const LA_NOTRECURSED: u32 = 16; pub const SX_LOCK_SHARED: u32 = 1; pub const SX_LOCK_SHARED_WAITERS: u32 = 2; pub const SX_LOCK_EXCLUSIVE_WAITERS: u32 = 4; pub const SX_LOCK_WRITE_SPINNER: u32 = 8; pub const SX_LOCK_RECURSED: u32 = 16; pub const SX_LOCK_FLAGMASK: u32 = 31; pub const SX_LOCK_WAITERS: u32 = 6; pub const SX_SHARERS_SHIFT: u32 = 5; pub const SX_ONE_SHARER: u32 = 32; pub const SX_LOCK_DESTROYED: u32 = 6; pub const SPLAY_NEGINF: i32 = -1; pub const SPLAY_INF: u32 = 1; pub const RB_STRICT_HST: u32 = 0; pub const RB_NEGINF: i32 = -1; pub const RB_INF: u32 = 1; pub const UMA_SMALLEST_UNIT: u32 = 8; pub const UMA_ZONE_UNMANAGED: u32 = 1; pub const UMA_ZONE_ZINIT: u32 = 2; pub const UMA_ZONE_CONTIG: u32 = 4; pub const UMA_ZONE_NOTOUCH: u32 = 8; pub const UMA_ZONE_MALLOC: u32 = 16; pub const UMA_ZONE_NOFREE: u32 = 32; pub const UMA_ZONE_MTXCLASS: u32 = 64; pub const UMA_ZONE_VM: u32 = 128; pub const UMA_ZONE_NOTPAGE: u32 = 256; pub const UMA_ZONE_SECONDARY: u32 = 512; pub const UMA_ZONE_NOBUCKET: u32 = 1024; pub const UMA_ZONE_MAXBUCKET: u32 = 2048; pub const UMA_ZONE_CACHESPREAD: u32 = 8192; pub const UMA_ZONE_NODUMP: u32 = 16384; pub const UMA_ZONE_PCPU: u32 = 32768; pub const UMA_ZONE_FIRSTTOUCH: u32 = 65536; pub const UMA_ZONE_ROUNDROBIN: u32 = 131072; pub const UMA_ZONE_SMR: u32 = 262144; pub const UMA_ZONE_NOKASAN: u32 = 524288; pub const UMA_ZONE_INHERIT: u32 = 754104; pub const UMA_ALIGN_CACHE: i32 = -1; pub const UMA_ANYDOMAIN: i32 = -1; pub const UMA_RECLAIM_DRAIN: u32 = 1; pub const UMA_RECLAIM_DRAIN_CPU: u32 = 2; pub const UMA_RECLAIM_TRIM: u32 = 3; pub const UMA_SLAB_BOOT: u32 = 1; pub const UMA_SLAB_KERNEL: u32 = 4; pub const UMA_SLAB_PRIV: u32 = 8; pub const UMA_STREAM_VERSION: u32 = 1; pub const UTH_MAX_NAME: u32 = 32; pub const UTH_ZONE_SECONDARY: u32 = 1; pub const CLOCK_REALTIME: u32 = 0; pub const CLOCK_VIRTUAL: u32 = 1; pub const CLOCK_PROF: u32 = 2; pub const CLOCK_MONOTONIC: u32 = 4; pub const CLOCK_UPTIME_FAST: u32 = 8; pub const CLOCK_UPTIME: u32 = 5; pub const CLOCK_UPTIME_PRECISE: u32 = 7; pub const CLOCK_REALTIME_PRECISE: u32 = 9; pub const CLOCK_REALTIME_FAST: u32 = 10; pub const CLOCK_MONOTONIC_PRECISE: u32 = 11; pub const CLOCK_MONOTONIC_FAST: u32 = 12; pub const CLOCK_SECOND: u32 = 13; pub const CLOCK_THREAD_CPUTIME_ID: u32 = 14; pub const CLOCK_PROCESS_CPUTIME_ID: u32 = 15; pub const CLOCK_BOOTTIME: u32 = 5; pub const CLOCK_REALTIME_COARSE: u32 = 10; pub const CLOCK_MONOTONIC_COARSE: u32 = 12; pub const TIMER_RELTIME: u32 = 0; pub const TIMER_ABSTIME: u32 = 1; pub const DST_NONE: u32 = 0; pub const DST_USA: u32 = 1; pub const DST_AUST: u32 = 2; pub const DST_WET: u32 = 3; pub const DST_MET: u32 = 4; pub const DST_EET: u32 = 5; pub const DST_CAN: u32 = 6; pub const SBT_MAX: u64 = 9223372036854775807; pub const ITIMER_REAL: u32 = 0; pub const ITIMER_VIRTUAL: u32 = 1; pub const ITIMER_PROF: u32 = 2; pub const CPUCLOCK_WHICH_PID: u32 = 0; pub const CPUCLOCK_WHICH_TID: u32 = 1; pub const CLK_TCK: u32 = 128; pub const CLOCKS_PER_SEC: u32 = 128; pub const TIME_UTC: u32 = 1; pub const TIME_MONOTONIC: u32 = 2; pub const SOCK_STREAM: u32 = 1; pub const SOCK_DGRAM: u32 = 2; pub const SOCK_RAW: u32 = 3; pub const SOCK_RDM: u32 = 4; pub const SOCK_SEQPACKET: u32 = 5; pub const SOCK_CLOEXEC: u32 = 268435456; pub const SOCK_NONBLOCK: u32 = 536870912; pub const SO_DEBUG: u32 = 1; pub const SO_ACCEPTCONN: u32 = 2; pub const SO_REUSEADDR: u32 = 4; pub const SO_KEEPALIVE: u32 = 8; pub const SO_DONTROUTE: u32 = 16; pub const SO_BROADCAST: u32 = 32; pub const SO_USELOOPBACK: u32 = 64; pub const SO_LINGER: u32 = 128; pub const SO_OOBINLINE: u32 = 256; pub const SO_REUSEPORT: u32 = 512; pub const SO_TIMESTAMP: u32 = 1024; pub const SO_NOSIGPIPE: u32 = 2048; pub const SO_ACCEPTFILTER: u32 = 4096; pub const SO_BINTIME: u32 = 8192; pub const SO_NO_OFFLOAD: u32 = 16384; pub const SO_NO_DDP: u32 = 32768; pub const SO_REUSEPORT_LB: u32 = 65536; pub const SO_RERROR: u32 = 131072; pub const SO_SNDBUF: u32 = 4097; pub const SO_RCVBUF: u32 = 4098; pub const SO_SNDLOWAT: u32 = 4099; pub const SO_RCVLOWAT: u32 = 4100; pub const SO_SNDTIMEO: u32 = 4101; pub const SO_RCVTIMEO: u32 = 4102; pub const SO_ERROR: u32 = 4103; pub const SO_TYPE: u32 = 4104; pub const SO_LABEL: u32 = 4105; pub const SO_PEERLABEL: u32 = 4112; pub const SO_LISTENQLIMIT: u32 = 4113; pub const SO_LISTENQLEN: u32 = 4114; pub const SO_LISTENINCQLEN: u32 = 4115; pub const SO_SETFIB: u32 = 4116; pub const SO_USER_COOKIE: u32 = 4117; pub const SO_PROTOCOL: u32 = 4118; pub const SO_PROTOTYPE: u32 = 4118; pub const SO_TS_CLOCK: u32 = 4119; pub const SO_MAX_PACING_RATE: u32 = 4120; pub const SO_DOMAIN: u32 = 4121; pub const SO_TS_REALTIME_MICRO: u32 = 0; pub const SO_TS_BINTIME: u32 = 1; pub const SO_TS_REALTIME: u32 = 2; pub const SO_TS_MONOTONIC: u32 = 3; pub const SO_TS_DEFAULT: u32 = 0; pub const SO_TS_CLOCK_MAX: u32 = 3; pub const SO_VENDOR: u32 = 2147483648; pub const SOL_SOCKET: u32 = 65535; pub const AF_UNSPEC: u32 = 0; pub const AF_UNIX: u32 = 1; pub const AF_INET: u32 = 2; pub const AF_IMPLINK: u32 = 3; pub const AF_PUP: u32 = 4; pub const AF_CHAOS: u32 = 5; pub const AF_NETBIOS: u32 = 6; pub const AF_ISO: u32 = 7; pub const AF_OSI: u32 = 7; pub const AF_ECMA: u32 = 8; pub const AF_DATAKIT: u32 = 9; pub const AF_CCITT: u32 = 10; pub const AF_SNA: u32 = 11; pub const AF_DECnet: u32 = 12; pub const AF_DLI: u32 = 13; pub const AF_LAT: u32 = 14; pub const AF_HYLINK: u32 = 15; pub const AF_APPLETALK: u32 = 16; pub const AF_ROUTE: u32 = 17; pub const AF_LINK: u32 = 18; pub const pseudo_AF_XTP: u32 = 19; pub const AF_COIP: u32 = 20; pub const AF_CNT: u32 = 21; pub const pseudo_AF_RTIP: u32 = 22; pub const AF_IPX: u32 = 23; pub const AF_SIP: u32 = 24; pub const pseudo_AF_PIP: u32 = 25; pub const AF_ISDN: u32 = 26; pub const AF_E164: u32 = 26; pub const pseudo_AF_KEY: u32 = 27; pub const AF_INET6: u32 = 28; pub const AF_NATM: u32 = 29; pub const AF_ATM: u32 = 30; pub const pseudo_AF_HDRCMPLT: u32 = 31; pub const AF_NETGRAPH: u32 = 32; pub const AF_SLOW: u32 = 33; pub const AF_SCLUSTER: u32 = 34; pub const AF_ARP: u32 = 35; pub const AF_BLUETOOTH: u32 = 36; pub const AF_IEEE80211: u32 = 37; pub const AF_NETLINK: u32 = 38; pub const AF_INET_SDP: u32 = 40; pub const AF_INET6_SDP: u32 = 42; pub const AF_HYPERV: u32 = 43; pub const AF_DIVERT: u32 = 44; pub const AF_MAX: u32 = 44; pub const AF_VENDOR00: u32 = 39; pub const AF_VENDOR01: u32 = 41; pub const AF_VENDOR03: u32 = 45; pub const AF_VENDOR04: u32 = 47; pub const AF_VENDOR05: u32 = 49; pub const AF_VENDOR06: u32 = 51; pub const AF_VENDOR07: u32 = 53; pub const AF_VENDOR08: u32 = 55; pub const AF_VENDOR09: u32 = 57; pub const AF_VENDOR10: u32 = 59; pub const AF_VENDOR11: u32 = 61; pub const AF_VENDOR12: u32 = 63; pub const AF_VENDOR13: u32 = 65; pub const AF_VENDOR14: u32 = 67; pub const AF_VENDOR15: u32 = 69; pub const AF_VENDOR16: u32 = 71; pub const AF_VENDOR17: u32 = 73; pub const AF_VENDOR18: u32 = 75; pub const AF_VENDOR19: u32 = 77; pub const AF_VENDOR20: u32 = 79; pub const AF_VENDOR21: u32 = 81; pub const AF_VENDOR22: u32 = 83; pub const AF_VENDOR23: u32 = 85; pub const AF_VENDOR24: u32 = 87; pub const AF_VENDOR25: u32 = 89; pub const AF_VENDOR26: u32 = 91; pub const AF_VENDOR27: u32 = 93; pub const AF_VENDOR28: u32 = 95; pub const AF_VENDOR29: u32 = 97; pub const AF_VENDOR30: u32 = 99; pub const AF_VENDOR31: u32 = 101; pub const AF_VENDOR32: u32 = 103; pub const AF_VENDOR33: u32 = 105; pub const AF_VENDOR34: u32 = 107; pub const AF_VENDOR35: u32 = 109; pub const AF_VENDOR36: u32 = 111; pub const AF_VENDOR37: u32 = 113; pub const AF_VENDOR38: u32 = 115; pub const AF_VENDOR39: u32 = 117; pub const AF_VENDOR40: u32 = 119; pub const AF_VENDOR41: u32 = 121; pub const AF_VENDOR42: u32 = 123; pub const AF_VENDOR43: u32 = 125; pub const AF_VENDOR44: u32 = 127; pub const AF_VENDOR45: u32 = 129; pub const AF_VENDOR46: u32 = 131; pub const AF_VENDOR47: u32 = 133; pub const SOCK_MAXADDRLEN: u32 = 255; pub const _SS_MAXSIZE: u32 = 128; pub const PF_UNSPEC: u32 = 0; pub const PF_INET: u32 = 2; pub const PF_IMPLINK: u32 = 3; pub const PF_PUP: u32 = 4; pub const PF_CHAOS: u32 = 5; pub const PF_NETBIOS: u32 = 6; pub const PF_ISO: u32 = 7; pub const PF_OSI: u32 = 7; pub const PF_ECMA: u32 = 8; pub const PF_DATAKIT: u32 = 9; pub const PF_CCITT: u32 = 10; pub const PF_SNA: u32 = 11; pub const PF_DECnet: u32 = 12; pub const PF_DLI: u32 = 13; pub const PF_LAT: u32 = 14; pub const PF_HYLINK: u32 = 15; pub const PF_APPLETALK: u32 = 16; pub const PF_ROUTE: u32 = 17; pub const PF_LINK: u32 = 18; pub const PF_XTP: u32 = 19; pub const PF_COIP: u32 = 20; pub const PF_CNT: u32 = 21; pub const PF_SIP: u32 = 24; pub const PF_IPX: u32 = 23; pub const PF_RTIP: u32 = 22; pub const PF_PIP: u32 = 25; pub const PF_ISDN: u32 = 26; pub const PF_KEY: u32 = 27; pub const PF_INET6: u32 = 28; pub const PF_NATM: u32 = 29; pub const PF_ATM: u32 = 30; pub const PF_NETGRAPH: u32 = 32; pub const PF_SLOW: u32 = 33; pub const PF_SCLUSTER: u32 = 34; pub const PF_ARP: u32 = 35; pub const PF_BLUETOOTH: u32 = 36; pub const PF_IEEE80211: u32 = 37; pub const PF_NETLINK: u32 = 38; pub const PF_INET_SDP: u32 = 40; pub const PF_INET6_SDP: u32 = 42; pub const PF_DIVERT: u32 = 44; pub const PF_MAX: u32 = 44; pub const NET_RT_DUMP: u32 = 1; pub const NET_RT_FLAGS: u32 = 2; pub const NET_RT_IFLIST: u32 = 3; pub const NET_RT_IFMALIST: u32 = 4; pub const NET_RT_IFLISTL: u32 = 5; pub const NET_RT_NHOP: u32 = 6; pub const NET_RT_NHGRP: u32 = 7; pub const SOMAXCONN: u32 = 128; pub const MSG_OOB: u32 = 1; pub const MSG_PEEK: u32 = 2; pub const MSG_DONTROUTE: u32 = 4; pub const MSG_EOR: u32 = 8; pub const MSG_TRUNC: u32 = 16; pub const MSG_CTRUNC: u32 = 32; pub const MSG_WAITALL: u32 = 64; pub const MSG_DONTWAIT: u32 = 128; pub const MSG_EOF: u32 = 256; pub const MSG_NOTIFICATION: u32 = 8192; pub const MSG_NBIO: u32 = 16384; pub const MSG_COMPAT: u32 = 32768; pub const MSG_NOSIGNAL: u32 = 131072; pub const MSG_CMSG_CLOEXEC: u32 = 262144; pub const MSG_WAITFORONE: u32 = 524288; pub const CMGROUP_MAX: u32 = 16; pub const SCM_RIGHTS: u32 = 1; pub const SCM_TIMESTAMP: u32 = 2; pub const SCM_CREDS: u32 = 3; pub const SCM_BINTIME: u32 = 4; pub const SCM_REALTIME: u32 = 5; pub const SCM_MONOTONIC: u32 = 6; pub const SCM_TIME_INFO: u32 = 7; pub const SCM_CREDS2: u32 = 8; pub const ST_INFO_HW: u32 = 1; pub const ST_INFO_HW_HPREC: u32 = 2; pub const SHUT_RD: u32 = 0; pub const SHUT_WR: u32 = 1; pub const SHUT_RDWR: u32 = 2; pub const PRU_FLUSH_RD: u32 = 0; pub const PRU_FLUSH_WR: u32 = 1; pub const PRU_FLUSH_RDWR: u32 = 2; pub const SF_NODISKIO: u32 = 1; pub const SF_MNOWAIT: u32 = 2; pub const SF_SYNC: u32 = 4; pub const SF_USER_READAHEAD: u32 = 8; pub const SF_NOCACHE: u32 = 16; pub const IF_NAMESIZE: u32 = 16; pub const IFNAMSIZ: u32 = 16; pub const IF_MAXUNIT: u32 = 32767; pub const IFF_UP: u32 = 1; pub const IFF_BROADCAST: u32 = 2; pub const IFF_DEBUG: u32 = 4; pub const IFF_LOOPBACK: u32 = 8; pub const IFF_POINTOPOINT: u32 = 16; pub const IFF_NEEDSEPOCH: u32 = 32; pub const IFF_DRV_RUNNING: u32 = 64; pub const IFF_NOARP: u32 = 128; pub const IFF_PROMISC: u32 = 256; pub const IFF_ALLMULTI: u32 = 512; pub const IFF_DRV_OACTIVE: u32 = 1024; pub const IFF_SIMPLEX: u32 = 2048; pub const IFF_LINK0: u32 = 4096; pub const IFF_LINK1: u32 = 8192; pub const IFF_LINK2: u32 = 16384; pub const IFF_ALTPHYS: u32 = 16384; pub const IFF_MULTICAST: u32 = 32768; pub const IFF_CANTCONFIG: u32 = 65536; pub const IFF_PPROMISC: u32 = 131072; pub const IFF_MONITOR: u32 = 262144; pub const IFF_STATICARP: u32 = 524288; pub const IFF_STICKYARP: u32 = 1048576; pub const IFF_DYING: u32 = 2097152; pub const IFF_RENAMING: u32 = 4194304; pub const IFF_SPARE: u32 = 8388608; pub const IFF_NETLINK_1: u32 = 16777216; pub const IFF_RUNNING: u32 = 64; pub const IFF_OACTIVE: u32 = 1024; pub const IFF_CANTCHANGE: u32 = 2199410; pub const LINK_STATE_UNKNOWN: u32 = 0; pub const LINK_STATE_DOWN: u32 = 1; pub const LINK_STATE_UP: u32 = 2; pub const IFCAP_B_RXCSUM: u32 = 0; pub const IFCAP_B_TXCSUM: u32 = 1; pub const IFCAP_B_NETCONS: u32 = 2; pub const IFCAP_B_VLAN_MTU: u32 = 3; pub const IFCAP_B_VLAN_HWTAGGING: u32 = 4; pub const IFCAP_B_JUMBO_MTU: u32 = 5; pub const IFCAP_B_POLLING: u32 = 6; pub const IFCAP_B_VLAN_HWCSUM: u32 = 7; pub const IFCAP_B_TSO4: u32 = 8; pub const IFCAP_B_TSO6: u32 = 9; pub const IFCAP_B_LRO: u32 = 10; pub const IFCAP_B_WOL_UCAST: u32 = 11; pub const IFCAP_B_WOL_MCAST: u32 = 12; pub const IFCAP_B_WOL_MAGIC: u32 = 13; pub const IFCAP_B_TOE4: u32 = 14; pub const IFCAP_B_TOE6: u32 = 15; pub const IFCAP_B_VLAN_HWFILTER: u32 = 16; pub const IFCAP_B_NV: u32 = 17; pub const IFCAP_B_VLAN_HWTSO: u32 = 18; pub const IFCAP_B_LINKSTATE: u32 = 19; pub const IFCAP_B_NETMAP: u32 = 20; pub const IFCAP_B_RXCSUM_IPV6: u32 = 21; pub const IFCAP_B_TXCSUM_IPV6: u32 = 22; pub const IFCAP_B_HWSTATS: u32 = 23; pub const IFCAP_B_TXRTLMT: u32 = 24; pub const IFCAP_B_HWRXTSTMP: u32 = 25; pub const IFCAP_B_MEXTPG: u32 = 26; pub const IFCAP_B_TXTLS4: u32 = 27; pub const IFCAP_B_TXTLS6: u32 = 28; pub const IFCAP_B_VXLAN_HWCSUM: u32 = 29; pub const IFCAP_B_VXLAN_HWTSO: u32 = 30; pub const IFCAP_B_TXTLS_RTLMT: u32 = 31; pub const IFCAP_B_RXTLS4: u32 = 32; pub const IFCAP_B_RXTLS6: u32 = 33; pub const __IFCAP_B_SIZE: u32 = 34; pub const IFCAP_B_SIZE: u32 = 34; pub const IFCAP2_RXTLS4: u32 = 0; pub const IFCAP2_RXTLS6: u32 = 1; pub const IFCAP_ALLCAPS: u32 = 4294967295; pub const IFQ_MAXLEN: u32 = 50; pub const IFNET_SLOWHZ: u32 = 1; pub const IFAN_ARRIVAL: u32 = 0; pub const IFAN_DEPARTURE: u32 = 1; pub const IFR_CAP_NV_MAXBUFSIZE: u32 = 2097152; pub const IFSTATMAX: u32 = 800; pub const IFG_ALL: &[u8; 4] = b"all\0"; pub const IFG_EGRESS: &[u8; 7] = b"egress\0"; pub const RSS_FUNC_NONE: u32 = 0; pub const RSS_FUNC_PRIVATE: u32 = 1; pub const RSS_FUNC_TOEPLITZ: u32 = 2; pub const RSS_TYPE_IPV4: u32 = 1; pub const RSS_TYPE_TCP_IPV4: u32 = 2; pub const RSS_TYPE_IPV6: u32 = 4; pub const RSS_TYPE_IPV6_EX: u32 = 8; pub const RSS_TYPE_TCP_IPV6: u32 = 16; pub const RSS_TYPE_TCP_IPV6_EX: u32 = 32; pub const RSS_TYPE_UDP_IPV4: u32 = 64; pub const RSS_TYPE_UDP_IPV6: u32 = 128; pub const RSS_TYPE_UDP_IPV6_EX: u32 = 256; pub const RSS_KEYLEN: u32 = 128; pub const IFNET_PCP_NONE: u32 = 255; pub const IFDR_MSG_SIZE: u32 = 64; pub const IFDR_REASON_MSG: u32 = 1; pub const IFDR_REASON_VENDOR: u32 = 2; pub const ETHER_ADDR_LEN: u32 = 6; pub const ETHER_TYPE_LEN: u32 = 2; pub const ETHER_CRC_LEN: u32 = 4; pub const ETHER_HDR_LEN: u32 = 14; pub const ETHER_MIN_LEN: u32 = 64; pub const ETHER_MAX_LEN: u32 = 1518; pub const ETHER_MAX_LEN_JUMBO: u32 = 9018; pub const ETHER_VLAN_ENCAP_LEN: u32 = 4; pub const ETHER_ALIGN: u32 = 2; pub const ETHER_CRC_POLY_LE: u32 = 3988292384; pub const ETHER_CRC_POLY_BE: u32 = 79764918; pub const EVL_VLID_MASK: u32 = 4095; pub const EVL_PRI_MASK: u32 = 57344; pub const ETHERTYPE_8023: u32 = 4; pub const ETHERTYPE_PUP: u32 = 512; pub const ETHERTYPE_PUPAT: u32 = 512; pub const ETHERTYPE_SPRITE: u32 = 1280; pub const ETHERTYPE_NS: u32 = 1536; pub const ETHERTYPE_NSAT: u32 = 1537; pub const ETHERTYPE_DLOG1: u32 = 1632; pub const ETHERTYPE_DLOG2: u32 = 1633; pub const ETHERTYPE_IP: u32 = 2048; pub const ETHERTYPE_X75: u32 = 2049; pub const ETHERTYPE_NBS: u32 = 2050; pub const ETHERTYPE_ECMA: u32 = 2051; pub const ETHERTYPE_CHAOS: u32 = 2052; pub const ETHERTYPE_X25: u32 = 2053; pub const ETHERTYPE_ARP: u32 = 2054; pub const ETHERTYPE_NSCOMPAT: u32 = 2055; pub const ETHERTYPE_FRARP: u32 = 2056; pub const ETHERTYPE_UBDEBUG: u32 = 2304; pub const ETHERTYPE_IEEEPUP: u32 = 2560; pub const ETHERTYPE_IEEEPUPAT: u32 = 2561; pub const ETHERTYPE_VINES: u32 = 2989; pub const ETHERTYPE_VINESLOOP: u32 = 2990; pub const ETHERTYPE_VINESECHO: u32 = 2991; pub const ETHERTYPE_TRAIL: u32 = 4096; pub const ETHERTYPE_NTRAILER: u32 = 16; pub const ETHERTYPE_DCA: u32 = 4660; pub const ETHERTYPE_VALID: u32 = 5632; pub const ETHERTYPE_DOGFIGHT: u32 = 6537; pub const ETHERTYPE_RCL: u32 = 6549; pub const ETHERTYPE_NBPVCD: u32 = 15360; pub const ETHERTYPE_NBPSCD: u32 = 15361; pub const ETHERTYPE_NBPCREQ: u32 = 15362; pub const ETHERTYPE_NBPCRSP: u32 = 15363; pub const ETHERTYPE_NBPCC: u32 = 15364; pub const ETHERTYPE_NBPCLREQ: u32 = 15365; pub const ETHERTYPE_NBPCLRSP: u32 = 15366; pub const ETHERTYPE_NBPDG: u32 = 15367; pub const ETHERTYPE_NBPDGB: u32 = 15368; pub const ETHERTYPE_NBPCLAIM: u32 = 15369; pub const ETHERTYPE_NBPDLTE: u32 = 15370; pub const ETHERTYPE_NBPRAS: u32 = 15371; pub const ETHERTYPE_NBPRAR: u32 = 15372; pub const ETHERTYPE_NBPRST: u32 = 15373; pub const ETHERTYPE_PCS: u32 = 16962; pub const ETHERTYPE_IMLBLDIAG: u32 = 16972; pub const ETHERTYPE_DIDDLE: u32 = 17185; pub const ETHERTYPE_IMLBL: u32 = 19522; pub const ETHERTYPE_SIMNET: u32 = 21000; pub const ETHERTYPE_DECEXPER: u32 = 24576; pub const ETHERTYPE_MOPDL: u32 = 24577; pub const ETHERTYPE_MOPRC: u32 = 24578; pub const ETHERTYPE_DECnet: u32 = 24579; pub const ETHERTYPE_DN: u32 = 24579; pub const ETHERTYPE_LAT: u32 = 24580; pub const ETHERTYPE_DECDIAG: u32 = 24581; pub const ETHERTYPE_DECCUST: u32 = 24582; pub const ETHERTYPE_SCA: u32 = 24583; pub const ETHERTYPE_AMBER: u32 = 24584; pub const ETHERTYPE_DECMUMPS: u32 = 24585; pub const ETHERTYPE_TRANSETHER: u32 = 25944; pub const ETHERTYPE_RAWFR: u32 = 25945; pub const ETHERTYPE_UBDL: u32 = 28672; pub const ETHERTYPE_UBNIU: u32 = 28673; pub const ETHERTYPE_UBDIAGLOOP: u32 = 28674; pub const ETHERTYPE_UBNMC: u32 = 28675; pub const ETHERTYPE_UBBST: u32 = 28677; pub const ETHERTYPE_OS9: u32 = 28679; pub const ETHERTYPE_OS9NET: u32 = 28681; pub const ETHERTYPE_RACAL: u32 = 28720; pub const ETHERTYPE_PRIMENTS: u32 = 28721; pub const ETHERTYPE_CABLETRON: u32 = 28724; pub const ETHERTYPE_CRONUSVLN: u32 = 32771; pub const ETHERTYPE_CRONUS: u32 = 32772; pub const ETHERTYPE_HP: u32 = 32773; pub const ETHERTYPE_NESTAR: u32 = 32774; pub const ETHERTYPE_ATTSTANFORD: u32 = 32776; pub const ETHERTYPE_EXCELAN: u32 = 32784; pub const ETHERTYPE_SG_DIAG: u32 = 32787; pub const ETHERTYPE_SG_NETGAMES: u32 = 32788; pub const ETHERTYPE_SG_RESV: u32 = 32789; pub const ETHERTYPE_SG_BOUNCE: u32 = 32790; pub const ETHERTYPE_APOLLODOMAIN: u32 = 32793; pub const ETHERTYPE_TYMSHARE: u32 = 32814; pub const ETHERTYPE_TIGAN: u32 = 32815; pub const ETHERTYPE_REVARP: u32 = 32821; pub const ETHERTYPE_AEONIC: u32 = 32822; pub const ETHERTYPE_IPXNEW: u32 = 32823; pub const ETHERTYPE_LANBRIDGE: u32 = 32824; pub const ETHERTYPE_DSMD: u32 = 32825; pub const ETHERTYPE_ARGONAUT: u32 = 32826; pub const ETHERTYPE_VAXELN: u32 = 32827; pub const ETHERTYPE_DECDNS: u32 = 32828; pub const ETHERTYPE_ENCRYPT: u32 = 32829; pub const ETHERTYPE_DECDTS: u32 = 32830; pub const ETHERTYPE_DECLTM: u32 = 32831; pub const ETHERTYPE_DECNETBIOS: u32 = 32832; pub const ETHERTYPE_DECLAST: u32 = 32833; pub const ETHERTYPE_PLANNING: u32 = 32836; pub const ETHERTYPE_DECAM: u32 = 32840; pub const ETHERTYPE_EXPERDATA: u32 = 32841; pub const ETHERTYPE_VEXP: u32 = 32859; pub const ETHERTYPE_VPROD: u32 = 32860; pub const ETHERTYPE_ES: u32 = 32861; pub const ETHERTYPE_LITTLE: u32 = 32864; pub const ETHERTYPE_COUNTERPOINT: u32 = 32866; pub const ETHERTYPE_VEECO: u32 = 32871; pub const ETHERTYPE_GENDYN: u32 = 32872; pub const ETHERTYPE_ATT: u32 = 32873; pub const ETHERTYPE_AUTOPHON: u32 = 32874; pub const ETHERTYPE_COMDESIGN: u32 = 32876; pub const ETHERTYPE_COMPUGRAPHIC: u32 = 32877; pub const ETHERTYPE_MATRA: u32 = 32890; pub const ETHERTYPE_DDE: u32 = 32891; pub const ETHERTYPE_MERIT: u32 = 32892; pub const ETHERTYPE_VLTLMAN: u32 = 32896; pub const ETHERTYPE_ATALK: u32 = 32923; pub const ETHERTYPE_AT: u32 = 32923; pub const ETHERTYPE_APPLETALK: u32 = 32923; pub const ETHERTYPE_SPIDER: u32 = 32927; pub const ETHERTYPE_PACER: u32 = 32966; pub const ETHERTYPE_APPLITEK: u32 = 32967; pub const ETHERTYPE_SNA: u32 = 32981; pub const ETHERTYPE_VARIAN: u32 = 32989; pub const ETHERTYPE_RETIX: u32 = 33010; pub const ETHERTYPE_AARP: u32 = 33011; pub const ETHERTYPE_APOLLO: u32 = 33015; pub const ETHERTYPE_VLAN: u32 = 33024; pub const ETHERTYPE_BOFL: u32 = 33026; pub const ETHERTYPE_WELLFLEET: u32 = 33027; pub const ETHERTYPE_TALARIS: u32 = 33067; pub const ETHERTYPE_WATERLOO: u32 = 33072; pub const ETHERTYPE_HAYES: u32 = 33072; pub const ETHERTYPE_VGLAB: u32 = 33073; pub const ETHERTYPE_IPX: u32 = 33079; pub const ETHERTYPE_NOVELL: u32 = 33080; pub const ETHERTYPE_MUMPS: u32 = 33087; pub const ETHERTYPE_AMOEBA: u32 = 33093; pub const ETHERTYPE_FLIP: u32 = 33094; pub const ETHERTYPE_VURESERVED: u32 = 33095; pub const ETHERTYPE_LOGICRAFT: u32 = 33096; pub const ETHERTYPE_NCD: u32 = 33097; pub const ETHERTYPE_ALPHA: u32 = 33098; pub const ETHERTYPE_SNMP: u32 = 33100; pub const ETHERTYPE_TEC: u32 = 33103; pub const ETHERTYPE_RATIONAL: u32 = 33104; pub const ETHERTYPE_XTP: u32 = 33149; pub const ETHERTYPE_SGITW: u32 = 33150; pub const ETHERTYPE_HIPPI_FP: u32 = 33152; pub const ETHERTYPE_STP: u32 = 33153; pub const ETHERTYPE_MOTOROLA: u32 = 33165; pub const ETHERTYPE_NETBEUI: u32 = 33169; pub const ETHERTYPE_ACCTON: u32 = 33680; pub const ETHERTYPE_TALARISMC: u32 = 34091; pub const ETHERTYPE_KALPANA: u32 = 34178; pub const ETHERTYPE_SECTRA: u32 = 34523; pub const ETHERTYPE_IPV6: u32 = 34525; pub const ETHERTYPE_DELTACON: u32 = 34526; pub const ETHERTYPE_ATOMIC: u32 = 34527; pub const ETHERTYPE_RDP: u32 = 34617; pub const ETHERTYPE_MICP: u32 = 34618; pub const ETHERTYPE_TCPCOMP: u32 = 34667; pub const ETHERTYPE_IPAS: u32 = 34668; pub const ETHERTYPE_SECUREDATA: u32 = 34669; pub const ETHERTYPE_FLOWCONTROL: u32 = 34824; pub const ETHERTYPE_SLOW: u32 = 34825; pub const ETHERTYPE_PPP: u32 = 34827; pub const ETHERTYPE_HITACHI: u32 = 34848; pub const ETHERTYPE_TEST: u32 = 34850; pub const ETHERTYPE_MPLS: u32 = 34887; pub const ETHERTYPE_MPLS_MCAST: u32 = 34888; pub const ETHERTYPE_AXIS: u32 = 34902; pub const ETHERTYPE_PPPOEDISC: u32 = 34915; pub const ETHERTYPE_PPPOE: u32 = 34916; pub const ETHERTYPE_LANPROBE: u32 = 34952; pub const ETHERTYPE_PAE: u32 = 34958; pub const ETHERTYPE_PROFINET: u32 = 34962; pub const ETHERTYPE_AOE: u32 = 34978; pub const ETHERTYPE_ETHERCAT: u32 = 34980; pub const ETHERTYPE_QINQ: u32 = 34984; pub const ETHERTYPE_POWERLINK: u32 = 34987; pub const ETHERTYPE_LLDP: u32 = 35020; pub const ETHERTYPE_SERCOS: u32 = 35021; pub const ETHERTYPE_MACSEC: u32 = 35045; pub const ETHERTYPE_PBB: u32 = 35047; pub const ETHERTYPE_FCOE: u32 = 35078; pub const ETHERTYPE_LOOPBACK: u32 = 36864; pub const ETHERTYPE_8021Q9100: u32 = 37120; pub const ETHERTYPE_LBACK: u32 = 36864; pub const ETHERTYPE_XNSSM: u32 = 36865; pub const ETHERTYPE_TCPSM: u32 = 36866; pub const ETHERTYPE_BCLOOP: u32 = 36867; pub const ETHERTYPE_8021Q9200: u32 = 37376; pub const ETHERTYPE_8021Q9300: u32 = 37632; pub const ETHERTYPE_DEBNI: u32 = 43690; pub const ETHERTYPE_SONIX: u32 = 64245; pub const ETHERTYPE_VITAL: u32 = 65280; pub const ETHERTYPE_MAX: u32 = 65535; pub const ETHERMTU: u32 = 1500; pub const ETHERMIN: u32 = 46; pub const ETHERMTU_JUMBO: u32 = 9000; pub const IEEE8021Q_PCP_BK: u32 = 1; pub const IEEE8021Q_PCP_BE: u32 = 0; pub const IEEE8021Q_PCP_EE: u32 = 2; pub const IEEE8021Q_PCP_CA: u32 = 3; pub const IEEE8021Q_PCP_VI: u32 = 4; pub const IEEE8021Q_PCP_VO: u32 = 5; pub const IEEE8021Q_PCP_IC: u32 = 6; pub const IEEE8021Q_PCP_NC: u32 = 7; pub const RNF_NORMAL: u32 = 1; pub const RNF_ROOT: u32 = 2; pub const RNF_ACTIVE: u32 = 4; pub const IPPROTO_IP: u32 = 0; pub const IPPROTO_ICMP: u32 = 1; pub const IPPROTO_TCP: u32 = 6; pub const IPPROTO_UDP: u32 = 17; pub const IPPROTO_IPV6: u32 = 41; pub const IPPROTO_RAW: u32 = 255; pub const INET_ADDRSTRLEN: u32 = 16; pub const IPPROTO_HOPOPTS: u32 = 0; pub const IPPROTO_IGMP: u32 = 2; pub const IPPROTO_GGP: u32 = 3; pub const IPPROTO_IPV4: u32 = 4; pub const IPPROTO_IPIP: u32 = 4; pub const IPPROTO_ST: u32 = 7; pub const IPPROTO_EGP: u32 = 8; pub const IPPROTO_PIGP: u32 = 9; pub const IPPROTO_RCCMON: u32 = 10; pub const IPPROTO_NVPII: u32 = 11; pub const IPPROTO_PUP: u32 = 12; pub const IPPROTO_ARGUS: u32 = 13; pub const IPPROTO_EMCON: u32 = 14; pub const IPPROTO_XNET: u32 = 15; pub const IPPROTO_CHAOS: u32 = 16; pub const IPPROTO_MUX: u32 = 18; pub const IPPROTO_MEAS: u32 = 19; pub const IPPROTO_HMP: u32 = 20; pub const IPPROTO_PRM: u32 = 21; pub const IPPROTO_IDP: u32 = 22; pub const IPPROTO_TRUNK1: u32 = 23; pub const IPPROTO_TRUNK2: u32 = 24; pub const IPPROTO_LEAF1: u32 = 25; pub const IPPROTO_LEAF2: u32 = 26; pub const IPPROTO_RDP: u32 = 27; pub const IPPROTO_IRTP: u32 = 28; pub const IPPROTO_TP: u32 = 29; pub const IPPROTO_BLT: u32 = 30; pub const IPPROTO_NSP: u32 = 31; pub const IPPROTO_INP: u32 = 32; pub const IPPROTO_DCCP: u32 = 33; pub const IPPROTO_3PC: u32 = 34; pub const IPPROTO_IDPR: u32 = 35; pub const IPPROTO_XTP: u32 = 36; pub const IPPROTO_DDP: u32 = 37; pub const IPPROTO_CMTP: u32 = 38; pub const IPPROTO_TPXX: u32 = 39; pub const IPPROTO_IL: u32 = 40; pub const IPPROTO_SDRP: u32 = 42; pub const IPPROTO_ROUTING: u32 = 43; pub const IPPROTO_FRAGMENT: u32 = 44; pub const IPPROTO_IDRP: u32 = 45; pub const IPPROTO_RSVP: u32 = 46; pub const IPPROTO_GRE: u32 = 47; pub const IPPROTO_MHRP: u32 = 48; pub const IPPROTO_BHA: u32 = 49; pub const IPPROTO_ESP: u32 = 50; pub const IPPROTO_AH: u32 = 51; pub const IPPROTO_INLSP: u32 = 52; pub const IPPROTO_SWIPE: u32 = 53; pub const IPPROTO_NHRP: u32 = 54; pub const IPPROTO_MOBILE: u32 = 55; pub const IPPROTO_TLSP: u32 = 56; pub const IPPROTO_SKIP: u32 = 57; pub const IPPROTO_ICMPV6: u32 = 58; pub const IPPROTO_NONE: u32 = 59; pub const IPPROTO_DSTOPTS: u32 = 60; pub const IPPROTO_AHIP: u32 = 61; pub const IPPROTO_CFTP: u32 = 62; pub const IPPROTO_HELLO: u32 = 63; pub const IPPROTO_SATEXPAK: u32 = 64; pub const IPPROTO_KRYPTOLAN: u32 = 65; pub const IPPROTO_RVD: u32 = 66; pub const IPPROTO_IPPC: u32 = 67; pub const IPPROTO_ADFS: u32 = 68; pub const IPPROTO_SATMON: u32 = 69; pub const IPPROTO_VISA: u32 = 70; pub const IPPROTO_IPCV: u32 = 71; pub const IPPROTO_CPNX: u32 = 72; pub const IPPROTO_CPHB: u32 = 73; pub const IPPROTO_WSN: u32 = 74; pub const IPPROTO_PVP: u32 = 75; pub const IPPROTO_BRSATMON: u32 = 76; pub const IPPROTO_ND: u32 = 77; pub const IPPROTO_WBMON: u32 = 78; pub const IPPROTO_WBEXPAK: u32 = 79; pub const IPPROTO_EON: u32 = 80; pub const IPPROTO_VMTP: u32 = 81; pub const IPPROTO_SVMTP: u32 = 82; pub const IPPROTO_VINES: u32 = 83; pub const IPPROTO_TTP: u32 = 84; pub const IPPROTO_IGP: u32 = 85; pub const IPPROTO_DGP: u32 = 86; pub const IPPROTO_TCF: u32 = 87; pub const IPPROTO_IGRP: u32 = 88; pub const IPPROTO_OSPFIGP: u32 = 89; pub const IPPROTO_SRPC: u32 = 90; pub const IPPROTO_LARP: u32 = 91; pub const IPPROTO_MTP: u32 = 92; pub const IPPROTO_AX25: u32 = 93; pub const IPPROTO_IPEIP: u32 = 94; pub const IPPROTO_MICP: u32 = 95; pub const IPPROTO_SCCSP: u32 = 96; pub const IPPROTO_ETHERIP: u32 = 97; pub const IPPROTO_ENCAP: u32 = 98; pub const IPPROTO_APES: u32 = 99; pub const IPPROTO_GMTP: u32 = 100; pub const IPPROTO_IPCOMP: u32 = 108; pub const IPPROTO_SCTP: u32 = 132; pub const IPPROTO_MH: u32 = 135; pub const IPPROTO_UDPLITE: u32 = 136; pub const IPPROTO_HIP: u32 = 139; pub const IPPROTO_SHIM6: u32 = 140; pub const IPPROTO_PIM: u32 = 103; pub const IPPROTO_CARP: u32 = 112; pub const IPPROTO_PGM: u32 = 113; pub const IPPROTO_MPLS: u32 = 137; pub const IPPROTO_PFSYNC: u32 = 240; pub const IPPROTO_RESERVED_253: u32 = 253; pub const IPPROTO_RESERVED_254: u32 = 254; pub const IPPROTO_OLD_DIVERT: u32 = 254; pub const IPPROTO_MAX: u32 = 256; pub const IPPROTO_DONE: u32 = 257; pub const IPPROTO_DIVERT: u32 = 258; pub const IPPROTO_SEND: u32 = 259; pub const IPPROTO_SPACER: u32 = 32767; pub const IPPORT_RESERVED: u32 = 1024; pub const IPPORT_EPHEMERALFIRST: u32 = 10000; pub const IPPORT_EPHEMERALLAST: u32 = 65535; pub const IPPORT_HIFIRSTAUTO: u32 = 49152; pub const IPPORT_HILASTAUTO: u32 = 65535; pub const IPPORT_RESERVEDSTART: u32 = 600; pub const IPPORT_MAX: u32 = 65535; pub const IN_CLASSA_NET: u32 = 4278190080; pub const IN_CLASSA_NSHIFT: u32 = 24; pub const IN_CLASSA_HOST: u32 = 16777215; pub const IN_CLASSA_MAX: u32 = 128; pub const IN_CLASSB_NET: u32 = 4294901760; pub const IN_CLASSB_NSHIFT: u32 = 16; pub const IN_CLASSB_HOST: u32 = 65535; pub const IN_CLASSB_MAX: u32 = 65536; pub const IN_CLASSC_NET: u32 = 4294967040; pub const IN_CLASSC_NSHIFT: u32 = 8; pub const IN_CLASSC_HOST: u32 = 255; pub const IN_NETMASK_DEFAULT: u32 = 4294967040; pub const IN_CLASSD_NET: u32 = 4026531840; pub const IN_CLASSD_NSHIFT: u32 = 28; pub const IN_CLASSD_HOST: u32 = 268435455; pub const IN_LOOPBACKNET: u32 = 127; pub const IP_OPTIONS: u32 = 1; pub const IP_HDRINCL: u32 = 2; pub const IP_TOS: u32 = 3; pub const IP_TTL: u32 = 4; pub const IP_RECVOPTS: u32 = 5; pub const IP_RECVRETOPTS: u32 = 6; pub const IP_RECVDSTADDR: u32 = 7; pub const IP_SENDSRCADDR: u32 = 7; pub const IP_RETOPTS: u32 = 8; pub const IP_MULTICAST_IF: u32 = 9; pub const IP_MULTICAST_TTL: u32 = 10; pub const IP_MULTICAST_LOOP: u32 = 11; pub const IP_ADD_MEMBERSHIP: u32 = 12; pub const IP_DROP_MEMBERSHIP: u32 = 13; pub const IP_MULTICAST_VIF: u32 = 14; pub const IP_RSVP_ON: u32 = 15; pub const IP_RSVP_OFF: u32 = 16; pub const IP_RSVP_VIF_ON: u32 = 17; pub const IP_RSVP_VIF_OFF: u32 = 18; pub const IP_PORTRANGE: u32 = 19; pub const IP_RECVIF: u32 = 20; pub const IP_IPSEC_POLICY: u32 = 21; pub const IP_ONESBCAST: u32 = 23; pub const IP_BINDANY: u32 = 24; pub const IP_ORIGDSTADDR: u32 = 27; pub const IP_RECVORIGDSTADDR: u32 = 27; pub const IP_FW_TABLE_ADD: u32 = 40; pub const IP_FW_TABLE_DEL: u32 = 41; pub const IP_FW_TABLE_FLUSH: u32 = 42; pub const IP_FW_TABLE_GETSIZE: u32 = 43; pub const IP_FW_TABLE_LIST: u32 = 44; pub const IP_FW3: u32 = 48; pub const IP_DUMMYNET3: u32 = 49; pub const IP_FW_ADD: u32 = 50; pub const IP_FW_DEL: u32 = 51; pub const IP_FW_FLUSH: u32 = 52; pub const IP_FW_ZERO: u32 = 53; pub const IP_FW_GET: u32 = 54; pub const IP_FW_RESETLOG: u32 = 55; pub const IP_FW_NAT_CFG: u32 = 56; pub const IP_FW_NAT_DEL: u32 = 57; pub const IP_FW_NAT_GET_CONFIG: u32 = 58; pub const IP_FW_NAT_GET_LOG: u32 = 59; pub const IP_DUMMYNET_CONFIGURE: u32 = 60; pub const IP_DUMMYNET_DEL: u32 = 61; pub const IP_DUMMYNET_FLUSH: u32 = 62; pub const IP_DUMMYNET_GET: u32 = 64; pub const IP_RECVTTL: u32 = 65; pub const IP_MINTTL: u32 = 66; pub const IP_DONTFRAG: u32 = 67; pub const IP_RECVTOS: u32 = 68; pub const IP_ADD_SOURCE_MEMBERSHIP: u32 = 70; pub const IP_DROP_SOURCE_MEMBERSHIP: u32 = 71; pub const IP_BLOCK_SOURCE: u32 = 72; pub const IP_UNBLOCK_SOURCE: u32 = 73; pub const IP_MSFILTER: u32 = 74; pub const IP_VLAN_PCP: u32 = 75; pub const MCAST_JOIN_GROUP: u32 = 80; pub const MCAST_LEAVE_GROUP: u32 = 81; pub const MCAST_JOIN_SOURCE_GROUP: u32 = 82; pub const MCAST_LEAVE_SOURCE_GROUP: u32 = 83; pub const MCAST_BLOCK_SOURCE: u32 = 84; pub const MCAST_UNBLOCK_SOURCE: u32 = 85; pub const IP_FLOWID: u32 = 90; pub const IP_FLOWTYPE: u32 = 91; pub const IP_RSSBUCKETID: u32 = 92; pub const IP_RECVFLOWID: u32 = 93; pub const IP_RECVRSSBUCKETID: u32 = 94; pub const IP_DEFAULT_MULTICAST_TTL: u32 = 1; pub const IP_DEFAULT_MULTICAST_LOOP: u32 = 1; pub const IP_MAX_MEMBERSHIPS: u32 = 4095; pub const IP_MAX_GROUP_SRC_FILTER: u32 = 512; pub const IP_MAX_SOCK_SRC_FILTER: u32 = 128; pub const IP_MAX_SOCK_MUTE_FILTER: u32 = 128; pub const MCAST_UNDEFINED: u32 = 0; pub const MCAST_INCLUDE: u32 = 1; pub const MCAST_EXCLUDE: u32 = 2; pub const IP_PORTRANGE_DEFAULT: u32 = 0; pub const IP_PORTRANGE_HIGH: u32 = 1; pub const IP_PORTRANGE_LOW: u32 = 2; pub const IPCTL_FORWARDING: u32 = 1; pub const IPCTL_SENDREDIRECTS: u32 = 2; pub const IPCTL_DEFTTL: u32 = 3; pub const IPCTL_SOURCEROUTE: u32 = 8; pub const IPCTL_DIRECTEDBROADCAST: u32 = 9; pub const IPCTL_INTRQMAXLEN: u32 = 10; pub const IPCTL_INTRQDROPS: u32 = 11; pub const IPCTL_STATS: u32 = 12; pub const IPCTL_ACCEPTSOURCEROUTE: u32 = 13; pub const IPCTL_FASTFORWARDING: u32 = 14; pub const IPCTL_GIF_TTL: u32 = 16; pub const IPCTL_INTRDQMAXLEN: u32 = 17; pub const IPCTL_INTRDQDROPS: u32 = 18; pub const __KAME_VERSION: &[u8; 8] = b"FreeBSD\0"; pub const IPV6PORT_RESERVED: u32 = 1024; pub const IPV6PORT_ANONMIN: u32 = 49152; pub const IPV6PORT_ANONMAX: u32 = 65535; pub const IPV6PORT_RESERVEDMIN: u32 = 600; pub const IPV6PORT_RESERVEDMAX: u32 = 1023; pub const INET6_ADDRSTRLEN: u32 = 46; pub const __IPV6_ADDR_SCOPE_NODELOCAL: u32 = 1; pub const __IPV6_ADDR_SCOPE_INTFACELOCAL: u32 = 1; pub const __IPV6_ADDR_SCOPE_LINKLOCAL: u32 = 2; pub const __IPV6_ADDR_SCOPE_SITELOCAL: u32 = 5; pub const __IPV6_ADDR_SCOPE_ORGLOCAL: u32 = 8; pub const __IPV6_ADDR_SCOPE_GLOBAL: u32 = 14; pub const IPV6_SOCKOPT_RESERVED1: u32 = 3; pub const IPV6_UNICAST_HOPS: u32 = 4; pub const IPV6_MULTICAST_IF: u32 = 9; pub const IPV6_MULTICAST_HOPS: u32 = 10; pub const IPV6_MULTICAST_LOOP: u32 = 11; pub const IPV6_JOIN_GROUP: u32 = 12; pub const IPV6_LEAVE_GROUP: u32 = 13; pub const IPV6_PORTRANGE: u32 = 14; pub const ICMP6_FILTER: u32 = 18; pub const IPV6_CHECKSUM: u32 = 26; pub const IPV6_V6ONLY: u32 = 27; pub const IPV6_BINDV6ONLY: u32 = 27; pub const IPV6_IPSEC_POLICY: u32 = 28; pub const IPV6_FW_ADD: u32 = 30; pub const IPV6_FW_DEL: u32 = 31; pub const IPV6_FW_FLUSH: u32 = 32; pub const IPV6_FW_ZERO: u32 = 33; pub const IPV6_FW_GET: u32 = 34; pub const IPV6_RTHDRDSTOPTS: u32 = 35; pub const IPV6_RECVPKTINFO: u32 = 36; pub const IPV6_RECVHOPLIMIT: u32 = 37; pub const IPV6_RECVRTHDR: u32 = 38; pub const IPV6_RECVHOPOPTS: u32 = 39; pub const IPV6_RECVDSTOPTS: u32 = 40; pub const IPV6_USE_MIN_MTU: u32 = 42; pub const IPV6_RECVPATHMTU: u32 = 43; pub const IPV6_PATHMTU: u32 = 44; pub const IPV6_PKTINFO: u32 = 46; pub const IPV6_HOPLIMIT: u32 = 47; pub const IPV6_NEXTHOP: u32 = 48; pub const IPV6_HOPOPTS: u32 = 49; pub const IPV6_DSTOPTS: u32 = 50; pub const IPV6_RTHDR: u32 = 51; pub const IPV6_RECVTCLASS: u32 = 57; pub const IPV6_AUTOFLOWLABEL: u32 = 59; pub const IPV6_TCLASS: u32 = 61; pub const IPV6_DONTFRAG: u32 = 62; pub const IPV6_PREFER_TEMPADDR: u32 = 63; pub const IPV6_BINDANY: u32 = 64; pub const IPV6_FLOWID: u32 = 67; pub const IPV6_FLOWTYPE: u32 = 68; pub const IPV6_RSSBUCKETID: u32 = 69; pub const IPV6_RECVFLOWID: u32 = 70; pub const IPV6_RECVRSSBUCKETID: u32 = 71; pub const IPV6_ORIGDSTADDR: u32 = 72; pub const IPV6_RECVORIGDSTADDR: u32 = 72; pub const IPV6_MSFILTER: u32 = 74; pub const IPV6_VLAN_PCP: u32 = 75; pub const IPV6_RTHDR_LOOSE: u32 = 0; pub const IPV6_RTHDR_STRICT: u32 = 1; pub const IPV6_RTHDR_TYPE_0: u32 = 0; pub const IPV6_DEFAULT_MULTICAST_HOPS: u32 = 1; pub const IPV6_DEFAULT_MULTICAST_LOOP: u32 = 1; pub const IPV6_MAX_MEMBERSHIPS: u32 = 4095; pub const IPV6_MAX_GROUP_SRC_FILTER: u32 = 512; pub const IPV6_MAX_SOCK_SRC_FILTER: u32 = 128; pub const IPV6_PORTRANGE_DEFAULT: u32 = 0; pub const IPV6_PORTRANGE_HIGH: u32 = 1; pub const IPV6_PORTRANGE_LOW: u32 = 2; pub const IPV6PROTO_MAXID: u32 = 104; pub const IPV6CTL_FORWARDING: u32 = 1; pub const IPV6CTL_SENDREDIRECTS: u32 = 2; pub const IPV6CTL_DEFHLIM: u32 = 3; pub const IPV6CTL_FORWSRCRT: u32 = 5; pub const IPV6CTL_STATS: u32 = 6; pub const IPV6CTL_MRTSTATS: u32 = 7; pub const IPV6CTL_MRTPROTO: u32 = 8; pub const IPV6CTL_MAXFRAGPACKETS: u32 = 9; pub const IPV6CTL_SOURCECHECK: u32 = 10; pub const IPV6CTL_SOURCECHECK_LOGINT: u32 = 11; pub const IPV6CTL_ACCEPT_RTADV: u32 = 12; pub const IPV6CTL_LOG_INTERVAL: u32 = 14; pub const IPV6CTL_HDRNESTLIMIT: u32 = 15; pub const IPV6CTL_DAD_COUNT: u32 = 16; pub const IPV6CTL_AUTO_FLOWLABEL: u32 = 17; pub const IPV6CTL_DEFMCASTHLIM: u32 = 18; pub const IPV6CTL_GIF_HLIM: u32 = 19; pub const IPV6CTL_KAME_VERSION: u32 = 20; pub const IPV6CTL_USE_DEPRECATED: u32 = 21; pub const IPV6CTL_RR_PRUNE: u32 = 22; pub const IPV6CTL_V6ONLY: u32 = 24; pub const IPV6CTL_USETEMPADDR: u32 = 32; pub const IPV6CTL_TEMPPLTIME: u32 = 33; pub const IPV6CTL_TEMPVLTIME: u32 = 34; pub const IPV6CTL_AUTO_LINKLOCAL: u32 = 35; pub const IPV6CTL_RIP6STATS: u32 = 36; pub const IPV6CTL_PREFER_TEMPADDR: u32 = 37; pub const IPV6CTL_ADDRCTLPOLICY: u32 = 38; pub const IPV6CTL_USE_DEFAULTZONE: u32 = 39; pub const IPV6CTL_MAXFRAGS: u32 = 41; pub const IPV6CTL_MCAST_PMTU: u32 = 44; pub const IPV6CTL_STEALTH: u32 = 45; pub const ICMPV6CTL_ND6_ONLINKNSRFC4861: u32 = 47; pub const IPV6CTL_NO_RADR: u32 = 48; pub const IPV6CTL_NORBIT_RAIF: u32 = 49; pub const IPV6CTL_RFC6204W3: u32 = 50; pub const IPV6CTL_INTRQMAXLEN: u32 = 51; pub const IPV6CTL_INTRDQMAXLEN: u32 = 52; pub const IPV6CTL_MAXFRAGSPERPACKET: u32 = 53; pub const IPV6CTL_MAXFRAGBUCKETSIZE: u32 = 54; pub const IPV6CTL_MAXID: u32 = 55; pub const PF_MD5_DIGEST_LENGTH: u32 = 16; pub const PFTM_TCP_FIRST_PACKET_VAL: u32 = 120; pub const PFTM_TCP_OPENING_VAL: u32 = 30; pub const PFTM_TCP_ESTABLISHED_VAL: u32 = 86400; pub const PFTM_TCP_CLOSING_VAL: u32 = 900; pub const PFTM_TCP_FIN_WAIT_VAL: u32 = 45; pub const PFTM_TCP_CLOSED_VAL: u32 = 90; pub const PFTM_UDP_FIRST_PACKET_VAL: u32 = 60; pub const PFTM_UDP_SINGLE_VAL: u32 = 30; pub const PFTM_UDP_MULTIPLE_VAL: u32 = 60; pub const PFTM_ICMP_FIRST_PACKET_VAL: u32 = 20; pub const PFTM_ICMP_ERROR_REPLY_VAL: u32 = 10; pub const PFTM_OTHER_FIRST_PACKET_VAL: u32 = 60; pub const PFTM_OTHER_SINGLE_VAL: u32 = 30; pub const PFTM_OTHER_MULTIPLE_VAL: u32 = 60; pub const PFTM_FRAG_VAL: u32 = 30; pub const PFTM_INTERVAL_VAL: u32 = 10; pub const PFTM_SRC_NODE_VAL: u32 = 0; pub const PFTM_TS_DIFF_VAL: u32 = 30; pub const PF_POOL_IDMASK: u32 = 15; pub const PF_POOL_TYPEMASK: u32 = 15; pub const PF_POOL_STICKYADDR: u32 = 32; pub const PF_WSCALE_FLAG: u32 = 128; pub const PF_WSCALE_MASK: u32 = 15; pub const PF_LOG: u32 = 1; pub const PF_LOG_ALL: u32 = 2; pub const PF_LOG_SOCKET_LOOKUP: u32 = 4; pub const PF_LOG_FORCE: u32 = 8; pub const PFRES_MATCH: u32 = 0; pub const PFRES_BADOFF: u32 = 1; pub const PFRES_FRAG: u32 = 2; pub const PFRES_SHORT: u32 = 3; pub const PFRES_NORM: u32 = 4; pub const PFRES_MEMORY: u32 = 5; pub const PFRES_TS: u32 = 6; pub const PFRES_CONGEST: u32 = 7; pub const PFRES_IPOPTIONS: u32 = 8; pub const PFRES_PROTCKSUM: u32 = 9; pub const PFRES_BADSTATE: u32 = 10; pub const PFRES_STATEINS: u32 = 11; pub const PFRES_MAXSTATES: u32 = 12; pub const PFRES_SRCLIMIT: u32 = 13; pub const PFRES_SYNPROXY: u32 = 14; pub const PFRES_MAPFAILED: u32 = 15; pub const PFRES_MAX: u32 = 16; pub const LCNT_STATES: u32 = 0; pub const LCNT_SRCSTATES: u32 = 1; pub const LCNT_SRCNODES: u32 = 2; pub const LCNT_SRCCONN: u32 = 3; pub const LCNT_SRCCONNRATE: u32 = 4; pub const LCNT_OVERLOAD_TABLE: u32 = 5; pub const LCNT_OVERLOAD_FLUSH: u32 = 6; pub const LCNT_MAX: u32 = 7; pub const KLCNT_SYNFLOODS: u32 = 7; pub const KLCNT_SYNCOOKIES_SENT: u32 = 8; pub const KLCNT_SYNCOOKIES_VALID: u32 = 9; pub const KLCNT_MAX: u32 = 10; pub const FCNT_STATE_SEARCH: u32 = 0; pub const FCNT_STATE_INSERT: u32 = 1; pub const FCNT_STATE_REMOVALS: u32 = 2; pub const FCNT_MAX: u32 = 3; pub const SCNT_SRC_NODE_SEARCH: u32 = 0; pub const SCNT_SRC_NODE_INSERT: u32 = 1; pub const SCNT_SRC_NODE_REMOVALS: u32 = 2; pub const SCNT_MAX: u32 = 3; pub const PF_TABLE_NAME_SIZE: u32 = 32; pub const PF_QNAME_SIZE: u32 = 64; pub const PF_REASS_ENABLED: u32 = 1; pub const PF_REASS_NODF: u32 = 2; pub const PFI_AFLAG_NETWORK: u32 = 1; pub const PFI_AFLAG_BROADCAST: u32 = 2; pub const PFI_AFLAG_PEER: u32 = 4; pub const PFI_AFLAG_MODEMASK: u32 = 7; pub const PFI_AFLAG_NOALIAS: u32 = 8; pub const PF_OSFP_EXPANDED: u32 = 1; pub const PF_OSFP_GENERIC: u32 = 2; pub const PF_OSFP_NODETAIL: u32 = 4; pub const PF_OSFP_LEN: u32 = 32; pub const _FP_RESERVED_BIT: u32 = 1; pub const _FP_UNUSED_BITS: u32 = 1; pub const _FP_CLASS_BITS: u32 = 10; pub const _FP_VERSION_BITS: u32 = 10; pub const _FP_SUBTYPE_BITS: u32 = 10; pub const PF_OSFP_WSIZE_MOD: u32 = 1; pub const PF_OSFP_WSIZE_DC: u32 = 2; pub const PF_OSFP_WSIZE_MSS: u32 = 4; pub const PF_OSFP_WSIZE_MTU: u32 = 8; pub const PF_OSFP_PSIZE_MOD: u32 = 16; pub const PF_OSFP_PSIZE_DC: u32 = 32; pub const PF_OSFP_WSCALE: u32 = 64; pub const PF_OSFP_WSCALE_MOD: u32 = 128; pub const PF_OSFP_WSCALE_DC: u32 = 256; pub const PF_OSFP_MSS: u32 = 512; pub const PF_OSFP_MSS_MOD: u32 = 1024; pub const PF_OSFP_MSS_DC: u32 = 2048; pub const PF_OSFP_DF: u32 = 4096; pub const PF_OSFP_TS0: u32 = 8192; pub const PF_OSFP_INET6: u32 = 16384; pub const PF_OSFP_MAXTTL_OFFSET: u32 = 40; pub const PF_OSFP_TCPOPT_NOP: u32 = 0; pub const PF_OSFP_TCPOPT_WSCALE: u32 = 1; pub const PF_OSFP_TCPOPT_MSS: u32 = 2; pub const PF_OSFP_TCPOPT_SACK: u32 = 3; pub const PF_OSFP_TCPOPT_TS: u32 = 4; pub const PF_OSFP_TCPOPT_BITS: u32 = 3; pub const PF_ANCHOR_NAME_SIZE: u32 = 64; pub const PF_SKIP_IFP: u32 = 0; pub const PF_SKIP_DIR: u32 = 1; pub const PF_SKIP_AF: u32 = 2; pub const PF_SKIP_PROTO: u32 = 3; pub const PF_SKIP_SRC_ADDR: u32 = 4; pub const PF_SKIP_SRC_PORT: u32 = 5; pub const PF_SKIP_DST_ADDR: u32 = 6; pub const PF_SKIP_DST_PORT: u32 = 7; pub const PF_SKIP_COUNT: u32 = 8; pub const PF_RULE_LABEL_SIZE: u32 = 64; pub const PF_RULE_MAX_LABEL_COUNT: u32 = 5; pub const PF_TAG_NAME_SIZE: u32 = 64; pub const PF_STATE_NORMAL: u32 = 1; pub const PF_STATE_MODULATE: u32 = 2; pub const PF_STATE_SYNPROXY: u32 = 3; pub const PF_FLUSH: u32 = 1; pub const PF_FLUSH_GLOBAL: u32 = 2; pub const PF_PRIO_ZERO: u32 = 255; pub const PF_PRIO_MAX: u32 = 7; pub const PFRULE_DROP: u32 = 0; pub const PFRULE_RETURNRST: u32 = 1; pub const PFRULE_FRAGMENT: u32 = 2; pub const PFRULE_RETURNICMP: u32 = 4; pub const PFRULE_RETURN: u32 = 8; pub const PFRULE_NOSYNC: u32 = 16; pub const PFRULE_SRCTRACK: u32 = 32; pub const PFRULE_RULESRCTRACK: u32 = 64; pub const PFRULE_NODF: u32 = 256; pub const PFRULE_FRAGMENT_NOREASS: u32 = 512; pub const PFRULE_RANDOMID: u32 = 2048; pub const PFRULE_REASSEMBLE_TCP: u32 = 4096; pub const PFRULE_SET_TOS: u32 = 8192; pub const PFRULE_IFBOUND: u32 = 65536; pub const PFRULE_STATESLOPPY: u32 = 131072; pub const PFRULE_DN_IS_PIPE: u32 = 64; pub const PFRULE_DN_IS_QUEUE: u32 = 128; pub const PFSTATE_ALLOWOPTS: u32 = 1; pub const PFSTATE_SLOPPY: u32 = 2; pub const PFSTATE_NOSYNC: u32 = 8; pub const PFSTATE_ACK: u32 = 16; pub const PFSTATE_NODF: u32 = 32; pub const PFSTATE_SETTOS: u32 = 64; pub const PFSTATE_RANDOMID: u32 = 128; pub const PFSTATE_SCRUB_TCP: u32 = 256; pub const PFSTATE_SETPRIO: u32 = 512; pub const PFSTATE_DN_IS_PIPE: u32 = 16384; pub const PFSTATE_DN_IS_QUEUE: u32 = 32768; pub const PFSTATE_SCRUBMASK: u32 = 416; pub const PFSTATE_SETMASK: u32 = 576; pub const PFSTATE_HIWAT: u32 = 100000; pub const PFSTATE_ADAPT_START: u32 = 60000; pub const PFSTATE_ADAPT_END: u32 = 120000; pub const PF_THRESHOLD_MULT: u32 = 1000; pub const PF_THRESHOLD_MAX: u32 = 4294967; pub const PFSNODE_HIWAT: u32 = 10000; pub const PFALTQ_FLAG_IF_REMOVED: u32 = 1; pub const PF_ALTQ_VERSION: u32 = 1; pub const PFSS_TIMESTAMP: u32 = 1; pub const PFSS_PAWS: u32 = 16; pub const PFSS_PAWS_IDLED: u32 = 32; pub const PFSS_DATA_TS: u32 = 64; pub const PFSS_DATA_NOTS: u32 = 128; pub const PF_SCRUB_FLAG_VALID: u32 = 1; pub const PF_STATE_VERSION: u32 = 20230404; pub const PFSYNC_SCRUB_FLAG_VALID: u32 = 1; pub const PFSYNC_FLAG_SRCNODE: u32 = 4; pub const PFSYNC_FLAG_NATSRCNODE: u32 = 8; pub const PF_RESERVED_ANCHOR: &[u8; 4] = b"_pf\0"; pub const PFR_TFLAG_PERSIST: u32 = 1; pub const PFR_TFLAG_CONST: u32 = 2; pub const PFR_TFLAG_ACTIVE: u32 = 4; pub const PFR_TFLAG_INACTIVE: u32 = 8; pub const PFR_TFLAG_REFERENCED: u32 = 16; pub const PFR_TFLAG_REFDANCHOR: u32 = 32; pub const PFR_TFLAG_COUNTERS: u32 = 64; pub const PFR_TFLAG_USRMASK: u32 = 67; pub const PFR_TFLAG_SETMASK: u32 = 60; pub const PFR_TFLAG_ALLMASK: u32 = 127; pub const PFI_IFLAG_REFS: u32 = 1; pub const PFI_IFLAG_SKIP: u32 = 256; pub const PF_DPORT_RANGE: u32 = 1; pub const PF_RPORT_RANGE: u32 = 2; pub const PFUDPS_NO_TRAFFIC: u32 = 0; pub const PFUDPS_SINGLE: u32 = 1; pub const PFUDPS_MULTIPLE: u32 = 2; pub const PFUDPS_NSTATES: u32 = 3; pub const PFOTHERS_NO_TRAFFIC: u32 = 0; pub const PFOTHERS_SINGLE: u32 = 1; pub const PFOTHERS_MULTIPLE: u32 = 2; pub const PFOTHERS_NSTATES: u32 = 3; pub const PF_SYNCOOKIES_HIWATPCT: u32 = 25; pub const PF_SYNCOOKIES_LOWATPCT: u32 = 12; pub const PFFRAG_FRENT_HIWAT: u32 = 5000; pub const PFR_KENTRY_HIWAT: u32 = 200000; pub const PF_FRAG_ENTRY_POINTS: u32 = 16; pub const PF_FRAG_ENTRY_LIMIT: u32 = 64; pub const PFIOC_ALTQ_VERSION: u32 = 1; pub const PFIOC_QSTATS_VERSION: u32 = 1; pub const PFR_FLAG_ATOMIC: u32 = 1; pub const PFR_FLAG_DUMMY: u32 = 2; pub const PFR_FLAG_FEEDBACK: u32 = 4; pub const PFR_FLAG_CLSTATS: u32 = 8; pub const PFR_FLAG_ADDRSTOO: u32 = 16; pub const PFR_FLAG_REPLACE: u32 = 32; pub const PFR_FLAG_ALLRSETS: u32 = 64; pub const PFR_FLAG_ALLMASK: u32 = 127; pub const PF_IFSPEED_VERSION: u32 = 1; pub type __int8_t = ::std::os::raw::c_schar; pub type __uint8_t = ::std::os::raw::c_uchar; pub type __int16_t = ::std::os::raw::c_short; pub type __uint16_t = ::std::os::raw::c_ushort; pub type __int32_t = ::std::os::raw::c_int; pub type __uint32_t = ::std::os::raw::c_uint; pub type __int64_t = ::std::os::raw::c_long; pub type __uint64_t = ::std::os::raw::c_ulong; pub type __int_least8_t = __int8_t; pub type __int_least16_t = __int16_t; pub type __int_least32_t = __int32_t; pub type __int_least64_t = __int64_t; pub type __intmax_t = __int64_t; pub type __uint_least8_t = __uint8_t; pub type __uint_least16_t = __uint16_t; pub type __uint_least32_t = __uint32_t; pub type __uint_least64_t = __uint64_t; pub type __uintmax_t = __uint64_t; pub type __intptr_t = __int64_t; pub type __intfptr_t = __int64_t; pub type __uintptr_t = __uint64_t; pub type __uintfptr_t = __uint64_t; pub type __vm_offset_t = __uint64_t; pub type __vm_size_t = __uint64_t; pub type __size_t = __uint64_t; pub type __ssize_t = __int64_t; pub type __ptrdiff_t = __int64_t; pub type __clock_t = __int32_t; pub type __critical_t = __int64_t; pub type __double_t = f64; pub type __float_t = f32; pub type __int_fast8_t = __int32_t; pub type __int_fast16_t = __int32_t; pub type __int_fast32_t = __int32_t; pub type __int_fast64_t = __int64_t; pub type __register_t = __int64_t; pub type __segsz_t = __int64_t; pub type __time_t = __int64_t; pub type __uint_fast8_t = __uint32_t; pub type __uint_fast16_t = __uint32_t; pub type __uint_fast32_t = __uint32_t; pub type __uint_fast64_t = __uint64_t; pub type __u_register_t = __uint64_t; pub type __vm_paddr_t = __uint64_t; pub type ___wchar_t = ::std::os::raw::c_int; pub type __blksize_t = __int32_t; pub type __blkcnt_t = __int64_t; pub type __clockid_t = __int32_t; pub type __fflags_t = __uint32_t; pub type __fsblkcnt_t = __uint64_t; pub type __fsfilcnt_t = __uint64_t; pub type __gid_t = __uint32_t; pub type __id_t = __int64_t; pub type __ino_t = __uint64_t; pub type __key_t = ::std::os::raw::c_long; pub type __lwpid_t = __int32_t; pub type __mode_t = __uint16_t; pub type __accmode_t = ::std::os::raw::c_int; pub type __nl_item = ::std::os::raw::c_int; pub type __nlink_t = __uint64_t; pub type __off_t = __int64_t; pub type __off64_t = __int64_t; pub type __pid_t = __int32_t; pub type __sbintime_t = __int64_t; pub type __rlim_t = __int64_t; pub type __sa_family_t = __uint8_t; pub type __socklen_t = __uint32_t; pub type __suseconds_t = ::std::os::raw::c_long; #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct __timer { _unused: [u8; 0], } pub type __timer_t = *mut __timer; #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct __mq { _unused: [u8; 0], } pub type __mqd_t = *mut __mq; pub type __uid_t = __uint32_t; pub type __useconds_t = ::std::os::raw::c_uint; pub type __cpuwhich_t = ::std::os::raw::c_int; pub type __cpulevel_t = ::std::os::raw::c_int; pub type __cpusetid_t = ::std::os::raw::c_int; pub type __daddr_t = __int64_t; pub type __ct_rune_t = ::std::os::raw::c_int; pub type __rune_t = __ct_rune_t; pub type __wint_t = __ct_rune_t; pub type __char16_t = __uint_least16_t; pub type __char32_t = __uint_least32_t; #[repr(C)] #[repr(align(16))] #[derive(Debug, Copy, Clone)] pub struct __max_align_t { pub __max_align1: ::std::os::raw::c_longlong, pub __bindgen_padding_0: u64, pub __max_align2: u128, } #[test] fn bindgen_test_layout___max_align_t() { const UNINIT: ::std::mem::MaybeUninit<__max_align_t> = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::<__max_align_t>(), 32usize, concat!("Size of: ", stringify!(__max_align_t)) ); assert_eq!( ::std::mem::align_of::<__max_align_t>(), 16usize, concat!("Alignment of ", stringify!(__max_align_t)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__max_align1) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(__max_align_t), "::", stringify!(__max_align1) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__max_align2) as usize - ptr as usize }, 16usize, concat!( "Offset of field: ", stringify!(__max_align_t), "::", stringify!(__max_align2) ) ); } pub type __dev_t = __uint64_t; pub type __fixpt_t = __uint32_t; #[repr(C)] #[derive(Copy, Clone)] pub union __mbstate_t { pub __mbstate8: [::std::os::raw::c_char; 128usize], pub _mbstateL: __int64_t, } #[test] fn bindgen_test_layout___mbstate_t() { const UNINIT: ::std::mem::MaybeUninit<__mbstate_t> = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::<__mbstate_t>(), 128usize, concat!("Size of: ", stringify!(__mbstate_t)) ); assert_eq!( ::std::mem::align_of::<__mbstate_t>(), 8usize, concat!("Alignment of ", stringify!(__mbstate_t)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__mbstate8) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(__mbstate_t), "::", stringify!(__mbstate8) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr)._mbstateL) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(__mbstate_t), "::", stringify!(_mbstateL) ) ); } pub type __rman_res_t = __uintmax_t; pub type __va_list = __builtin_va_list; pub type __gnuc_va_list = __va_list; #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pthread { _unused: [u8; 0], } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pthread_attr { _unused: [u8; 0], } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pthread_cond { _unused: [u8; 0], } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pthread_cond_attr { _unused: [u8; 0], } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pthread_mutex { _unused: [u8; 0], } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pthread_mutex_attr { _unused: [u8; 0], } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pthread_rwlock { _unused: [u8; 0], } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pthread_rwlockattr { _unused: [u8; 0], } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pthread_barrier { _unused: [u8; 0], } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pthread_barrier_attr { _unused: [u8; 0], } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pthread_spinlock { _unused: [u8; 0], } pub type pthread_t = *mut pthread; pub type pthread_attr_t = *mut pthread_attr; pub type pthread_mutex_t = *mut pthread_mutex; pub type pthread_mutexattr_t = *mut pthread_mutex_attr; pub type pthread_cond_t = *mut pthread_cond; pub type pthread_condattr_t = *mut pthread_cond_attr; pub type pthread_key_t = ::std::os::raw::c_int; pub type pthread_once_t = pthread_once; pub type pthread_rwlock_t = *mut pthread_rwlock; pub type pthread_rwlockattr_t = *mut pthread_rwlockattr; pub type pthread_barrier_t = *mut pthread_barrier; #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pthread_barrierattr { _unused: [u8; 0], } pub type pthread_barrierattr_t = *mut pthread_barrierattr; pub type pthread_spinlock_t = *mut pthread_spinlock; pub type pthread_addr_t = *mut ::std::os::raw::c_void; pub type pthread_startroutine_t = ::std::option::Option *mut ::std::os::raw::c_void>; #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pthread_once { pub state: ::std::os::raw::c_int, pub mutex: pthread_mutex_t, } #[test] fn bindgen_test_layout_pthread_once() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 16usize, concat!("Size of: ", stringify!(pthread_once)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pthread_once)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).state) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(pthread_once), "::", stringify!(state)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).mutex) as usize - ptr as usize }, 8usize, concat!("Offset of field: ", stringify!(pthread_once), "::", stringify!(mutex)) ); } pub type u_char = ::std::os::raw::c_uchar; pub type u_short = ::std::os::raw::c_ushort; pub type u_int = ::std::os::raw::c_uint; pub type u_long = ::std::os::raw::c_ulong; pub type ushort = ::std::os::raw::c_ushort; pub type uint = ::std::os::raw::c_uint; pub type intmax_t = __intmax_t; pub type uintmax_t = __uintmax_t; pub type u_int8_t = __uint8_t; pub type u_int16_t = __uint16_t; pub type u_int32_t = __uint32_t; pub type u_int64_t = __uint64_t; pub type u_quad_t = __uint64_t; pub type quad_t = __int64_t; pub type qaddr_t = *mut quad_t; pub type caddr_t = *mut ::std::os::raw::c_char; pub type c_caddr_t = *const ::std::os::raw::c_char; pub type blksize_t = __blksize_t; pub type cpuwhich_t = __cpuwhich_t; pub type cpulevel_t = __cpulevel_t; pub type cpusetid_t = __cpusetid_t; pub type blkcnt_t = __blkcnt_t; pub type clock_t = __clock_t; pub type clockid_t = __clockid_t; pub type critical_t = __critical_t; pub type daddr_t = __daddr_t; pub type dev_t = __dev_t; pub type fflags_t = __fflags_t; pub type fixpt_t = __fixpt_t; pub type fsblkcnt_t = __fsblkcnt_t; pub type fsfilcnt_t = __fsfilcnt_t; pub type gid_t = __gid_t; pub type in_addr_t = __uint32_t; pub type in_port_t = __uint16_t; pub type id_t = __id_t; pub type ino_t = __ino_t; pub type key_t = __key_t; pub type lwpid_t = __lwpid_t; pub type mode_t = __mode_t; pub type accmode_t = __accmode_t; pub type nlink_t = __nlink_t; pub type off_t = __off_t; pub type off64_t = __off64_t; pub type pid_t = __pid_t; pub type register_t = __register_t; pub type rlim_t = __rlim_t; pub type sbintime_t = __sbintime_t; pub type segsz_t = __segsz_t; pub type suseconds_t = __suseconds_t; pub type time_t = __time_t; pub type timer_t = __timer_t; pub type mqd_t = __mqd_t; pub type u_register_t = __u_register_t; pub type uid_t = __uid_t; pub type useconds_t = __useconds_t; pub type cap_ioctl_t = ::std::os::raw::c_ulong; #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct cap_rights { _unused: [u8; 0], } pub type cap_rights_t = cap_rights; pub type kpaddr_t = __uint64_t; pub type kvaddr_t = __uint64_t; pub type ksize_t = __uint64_t; pub type kssize_t = __int64_t; pub type vm_offset_t = __vm_offset_t; pub type vm_ooffset_t = __uint64_t; pub type vm_paddr_t = __vm_paddr_t; pub type vm_pindex_t = __uint64_t; pub type vm_size_t = __vm_size_t; pub type rman_res_t = __rman_res_t; pub type syscallarg_t = __register_t; #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct __sigset { pub __bits: [__uint32_t; 4usize], } #[test] fn bindgen_test_layout___sigset() { const UNINIT: ::std::mem::MaybeUninit<__sigset> = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::<__sigset>(), 16usize, concat!("Size of: ", stringify!(__sigset)) ); assert_eq!( ::std::mem::align_of::<__sigset>(), 4usize, concat!("Alignment of ", stringify!(__sigset)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__bits) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(__sigset), "::", stringify!(__bits)) ); } pub type __sigset_t = __sigset; #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct timeval { pub tv_sec: time_t, pub tv_usec: suseconds_t, } #[test] fn bindgen_test_layout_timeval() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 16usize, concat!("Size of: ", stringify!(timeval)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(timeval)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).tv_sec) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(timeval), "::", stringify!(tv_sec)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).tv_usec) as usize - ptr as usize }, 8usize, concat!("Offset of field: ", stringify!(timeval), "::", stringify!(tv_usec)) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct timespec { pub tv_sec: time_t, pub tv_nsec: ::std::os::raw::c_long, } #[test] fn bindgen_test_layout_timespec() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 16usize, concat!("Size of: ", stringify!(timespec)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(timespec)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).tv_sec) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(timespec), "::", stringify!(tv_sec)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).tv_nsec) as usize - ptr as usize }, 8usize, concat!("Offset of field: ", stringify!(timespec), "::", stringify!(tv_nsec)) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct itimerspec { pub it_interval: timespec, pub it_value: timespec, } #[test] fn bindgen_test_layout_itimerspec() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 32usize, concat!("Size of: ", stringify!(itimerspec)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(itimerspec)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).it_interval) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(itimerspec), "::", stringify!(it_interval) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).it_value) as usize - ptr as usize }, 16usize, concat!("Offset of field: ", stringify!(itimerspec), "::", stringify!(it_value)) ); } pub type __fd_mask = ::std::os::raw::c_ulong; pub type fd_mask = __fd_mask; pub type sigset_t = __sigset_t; #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct fd_set { pub __fds_bits: [__fd_mask; 16usize], } #[test] fn bindgen_test_layout_fd_set() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 128usize, concat!("Size of: ", stringify!(fd_set)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(fd_set)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fds_bits) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(fd_set), "::", stringify!(__fds_bits)) ); } unsafe extern "C" { pub fn pselect( arg1: ::std::os::raw::c_int, arg2: *mut fd_set, arg3: *mut fd_set, arg4: *mut fd_set, arg5: *const timespec, arg6: *const sigset_t, ) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn select( arg1: ::std::os::raw::c_int, arg2: *mut fd_set, arg3: *mut fd_set, arg4: *mut fd_set, arg5: *mut timeval, ) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn ftruncate(arg1: ::std::os::raw::c_int, arg2: off_t) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn lseek(arg1: ::std::os::raw::c_int, arg2: off_t, arg3: ::std::os::raw::c_int) -> off_t; } unsafe extern "C" { pub fn mmap( arg1: *mut ::std::os::raw::c_void, arg2: usize, arg3: ::std::os::raw::c_int, arg4: ::std::os::raw::c_int, arg5: ::std::os::raw::c_int, arg6: off_t, ) -> *mut ::std::os::raw::c_void; } unsafe extern "C" { pub fn truncate(arg1: *const ::std::os::raw::c_char, arg2: off_t) -> ::std::os::raw::c_int; } pub type sig_atomic_t = ::std::os::raw::c_long; #[repr(C)] #[repr(align(16))] #[derive(Debug, Copy, Clone)] pub struct sigcontext { pub sc_mask: __sigset, pub sc_onstack: ::std::os::raw::c_long, pub sc_rdi: ::std::os::raw::c_long, pub sc_rsi: ::std::os::raw::c_long, pub sc_rdx: ::std::os::raw::c_long, pub sc_rcx: ::std::os::raw::c_long, pub sc_r8: ::std::os::raw::c_long, pub sc_r9: ::std::os::raw::c_long, pub sc_rax: ::std::os::raw::c_long, pub sc_rbx: ::std::os::raw::c_long, pub sc_rbp: ::std::os::raw::c_long, pub sc_r10: ::std::os::raw::c_long, pub sc_r11: ::std::os::raw::c_long, pub sc_r12: ::std::os::raw::c_long, pub sc_r13: ::std::os::raw::c_long, pub sc_r14: ::std::os::raw::c_long, pub sc_r15: ::std::os::raw::c_long, pub sc_trapno: ::std::os::raw::c_int, pub sc_fs: ::std::os::raw::c_short, pub sc_gs: ::std::os::raw::c_short, pub sc_addr: ::std::os::raw::c_long, pub sc_flags: ::std::os::raw::c_int, pub sc_es: ::std::os::raw::c_short, pub sc_ds: ::std::os::raw::c_short, pub sc_err: ::std::os::raw::c_long, pub sc_rip: ::std::os::raw::c_long, pub sc_cs: ::std::os::raw::c_long, pub sc_rflags: ::std::os::raw::c_long, pub sc_rsp: ::std::os::raw::c_long, pub sc_ss: ::std::os::raw::c_long, pub sc_len: ::std::os::raw::c_long, pub sc_fpformat: ::std::os::raw::c_long, pub sc_ownedfp: ::std::os::raw::c_long, pub sc_fpstate: [::std::os::raw::c_long; 64usize], pub sc_fsbase: ::std::os::raw::c_long, pub sc_gsbase: ::std::os::raw::c_long, pub sc_xfpustate: ::std::os::raw::c_long, pub sc_xfpustate_len: ::std::os::raw::c_long, pub sc_spare: [::std::os::raw::c_long; 4usize], } #[test] fn bindgen_test_layout_sigcontext() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 816usize, concat!("Size of: ", stringify!(sigcontext)) ); assert_eq!( ::std::mem::align_of::(), 16usize, concat!("Alignment of ", stringify!(sigcontext)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).sc_mask) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(sigcontext), "::", stringify!(sc_mask)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).sc_onstack) as usize - ptr as usize }, 16usize, concat!( "Offset of field: ", stringify!(sigcontext), "::", stringify!(sc_onstack) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).sc_rdi) as usize - ptr as usize }, 24usize, concat!("Offset of field: ", stringify!(sigcontext), "::", stringify!(sc_rdi)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).sc_rsi) as usize - ptr as usize }, 32usize, concat!("Offset of field: ", stringify!(sigcontext), "::", stringify!(sc_rsi)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).sc_rdx) as usize - ptr as usize }, 40usize, concat!("Offset of field: ", stringify!(sigcontext), "::", stringify!(sc_rdx)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).sc_rcx) as usize - ptr as usize }, 48usize, concat!("Offset of field: ", stringify!(sigcontext), "::", stringify!(sc_rcx)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).sc_r8) as usize - ptr as usize }, 56usize, concat!("Offset of field: ", stringify!(sigcontext), "::", stringify!(sc_r8)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).sc_r9) as usize - ptr as usize }, 64usize, concat!("Offset of field: ", stringify!(sigcontext), "::", stringify!(sc_r9)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).sc_rax) as usize - ptr as usize }, 72usize, concat!("Offset of field: ", stringify!(sigcontext), "::", stringify!(sc_rax)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).sc_rbx) as usize - ptr as usize }, 80usize, concat!("Offset of field: ", stringify!(sigcontext), "::", stringify!(sc_rbx)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).sc_rbp) as usize - ptr as usize }, 88usize, concat!("Offset of field: ", stringify!(sigcontext), "::", stringify!(sc_rbp)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).sc_r10) as usize - ptr as usize }, 96usize, concat!("Offset of field: ", stringify!(sigcontext), "::", stringify!(sc_r10)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).sc_r11) as usize - ptr as usize }, 104usize, concat!("Offset of field: ", stringify!(sigcontext), "::", stringify!(sc_r11)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).sc_r12) as usize - ptr as usize }, 112usize, concat!("Offset of field: ", stringify!(sigcontext), "::", stringify!(sc_r12)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).sc_r13) as usize - ptr as usize }, 120usize, concat!("Offset of field: ", stringify!(sigcontext), "::", stringify!(sc_r13)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).sc_r14) as usize - ptr as usize }, 128usize, concat!("Offset of field: ", stringify!(sigcontext), "::", stringify!(sc_r14)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).sc_r15) as usize - ptr as usize }, 136usize, concat!("Offset of field: ", stringify!(sigcontext), "::", stringify!(sc_r15)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).sc_trapno) as usize - ptr as usize }, 144usize, concat!("Offset of field: ", stringify!(sigcontext), "::", stringify!(sc_trapno)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).sc_fs) as usize - ptr as usize }, 148usize, concat!("Offset of field: ", stringify!(sigcontext), "::", stringify!(sc_fs)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).sc_gs) as usize - ptr as usize }, 150usize, concat!("Offset of field: ", stringify!(sigcontext), "::", stringify!(sc_gs)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).sc_addr) as usize - ptr as usize }, 152usize, concat!("Offset of field: ", stringify!(sigcontext), "::", stringify!(sc_addr)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).sc_flags) as usize - ptr as usize }, 160usize, concat!("Offset of field: ", stringify!(sigcontext), "::", stringify!(sc_flags)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).sc_es) as usize - ptr as usize }, 164usize, concat!("Offset of field: ", stringify!(sigcontext), "::", stringify!(sc_es)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).sc_ds) as usize - ptr as usize }, 166usize, concat!("Offset of field: ", stringify!(sigcontext), "::", stringify!(sc_ds)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).sc_err) as usize - ptr as usize }, 168usize, concat!("Offset of field: ", stringify!(sigcontext), "::", stringify!(sc_err)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).sc_rip) as usize - ptr as usize }, 176usize, concat!("Offset of field: ", stringify!(sigcontext), "::", stringify!(sc_rip)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).sc_cs) as usize - ptr as usize }, 184usize, concat!("Offset of field: ", stringify!(sigcontext), "::", stringify!(sc_cs)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).sc_rflags) as usize - ptr as usize }, 192usize, concat!("Offset of field: ", stringify!(sigcontext), "::", stringify!(sc_rflags)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).sc_rsp) as usize - ptr as usize }, 200usize, concat!("Offset of field: ", stringify!(sigcontext), "::", stringify!(sc_rsp)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).sc_ss) as usize - ptr as usize }, 208usize, concat!("Offset of field: ", stringify!(sigcontext), "::", stringify!(sc_ss)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).sc_len) as usize - ptr as usize }, 216usize, concat!("Offset of field: ", stringify!(sigcontext), "::", stringify!(sc_len)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).sc_fpformat) as usize - ptr as usize }, 224usize, concat!( "Offset of field: ", stringify!(sigcontext), "::", stringify!(sc_fpformat) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).sc_ownedfp) as usize - ptr as usize }, 232usize, concat!( "Offset of field: ", stringify!(sigcontext), "::", stringify!(sc_ownedfp) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).sc_fpstate) as usize - ptr as usize }, 240usize, concat!( "Offset of field: ", stringify!(sigcontext), "::", stringify!(sc_fpstate) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).sc_fsbase) as usize - ptr as usize }, 752usize, concat!("Offset of field: ", stringify!(sigcontext), "::", stringify!(sc_fsbase)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).sc_gsbase) as usize - ptr as usize }, 760usize, concat!("Offset of field: ", stringify!(sigcontext), "::", stringify!(sc_gsbase)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).sc_xfpustate) as usize - ptr as usize }, 768usize, concat!( "Offset of field: ", stringify!(sigcontext), "::", stringify!(sc_xfpustate) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).sc_xfpustate_len) as usize - ptr as usize }, 776usize, concat!( "Offset of field: ", stringify!(sigcontext), "::", stringify!(sc_xfpustate_len) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).sc_spare) as usize - ptr as usize }, 784usize, concat!("Offset of field: ", stringify!(sigcontext), "::", stringify!(sc_spare)) ); } pub type __sighandler_t = ::std::option::Option; #[repr(C)] #[derive(Copy, Clone)] pub union sigval { pub sival_int: ::std::os::raw::c_int, pub sival_ptr: *mut ::std::os::raw::c_void, pub sigval_int: ::std::os::raw::c_int, pub sigval_ptr: *mut ::std::os::raw::c_void, } #[test] fn bindgen_test_layout_sigval() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 8usize, concat!("Size of: ", stringify!(sigval)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(sigval)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).sival_int) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(sigval), "::", stringify!(sival_int)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).sival_ptr) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(sigval), "::", stringify!(sival_ptr)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).sigval_int) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(sigval), "::", stringify!(sigval_int)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).sigval_ptr) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(sigval), "::", stringify!(sigval_ptr)) ); } #[repr(C)] #[derive(Copy, Clone)] pub struct sigevent { pub sigev_notify: ::std::os::raw::c_int, pub sigev_signo: ::std::os::raw::c_int, pub sigev_value: sigval, pub _sigev_un: sigevent__bindgen_ty_1, } #[repr(C)] #[derive(Copy, Clone)] pub union sigevent__bindgen_ty_1 { pub _threadid: __lwpid_t, pub _sigev_thread: sigevent__bindgen_ty_1__bindgen_ty_1, pub _kevent_flags: ::std::os::raw::c_ushort, pub __spare__: [::std::os::raw::c_long; 8usize], } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct sigevent__bindgen_ty_1__bindgen_ty_1 { pub _function: ::std::option::Option, pub _attribute: *mut *mut pthread_attr, } #[test] fn bindgen_test_layout_sigevent__bindgen_ty_1__bindgen_ty_1() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 16usize, concat!("Size of: ", stringify!(sigevent__bindgen_ty_1__bindgen_ty_1)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(sigevent__bindgen_ty_1__bindgen_ty_1)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr)._function) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(sigevent__bindgen_ty_1__bindgen_ty_1), "::", stringify!(_function) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr)._attribute) as usize - ptr as usize }, 8usize, concat!( "Offset of field: ", stringify!(sigevent__bindgen_ty_1__bindgen_ty_1), "::", stringify!(_attribute) ) ); } #[test] fn bindgen_test_layout_sigevent__bindgen_ty_1() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 64usize, concat!("Size of: ", stringify!(sigevent__bindgen_ty_1)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(sigevent__bindgen_ty_1)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr)._threadid) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(sigevent__bindgen_ty_1), "::", stringify!(_threadid) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr)._sigev_thread) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(sigevent__bindgen_ty_1), "::", stringify!(_sigev_thread) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr)._kevent_flags) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(sigevent__bindgen_ty_1), "::", stringify!(_kevent_flags) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__spare__) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(sigevent__bindgen_ty_1), "::", stringify!(__spare__) ) ); } #[test] fn bindgen_test_layout_sigevent() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 80usize, concat!("Size of: ", stringify!(sigevent)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(sigevent)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).sigev_notify) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(sigevent), "::", stringify!(sigev_notify) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).sigev_signo) as usize - ptr as usize }, 4usize, concat!("Offset of field: ", stringify!(sigevent), "::", stringify!(sigev_signo)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).sigev_value) as usize - ptr as usize }, 8usize, concat!("Offset of field: ", stringify!(sigevent), "::", stringify!(sigev_value)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr)._sigev_un) as usize - ptr as usize }, 16usize, concat!("Offset of field: ", stringify!(sigevent), "::", stringify!(_sigev_un)) ); } #[repr(C)] #[derive(Copy, Clone)] pub struct __siginfo { pub si_signo: ::std::os::raw::c_int, pub si_errno: ::std::os::raw::c_int, pub si_code: ::std::os::raw::c_int, pub si_pid: __pid_t, pub si_uid: __uid_t, pub si_status: ::std::os::raw::c_int, pub si_addr: *mut ::std::os::raw::c_void, pub si_value: sigval, pub _reason: __siginfo__bindgen_ty_1, } #[repr(C)] #[derive(Copy, Clone)] pub union __siginfo__bindgen_ty_1 { pub _fault: __siginfo__bindgen_ty_1__bindgen_ty_1, pub _timer: __siginfo__bindgen_ty_1__bindgen_ty_2, pub _mesgq: __siginfo__bindgen_ty_1__bindgen_ty_3, pub _poll: __siginfo__bindgen_ty_1__bindgen_ty_4, pub _capsicum: __siginfo__bindgen_ty_1__bindgen_ty_5, pub __spare__: __siginfo__bindgen_ty_1__bindgen_ty_6, } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct __siginfo__bindgen_ty_1__bindgen_ty_1 { pub _trapno: ::std::os::raw::c_int, } #[test] fn bindgen_test_layout___siginfo__bindgen_ty_1__bindgen_ty_1() { const UNINIT: ::std::mem::MaybeUninit<__siginfo__bindgen_ty_1__bindgen_ty_1> = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::<__siginfo__bindgen_ty_1__bindgen_ty_1>(), 4usize, concat!("Size of: ", stringify!(__siginfo__bindgen_ty_1__bindgen_ty_1)) ); assert_eq!( ::std::mem::align_of::<__siginfo__bindgen_ty_1__bindgen_ty_1>(), 4usize, concat!("Alignment of ", stringify!(__siginfo__bindgen_ty_1__bindgen_ty_1)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr)._trapno) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(__siginfo__bindgen_ty_1__bindgen_ty_1), "::", stringify!(_trapno) ) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct __siginfo__bindgen_ty_1__bindgen_ty_2 { pub _timerid: ::std::os::raw::c_int, pub _overrun: ::std::os::raw::c_int, } #[test] fn bindgen_test_layout___siginfo__bindgen_ty_1__bindgen_ty_2() { const UNINIT: ::std::mem::MaybeUninit<__siginfo__bindgen_ty_1__bindgen_ty_2> = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::<__siginfo__bindgen_ty_1__bindgen_ty_2>(), 8usize, concat!("Size of: ", stringify!(__siginfo__bindgen_ty_1__bindgen_ty_2)) ); assert_eq!( ::std::mem::align_of::<__siginfo__bindgen_ty_1__bindgen_ty_2>(), 4usize, concat!("Alignment of ", stringify!(__siginfo__bindgen_ty_1__bindgen_ty_2)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr)._timerid) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(__siginfo__bindgen_ty_1__bindgen_ty_2), "::", stringify!(_timerid) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr)._overrun) as usize - ptr as usize }, 4usize, concat!( "Offset of field: ", stringify!(__siginfo__bindgen_ty_1__bindgen_ty_2), "::", stringify!(_overrun) ) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct __siginfo__bindgen_ty_1__bindgen_ty_3 { pub _mqd: ::std::os::raw::c_int, } #[test] fn bindgen_test_layout___siginfo__bindgen_ty_1__bindgen_ty_3() { const UNINIT: ::std::mem::MaybeUninit<__siginfo__bindgen_ty_1__bindgen_ty_3> = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::<__siginfo__bindgen_ty_1__bindgen_ty_3>(), 4usize, concat!("Size of: ", stringify!(__siginfo__bindgen_ty_1__bindgen_ty_3)) ); assert_eq!( ::std::mem::align_of::<__siginfo__bindgen_ty_1__bindgen_ty_3>(), 4usize, concat!("Alignment of ", stringify!(__siginfo__bindgen_ty_1__bindgen_ty_3)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr)._mqd) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(__siginfo__bindgen_ty_1__bindgen_ty_3), "::", stringify!(_mqd) ) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct __siginfo__bindgen_ty_1__bindgen_ty_4 { pub _band: ::std::os::raw::c_long, } #[test] fn bindgen_test_layout___siginfo__bindgen_ty_1__bindgen_ty_4() { const UNINIT: ::std::mem::MaybeUninit<__siginfo__bindgen_ty_1__bindgen_ty_4> = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::<__siginfo__bindgen_ty_1__bindgen_ty_4>(), 8usize, concat!("Size of: ", stringify!(__siginfo__bindgen_ty_1__bindgen_ty_4)) ); assert_eq!( ::std::mem::align_of::<__siginfo__bindgen_ty_1__bindgen_ty_4>(), 8usize, concat!("Alignment of ", stringify!(__siginfo__bindgen_ty_1__bindgen_ty_4)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr)._band) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(__siginfo__bindgen_ty_1__bindgen_ty_4), "::", stringify!(_band) ) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct __siginfo__bindgen_ty_1__bindgen_ty_5 { pub _syscall: ::std::os::raw::c_int, } #[test] fn bindgen_test_layout___siginfo__bindgen_ty_1__bindgen_ty_5() { const UNINIT: ::std::mem::MaybeUninit<__siginfo__bindgen_ty_1__bindgen_ty_5> = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::<__siginfo__bindgen_ty_1__bindgen_ty_5>(), 4usize, concat!("Size of: ", stringify!(__siginfo__bindgen_ty_1__bindgen_ty_5)) ); assert_eq!( ::std::mem::align_of::<__siginfo__bindgen_ty_1__bindgen_ty_5>(), 4usize, concat!("Alignment of ", stringify!(__siginfo__bindgen_ty_1__bindgen_ty_5)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr)._syscall) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(__siginfo__bindgen_ty_1__bindgen_ty_5), "::", stringify!(_syscall) ) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct __siginfo__bindgen_ty_1__bindgen_ty_6 { pub __spare1__: ::std::os::raw::c_long, pub __spare2__: [::std::os::raw::c_int; 7usize], } #[test] fn bindgen_test_layout___siginfo__bindgen_ty_1__bindgen_ty_6() { const UNINIT: ::std::mem::MaybeUninit<__siginfo__bindgen_ty_1__bindgen_ty_6> = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::<__siginfo__bindgen_ty_1__bindgen_ty_6>(), 40usize, concat!("Size of: ", stringify!(__siginfo__bindgen_ty_1__bindgen_ty_6)) ); assert_eq!( ::std::mem::align_of::<__siginfo__bindgen_ty_1__bindgen_ty_6>(), 8usize, concat!("Alignment of ", stringify!(__siginfo__bindgen_ty_1__bindgen_ty_6)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__spare1__) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(__siginfo__bindgen_ty_1__bindgen_ty_6), "::", stringify!(__spare1__) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__spare2__) as usize - ptr as usize }, 8usize, concat!( "Offset of field: ", stringify!(__siginfo__bindgen_ty_1__bindgen_ty_6), "::", stringify!(__spare2__) ) ); } #[test] fn bindgen_test_layout___siginfo__bindgen_ty_1() { const UNINIT: ::std::mem::MaybeUninit<__siginfo__bindgen_ty_1> = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::<__siginfo__bindgen_ty_1>(), 40usize, concat!("Size of: ", stringify!(__siginfo__bindgen_ty_1)) ); assert_eq!( ::std::mem::align_of::<__siginfo__bindgen_ty_1>(), 8usize, concat!("Alignment of ", stringify!(__siginfo__bindgen_ty_1)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr)._fault) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(__siginfo__bindgen_ty_1), "::", stringify!(_fault) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr)._timer) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(__siginfo__bindgen_ty_1), "::", stringify!(_timer) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr)._mesgq) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(__siginfo__bindgen_ty_1), "::", stringify!(_mesgq) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr)._poll) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(__siginfo__bindgen_ty_1), "::", stringify!(_poll) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr)._capsicum) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(__siginfo__bindgen_ty_1), "::", stringify!(_capsicum) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__spare__) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(__siginfo__bindgen_ty_1), "::", stringify!(__spare__) ) ); } #[test] fn bindgen_test_layout___siginfo() { const UNINIT: ::std::mem::MaybeUninit<__siginfo> = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::<__siginfo>(), 80usize, concat!("Size of: ", stringify!(__siginfo)) ); assert_eq!( ::std::mem::align_of::<__siginfo>(), 8usize, concat!("Alignment of ", stringify!(__siginfo)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).si_signo) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(__siginfo), "::", stringify!(si_signo)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).si_errno) as usize - ptr as usize }, 4usize, concat!("Offset of field: ", stringify!(__siginfo), "::", stringify!(si_errno)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).si_code) as usize - ptr as usize }, 8usize, concat!("Offset of field: ", stringify!(__siginfo), "::", stringify!(si_code)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).si_pid) as usize - ptr as usize }, 12usize, concat!("Offset of field: ", stringify!(__siginfo), "::", stringify!(si_pid)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).si_uid) as usize - ptr as usize }, 16usize, concat!("Offset of field: ", stringify!(__siginfo), "::", stringify!(si_uid)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).si_status) as usize - ptr as usize }, 20usize, concat!("Offset of field: ", stringify!(__siginfo), "::", stringify!(si_status)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).si_addr) as usize - ptr as usize }, 24usize, concat!("Offset of field: ", stringify!(__siginfo), "::", stringify!(si_addr)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).si_value) as usize - ptr as usize }, 32usize, concat!("Offset of field: ", stringify!(__siginfo), "::", stringify!(si_value)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr)._reason) as usize - ptr as usize }, 40usize, concat!("Offset of field: ", stringify!(__siginfo), "::", stringify!(_reason)) ); } pub type siginfo_t = __siginfo; #[repr(C)] #[derive(Copy, Clone)] pub struct sigaction { pub __sigaction_u: sigaction__bindgen_ty_1, pub sa_flags: ::std::os::raw::c_int, pub sa_mask: sigset_t, } #[repr(C)] #[derive(Copy, Clone)] pub union sigaction__bindgen_ty_1 { pub __sa_handler: ::std::option::Option, pub __sa_sigaction: ::std::option::Option< unsafe extern "C" fn(arg1: ::std::os::raw::c_int, arg2: *mut __siginfo, arg3: *mut ::std::os::raw::c_void), >, } #[test] fn bindgen_test_layout_sigaction__bindgen_ty_1() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 8usize, concat!("Size of: ", stringify!(sigaction__bindgen_ty_1)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(sigaction__bindgen_ty_1)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__sa_handler) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(sigaction__bindgen_ty_1), "::", stringify!(__sa_handler) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__sa_sigaction) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(sigaction__bindgen_ty_1), "::", stringify!(__sa_sigaction) ) ); } #[test] fn bindgen_test_layout_sigaction() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 32usize, concat!("Size of: ", stringify!(sigaction)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(sigaction)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__sigaction_u) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(sigaction), "::", stringify!(__sigaction_u) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).sa_flags) as usize - ptr as usize }, 8usize, concat!("Offset of field: ", stringify!(sigaction), "::", stringify!(sa_flags)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).sa_mask) as usize - ptr as usize }, 12usize, concat!("Offset of field: ", stringify!(sigaction), "::", stringify!(sa_mask)) ); } pub type sig_t = __sighandler_t; pub type __siginfohandler_t = ::std::option::Option< unsafe extern "C" fn(arg1: ::std::os::raw::c_int, arg2: *mut __siginfo, arg3: *mut ::std::os::raw::c_void), >; pub type stack_t = sigaltstack; #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct sigaltstack { pub ss_sp: *mut ::std::os::raw::c_void, pub ss_size: __size_t, pub ss_flags: ::std::os::raw::c_int, } #[test] fn bindgen_test_layout_sigaltstack() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 24usize, concat!("Size of: ", stringify!(sigaltstack)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(sigaltstack)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ss_sp) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(sigaltstack), "::", stringify!(ss_sp)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ss_size) as usize - ptr as usize }, 8usize, concat!("Offset of field: ", stringify!(sigaltstack), "::", stringify!(ss_size)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ss_flags) as usize - ptr as usize }, 16usize, concat!("Offset of field: ", stringify!(sigaltstack), "::", stringify!(ss_flags)) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct sigvec { pub sv_handler: __sighandler_t, pub sv_mask: ::std::os::raw::c_int, pub sv_flags: ::std::os::raw::c_int, } #[test] fn bindgen_test_layout_sigvec() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 16usize, concat!("Size of: ", stringify!(sigvec)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(sigvec)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).sv_handler) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(sigvec), "::", stringify!(sv_handler)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).sv_mask) as usize - ptr as usize }, 8usize, concat!("Offset of field: ", stringify!(sigvec), "::", stringify!(sv_mask)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).sv_flags) as usize - ptr as usize }, 12usize, concat!("Offset of field: ", stringify!(sigvec), "::", stringify!(sv_flags)) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct sigstack { pub ss_sp: *mut ::std::os::raw::c_void, pub ss_onstack: ::std::os::raw::c_int, } #[test] fn bindgen_test_layout_sigstack() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 16usize, concat!("Size of: ", stringify!(sigstack)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(sigstack)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ss_sp) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(sigstack), "::", stringify!(ss_sp)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ss_onstack) as usize - ptr as usize }, 8usize, concat!("Offset of field: ", stringify!(sigstack), "::", stringify!(ss_onstack)) ); } unsafe extern "C" { pub fn signal(arg1: ::std::os::raw::c_int, arg2: __sighandler_t) -> __sighandler_t; } pub type counter_u64_t = *mut u64; #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct _cpuset { pub __bits: [::std::os::raw::c_long; 16usize], } #[test] fn bindgen_test_layout__cpuset() { const UNINIT: ::std::mem::MaybeUninit<_cpuset> = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::<_cpuset>(), 128usize, concat!("Size of: ", stringify!(_cpuset)) ); assert_eq!( ::std::mem::align_of::<_cpuset>(), 8usize, concat!("Alignment of ", stringify!(_cpuset)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__bits) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(_cpuset), "::", stringify!(__bits)) ); } pub type cpuset_t = _cpuset; unsafe extern "C" { pub fn __cpuset_alloc(set_size: usize) -> *mut cpuset_t; } unsafe extern "C" { pub fn __cpuset_free(ptr: *mut cpuset_t); } unsafe extern "C" { pub fn cpuset(arg1: *mut cpusetid_t) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn cpuset_setid(arg1: cpuwhich_t, arg2: id_t, arg3: cpusetid_t) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn cpuset_getid(arg1: cpulevel_t, arg2: cpuwhich_t, arg3: id_t, arg4: *mut cpusetid_t) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn cpuset_getaffinity( arg1: cpulevel_t, arg2: cpuwhich_t, arg3: id_t, arg4: usize, arg5: *mut cpuset_t, ) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn cpuset_setaffinity( arg1: cpulevel_t, arg2: cpuwhich_t, arg3: id_t, arg4: usize, arg5: *const cpuset_t, ) -> ::std::os::raw::c_int; } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct epoch_context { pub data: [*mut ::std::os::raw::c_void; 2usize], } #[test] fn bindgen_test_layout_epoch_context() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 16usize, concat!("Size of: ", stringify!(epoch_context)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(epoch_context)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).data) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(epoch_context), "::", stringify!(data)) ); } pub type epoch_context_t = *mut epoch_context; pub type epoch_callback_t = ::std::option::Option; #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct lock_object { pub lo_name: *const ::std::os::raw::c_char, pub lo_flags: u_int, pub lo_data: u_int, pub lo_witness: *mut witness, } #[test] fn bindgen_test_layout_lock_object() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 24usize, concat!("Size of: ", stringify!(lock_object)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(lock_object)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).lo_name) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(lock_object), "::", stringify!(lo_name)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).lo_flags) as usize - ptr as usize }, 8usize, concat!("Offset of field: ", stringify!(lock_object), "::", stringify!(lo_flags)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).lo_data) as usize - ptr as usize }, 12usize, concat!("Offset of field: ", stringify!(lock_object), "::", stringify!(lo_data)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).lo_witness) as usize - ptr as usize }, 16usize, concat!( "Offset of field: ", stringify!(lock_object), "::", stringify!(lo_witness) ) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct mtx { pub lock_object: lock_object, pub mtx_lock: usize, } #[test] fn bindgen_test_layout_mtx() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 32usize, concat!("Size of: ", stringify!(mtx)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(mtx)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).lock_object) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(mtx), "::", stringify!(lock_object)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).mtx_lock) as usize - ptr as usize }, 24usize, concat!("Offset of field: ", stringify!(mtx), "::", stringify!(mtx_lock)) ); } #[repr(C)] #[repr(align(64))] #[derive(Debug, Copy, Clone)] pub struct mtx_padalign { pub lock_object: lock_object, pub mtx_lock: usize, } #[test] fn bindgen_test_layout_mtx_padalign() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 64usize, concat!("Size of: ", stringify!(mtx_padalign)) ); assert_eq!( ::std::mem::align_of::(), 64usize, concat!("Alignment of ", stringify!(mtx_padalign)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).lock_object) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(mtx_padalign), "::", stringify!(lock_object) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).mtx_lock) as usize - ptr as usize }, 24usize, concat!( "Offset of field: ", stringify!(mtx_padalign), "::", stringify!(mtx_lock) ) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct malloc_type_stats { pub mts_memalloced: u64, pub mts_memfreed: u64, pub mts_numallocs: u64, pub mts_numfrees: u64, pub mts_size: u64, pub _mts_reserved1: u64, pub _mts_reserved2: u64, pub _mts_reserved3: u64, } #[test] fn bindgen_test_layout_malloc_type_stats() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 64usize, concat!("Size of: ", stringify!(malloc_type_stats)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(malloc_type_stats)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).mts_memalloced) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(malloc_type_stats), "::", stringify!(mts_memalloced) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).mts_memfreed) as usize - ptr as usize }, 8usize, concat!( "Offset of field: ", stringify!(malloc_type_stats), "::", stringify!(mts_memfreed) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).mts_numallocs) as usize - ptr as usize }, 16usize, concat!( "Offset of field: ", stringify!(malloc_type_stats), "::", stringify!(mts_numallocs) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).mts_numfrees) as usize - ptr as usize }, 24usize, concat!( "Offset of field: ", stringify!(malloc_type_stats), "::", stringify!(mts_numfrees) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).mts_size) as usize - ptr as usize }, 32usize, concat!( "Offset of field: ", stringify!(malloc_type_stats), "::", stringify!(mts_size) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr)._mts_reserved1) as usize - ptr as usize }, 40usize, concat!( "Offset of field: ", stringify!(malloc_type_stats), "::", stringify!(_mts_reserved1) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr)._mts_reserved2) as usize - ptr as usize }, 48usize, concat!( "Offset of field: ", stringify!(malloc_type_stats), "::", stringify!(_mts_reserved2) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr)._mts_reserved3) as usize - ptr as usize }, 56usize, concat!( "Offset of field: ", stringify!(malloc_type_stats), "::", stringify!(_mts_reserved3) ) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct malloc_type_internal { pub mti_probes: [u32; 2usize], pub mti_zone: u_char, pub mti_stats: *mut malloc_type_stats, pub mti_spare: [u_long; 8usize], } #[test] fn bindgen_test_layout_malloc_type_internal() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 88usize, concat!("Size of: ", stringify!(malloc_type_internal)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(malloc_type_internal)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).mti_probes) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(malloc_type_internal), "::", stringify!(mti_probes) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).mti_zone) as usize - ptr as usize }, 8usize, concat!( "Offset of field: ", stringify!(malloc_type_internal), "::", stringify!(mti_zone) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).mti_stats) as usize - ptr as usize }, 16usize, concat!( "Offset of field: ", stringify!(malloc_type_internal), "::", stringify!(mti_stats) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).mti_spare) as usize - ptr as usize }, 24usize, concat!( "Offset of field: ", stringify!(malloc_type_internal), "::", stringify!(mti_spare) ) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct malloc_type { pub ks_next: *mut malloc_type, pub ks_version: u_long, pub ks_shortdesc: *const ::std::os::raw::c_char, pub ks_mti: malloc_type_internal, } #[test] fn bindgen_test_layout_malloc_type() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 112usize, concat!("Size of: ", stringify!(malloc_type)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(malloc_type)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ks_next) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(malloc_type), "::", stringify!(ks_next)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ks_version) as usize - ptr as usize }, 8usize, concat!( "Offset of field: ", stringify!(malloc_type), "::", stringify!(ks_version) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ks_shortdesc) as usize - ptr as usize }, 16usize, concat!( "Offset of field: ", stringify!(malloc_type), "::", stringify!(ks_shortdesc) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ks_mti) as usize - ptr as usize }, 24usize, concat!("Offset of field: ", stringify!(malloc_type), "::", stringify!(ks_mti)) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct malloc_type_stream_header { pub mtsh_version: u32, pub mtsh_maxcpus: u32, pub mtsh_count: u32, pub _mtsh_pad: u32, } #[test] fn bindgen_test_layout_malloc_type_stream_header() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 16usize, concat!("Size of: ", stringify!(malloc_type_stream_header)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(malloc_type_stream_header)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).mtsh_version) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(malloc_type_stream_header), "::", stringify!(mtsh_version) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).mtsh_maxcpus) as usize - ptr as usize }, 4usize, concat!( "Offset of field: ", stringify!(malloc_type_stream_header), "::", stringify!(mtsh_maxcpus) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).mtsh_count) as usize - ptr as usize }, 8usize, concat!( "Offset of field: ", stringify!(malloc_type_stream_header), "::", stringify!(mtsh_count) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr)._mtsh_pad) as usize - ptr as usize }, 12usize, concat!( "Offset of field: ", stringify!(malloc_type_stream_header), "::", stringify!(_mtsh_pad) ) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct malloc_type_header { pub mth_name: [::std::os::raw::c_char; 32usize], } #[test] fn bindgen_test_layout_malloc_type_header() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 32usize, concat!("Size of: ", stringify!(malloc_type_header)) ); assert_eq!( ::std::mem::align_of::(), 1usize, concat!("Alignment of ", stringify!(malloc_type_header)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).mth_name) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(malloc_type_header), "::", stringify!(mth_name) ) ); } pub type va_list = __va_list; pub type int_least8_t = __int_least8_t; pub type int_least16_t = __int_least16_t; pub type int_least32_t = __int_least32_t; pub type int_least64_t = __int_least64_t; pub type uint_least8_t = __uint_least8_t; pub type uint_least16_t = __uint_least16_t; pub type uint_least32_t = __uint_least32_t; pub type uint_least64_t = __uint_least64_t; pub type int_fast8_t = __int_fast8_t; pub type int_fast16_t = __int_fast16_t; pub type int_fast32_t = __int_fast32_t; pub type int_fast64_t = __int_fast64_t; pub type uint_fast8_t = __uint_fast8_t; pub type uint_fast16_t = __uint_fast16_t; pub type uint_fast32_t = __uint_fast32_t; pub type uint_fast64_t = __uint_fast64_t; pub type fpos_t = __off_t; pub type rsize_t = usize; #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct __sbuf { pub _base: *mut ::std::os::raw::c_uchar, pub _size: ::std::os::raw::c_int, } #[test] fn bindgen_test_layout___sbuf() { const UNINIT: ::std::mem::MaybeUninit<__sbuf> = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::<__sbuf>(), 16usize, concat!("Size of: ", stringify!(__sbuf)) ); assert_eq!( ::std::mem::align_of::<__sbuf>(), 8usize, concat!("Alignment of ", stringify!(__sbuf)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr)._base) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(__sbuf), "::", stringify!(_base)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr)._size) as usize - ptr as usize }, 8usize, concat!("Offset of field: ", stringify!(__sbuf), "::", stringify!(_size)) ); } #[repr(C)] #[derive(Copy, Clone)] pub struct __sFILE { pub _p: *mut ::std::os::raw::c_uchar, pub _r: ::std::os::raw::c_int, pub _w: ::std::os::raw::c_int, pub _flags: ::std::os::raw::c_short, pub _file: ::std::os::raw::c_short, pub _bf: __sbuf, pub _lbfsize: ::std::os::raw::c_int, pub _cookie: *mut ::std::os::raw::c_void, pub _close: ::std::option::Option ::std::os::raw::c_int>, pub _read: ::std::option::Option< unsafe extern "C" fn( arg1: *mut ::std::os::raw::c_void, arg2: *mut ::std::os::raw::c_char, arg3: ::std::os::raw::c_int, ) -> ::std::os::raw::c_int, >, pub _seek: ::std::option::Option< unsafe extern "C" fn(arg1: *mut ::std::os::raw::c_void, arg2: fpos_t, arg3: ::std::os::raw::c_int) -> fpos_t, >, pub _write: ::std::option::Option< unsafe extern "C" fn( arg1: *mut ::std::os::raw::c_void, arg2: *const ::std::os::raw::c_char, arg3: ::std::os::raw::c_int, ) -> ::std::os::raw::c_int, >, pub _ub: __sbuf, pub _up: *mut ::std::os::raw::c_uchar, pub _ur: ::std::os::raw::c_int, pub _ubuf: [::std::os::raw::c_uchar; 3usize], pub _nbuf: [::std::os::raw::c_uchar; 1usize], pub _lb: __sbuf, pub _blksize: ::std::os::raw::c_int, pub _offset: fpos_t, pub _fl_mutex: *mut pthread_mutex, pub _fl_owner: *mut pthread, pub _fl_count: ::std::os::raw::c_int, pub _orientation: ::std::os::raw::c_int, pub _mbstate: __mbstate_t, pub _flags2: ::std::os::raw::c_int, } #[test] fn bindgen_test_layout___sFILE() { const UNINIT: ::std::mem::MaybeUninit<__sFILE> = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::<__sFILE>(), 312usize, concat!("Size of: ", stringify!(__sFILE)) ); assert_eq!( ::std::mem::align_of::<__sFILE>(), 8usize, concat!("Alignment of ", stringify!(__sFILE)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr)._p) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(__sFILE), "::", stringify!(_p)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr)._r) as usize - ptr as usize }, 8usize, concat!("Offset of field: ", stringify!(__sFILE), "::", stringify!(_r)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr)._w) as usize - ptr as usize }, 12usize, concat!("Offset of field: ", stringify!(__sFILE), "::", stringify!(_w)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr)._flags) as usize - ptr as usize }, 16usize, concat!("Offset of field: ", stringify!(__sFILE), "::", stringify!(_flags)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr)._file) as usize - ptr as usize }, 18usize, concat!("Offset of field: ", stringify!(__sFILE), "::", stringify!(_file)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr)._bf) as usize - ptr as usize }, 24usize, concat!("Offset of field: ", stringify!(__sFILE), "::", stringify!(_bf)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr)._lbfsize) as usize - ptr as usize }, 40usize, concat!("Offset of field: ", stringify!(__sFILE), "::", stringify!(_lbfsize)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr)._cookie) as usize - ptr as usize }, 48usize, concat!("Offset of field: ", stringify!(__sFILE), "::", stringify!(_cookie)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr)._close) as usize - ptr as usize }, 56usize, concat!("Offset of field: ", stringify!(__sFILE), "::", stringify!(_close)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr)._read) as usize - ptr as usize }, 64usize, concat!("Offset of field: ", stringify!(__sFILE), "::", stringify!(_read)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr)._seek) as usize - ptr as usize }, 72usize, concat!("Offset of field: ", stringify!(__sFILE), "::", stringify!(_seek)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr)._write) as usize - ptr as usize }, 80usize, concat!("Offset of field: ", stringify!(__sFILE), "::", stringify!(_write)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr)._ub) as usize - ptr as usize }, 88usize, concat!("Offset of field: ", stringify!(__sFILE), "::", stringify!(_ub)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr)._up) as usize - ptr as usize }, 104usize, concat!("Offset of field: ", stringify!(__sFILE), "::", stringify!(_up)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr)._ur) as usize - ptr as usize }, 112usize, concat!("Offset of field: ", stringify!(__sFILE), "::", stringify!(_ur)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr)._ubuf) as usize - ptr as usize }, 116usize, concat!("Offset of field: ", stringify!(__sFILE), "::", stringify!(_ubuf)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr)._nbuf) as usize - ptr as usize }, 119usize, concat!("Offset of field: ", stringify!(__sFILE), "::", stringify!(_nbuf)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr)._lb) as usize - ptr as usize }, 120usize, concat!("Offset of field: ", stringify!(__sFILE), "::", stringify!(_lb)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr)._blksize) as usize - ptr as usize }, 136usize, concat!("Offset of field: ", stringify!(__sFILE), "::", stringify!(_blksize)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr)._offset) as usize - ptr as usize }, 144usize, concat!("Offset of field: ", stringify!(__sFILE), "::", stringify!(_offset)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr)._fl_mutex) as usize - ptr as usize }, 152usize, concat!("Offset of field: ", stringify!(__sFILE), "::", stringify!(_fl_mutex)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr)._fl_owner) as usize - ptr as usize }, 160usize, concat!("Offset of field: ", stringify!(__sFILE), "::", stringify!(_fl_owner)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr)._fl_count) as usize - ptr as usize }, 168usize, concat!("Offset of field: ", stringify!(__sFILE), "::", stringify!(_fl_count)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr)._orientation) as usize - ptr as usize }, 172usize, concat!("Offset of field: ", stringify!(__sFILE), "::", stringify!(_orientation)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr)._mbstate) as usize - ptr as usize }, 176usize, concat!("Offset of field: ", stringify!(__sFILE), "::", stringify!(_mbstate)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr)._flags2) as usize - ptr as usize }, 304usize, concat!("Offset of field: ", stringify!(__sFILE), "::", stringify!(_flags2)) ); } pub type FILE = __sFILE; unsafe extern "C" { pub static mut __stdinp: *mut FILE; } unsafe extern "C" { pub static mut __stdoutp: *mut FILE; } unsafe extern "C" { pub static mut __stderrp: *mut FILE; } unsafe extern "C" { pub fn clearerr(arg1: *mut FILE); } unsafe extern "C" { pub fn fclose(arg1: *mut FILE) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn feof(arg1: *mut FILE) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn ferror(arg1: *mut FILE) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn fflush(arg1: *mut FILE) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn fgetc(arg1: *mut FILE) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn fgetpos(arg1: *mut FILE, arg2: *mut fpos_t) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn fgets( arg1: *mut ::std::os::raw::c_char, arg2: ::std::os::raw::c_int, arg3: *mut FILE, ) -> *mut ::std::os::raw::c_char; } unsafe extern "C" { pub fn fopen(arg1: *const ::std::os::raw::c_char, arg2: *const ::std::os::raw::c_char) -> *mut FILE; } unsafe extern "C" { pub fn fprintf(arg1: *mut FILE, arg2: *const ::std::os::raw::c_char, ...) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn fputc(arg1: ::std::os::raw::c_int, arg2: *mut FILE) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn fputs(arg1: *const ::std::os::raw::c_char, arg2: *mut FILE) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn fread( arg1: *mut ::std::os::raw::c_void, arg2: ::std::os::raw::c_ulong, arg3: ::std::os::raw::c_ulong, arg4: *mut FILE, ) -> ::std::os::raw::c_ulong; } unsafe extern "C" { pub fn freopen( arg1: *const ::std::os::raw::c_char, arg2: *const ::std::os::raw::c_char, arg3: *mut FILE, ) -> *mut FILE; } unsafe extern "C" { pub fn fscanf(arg1: *mut FILE, arg2: *const ::std::os::raw::c_char, ...) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn fseek(arg1: *mut FILE, arg2: ::std::os::raw::c_long, arg3: ::std::os::raw::c_int) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn fsetpos(arg1: *mut FILE, arg2: *const fpos_t) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn ftell(arg1: *mut FILE) -> ::std::os::raw::c_long; } unsafe extern "C" { pub fn fwrite( arg1: *const ::std::os::raw::c_void, arg2: ::std::os::raw::c_ulong, arg3: ::std::os::raw::c_ulong, arg4: *mut FILE, ) -> ::std::os::raw::c_ulong; } unsafe extern "C" { pub fn getc(arg1: *mut FILE) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn getchar() -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn gets_s(arg1: *mut ::std::os::raw::c_char, arg2: rsize_t) -> *mut ::std::os::raw::c_char; } unsafe extern "C" { pub fn perror(arg1: *const ::std::os::raw::c_char); } unsafe extern "C" { pub fn printf(arg1: *const ::std::os::raw::c_char, ...) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn putc(arg1: ::std::os::raw::c_int, arg2: *mut FILE) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn putchar(arg1: ::std::os::raw::c_int) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn puts(arg1: *const ::std::os::raw::c_char) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn remove(arg1: *const ::std::os::raw::c_char) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn rename(arg1: *const ::std::os::raw::c_char, arg2: *const ::std::os::raw::c_char) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn rewind(arg1: *mut FILE); } unsafe extern "C" { pub fn scanf(arg1: *const ::std::os::raw::c_char, ...) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn setbuf(arg1: *mut FILE, arg2: *mut ::std::os::raw::c_char); } unsafe extern "C" { pub fn setvbuf( arg1: *mut FILE, arg2: *mut ::std::os::raw::c_char, arg3: ::std::os::raw::c_int, arg4: usize, ) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn sprintf( arg1: *mut ::std::os::raw::c_char, arg2: *const ::std::os::raw::c_char, ... ) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn sscanf( arg1: *const ::std::os::raw::c_char, arg2: *const ::std::os::raw::c_char, ... ) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn tmpfile() -> *mut FILE; } unsafe extern "C" { pub fn tmpnam(arg1: *mut ::std::os::raw::c_char) -> *mut ::std::os::raw::c_char; } unsafe extern "C" { pub fn ungetc(arg1: ::std::os::raw::c_int, arg2: *mut FILE) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn vfprintf( arg1: *mut FILE, arg2: *const ::std::os::raw::c_char, arg3: *mut __va_list_tag, ) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn vprintf(arg1: *const ::std::os::raw::c_char, arg2: *mut __va_list_tag) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn vsprintf( arg1: *mut ::std::os::raw::c_char, arg2: *const ::std::os::raw::c_char, arg3: *mut __va_list_tag, ) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn snprintf( arg1: *mut ::std::os::raw::c_char, arg2: ::std::os::raw::c_ulong, arg3: *const ::std::os::raw::c_char, ... ) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn vsnprintf( arg1: *mut ::std::os::raw::c_char, arg2: ::std::os::raw::c_ulong, arg3: *const ::std::os::raw::c_char, arg4: *mut __va_list_tag, ) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn vfscanf( arg1: *mut FILE, arg2: *const ::std::os::raw::c_char, arg3: *mut __va_list_tag, ) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn vscanf(arg1: *const ::std::os::raw::c_char, arg2: *mut __va_list_tag) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn vsscanf( arg1: *const ::std::os::raw::c_char, arg2: *const ::std::os::raw::c_char, arg3: *mut __va_list_tag, ) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn ctermid(arg1: *mut ::std::os::raw::c_char) -> *mut ::std::os::raw::c_char; } unsafe extern "C" { pub fn fdopen(arg1: ::std::os::raw::c_int, arg2: *const ::std::os::raw::c_char) -> *mut FILE; } unsafe extern "C" { pub fn fileno(arg1: *mut FILE) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn pclose(arg1: *mut FILE) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn popen(arg1: *const ::std::os::raw::c_char, arg2: *const ::std::os::raw::c_char) -> *mut FILE; } unsafe extern "C" { pub fn ftrylockfile(arg1: *mut FILE) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn flockfile(arg1: *mut FILE); } unsafe extern "C" { pub fn funlockfile(arg1: *mut FILE); } unsafe extern "C" { pub fn getc_unlocked(arg1: *mut FILE) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn getchar_unlocked() -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn putc_unlocked(arg1: ::std::os::raw::c_int, arg2: *mut FILE) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn putchar_unlocked(arg1: ::std::os::raw::c_int) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn clearerr_unlocked(arg1: *mut FILE); } unsafe extern "C" { pub fn feof_unlocked(arg1: *mut FILE) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn ferror_unlocked(arg1: *mut FILE) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn fflush_unlocked(arg1: *mut FILE) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn fileno_unlocked(arg1: *mut FILE) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn fputc_unlocked(arg1: ::std::os::raw::c_int, arg2: *mut FILE) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn fputs_unlocked(arg1: *const ::std::os::raw::c_char, arg2: *mut FILE) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn fread_unlocked(arg1: *mut ::std::os::raw::c_void, arg2: usize, arg3: usize, arg4: *mut FILE) -> usize; } unsafe extern "C" { pub fn fwrite_unlocked(arg1: *const ::std::os::raw::c_void, arg2: usize, arg3: usize, arg4: *mut FILE) -> usize; } unsafe extern "C" { pub fn fseeko(arg1: *mut FILE, arg2: __off_t, arg3: ::std::os::raw::c_int) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn ftello(arg1: *mut FILE) -> __off_t; } unsafe extern "C" { pub fn getw(arg1: *mut FILE) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn putw(arg1: ::std::os::raw::c_int, arg2: *mut FILE) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn tempnam( arg1: *const ::std::os::raw::c_char, arg2: *const ::std::os::raw::c_char, ) -> *mut ::std::os::raw::c_char; } unsafe extern "C" { pub fn fmemopen(arg1: *mut ::std::os::raw::c_void, arg2: usize, arg3: *const ::std::os::raw::c_char) -> *mut FILE; } unsafe extern "C" { pub fn getdelim( arg1: *mut *mut ::std::os::raw::c_char, arg2: *mut usize, arg3: ::std::os::raw::c_int, arg4: *mut FILE, ) -> isize; } unsafe extern "C" { pub fn open_memstream(arg1: *mut *mut ::std::os::raw::c_char, arg2: *mut usize) -> *mut FILE; } unsafe extern "C" { pub fn renameat( arg1: ::std::os::raw::c_int, arg2: *const ::std::os::raw::c_char, arg3: ::std::os::raw::c_int, arg4: *const ::std::os::raw::c_char, ) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn vdprintf( arg1: ::std::os::raw::c_int, arg2: *const ::std::os::raw::c_char, arg3: *mut __va_list_tag, ) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn getline(arg1: *mut *mut ::std::os::raw::c_char, arg2: *mut usize, arg3: *mut FILE) -> isize; } unsafe extern "C" { pub fn dprintf(arg1: ::std::os::raw::c_int, arg2: *const ::std::os::raw::c_char, ...) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn asprintf( arg1: *mut *mut ::std::os::raw::c_char, arg2: *const ::std::os::raw::c_char, ... ) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn ctermid_r(arg1: *mut ::std::os::raw::c_char) -> *mut ::std::os::raw::c_char; } unsafe extern "C" { pub fn fcloseall(); } unsafe extern "C" { pub fn fdclose(arg1: *mut FILE, arg2: *mut ::std::os::raw::c_int) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn fgetln(arg1: *mut FILE, arg2: *mut usize) -> *mut ::std::os::raw::c_char; } unsafe extern "C" { pub fn fmtcheck( arg1: *const ::std::os::raw::c_char, arg2: *const ::std::os::raw::c_char, ) -> *const ::std::os::raw::c_char; } unsafe extern "C" { pub fn fpurge(arg1: *mut FILE) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn setbuffer(arg1: *mut FILE, arg2: *mut ::std::os::raw::c_char, arg3: ::std::os::raw::c_int); } unsafe extern "C" { pub fn setlinebuf(arg1: *mut FILE) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn vasprintf( arg1: *mut *mut ::std::os::raw::c_char, arg2: *const ::std::os::raw::c_char, arg3: *mut __va_list_tag, ) -> ::std::os::raw::c_int; } unsafe extern "C" { pub static sys_nerr: ::std::os::raw::c_int; } unsafe extern "C" { pub static sys_errlist: [*const ::std::os::raw::c_char; 0usize]; } unsafe extern "C" { pub fn funopen( arg1: *const ::std::os::raw::c_void, arg2: ::std::option::Option< unsafe extern "C" fn( arg1: *mut ::std::os::raw::c_void, arg2: *mut ::std::os::raw::c_char, arg3: ::std::os::raw::c_int, ) -> ::std::os::raw::c_int, >, arg3: ::std::option::Option< unsafe extern "C" fn( arg1: *mut ::std::os::raw::c_void, arg2: *const ::std::os::raw::c_char, arg3: ::std::os::raw::c_int, ) -> ::std::os::raw::c_int, >, arg4: ::std::option::Option< unsafe extern "C" fn( arg1: *mut ::std::os::raw::c_void, arg2: fpos_t, arg3: ::std::os::raw::c_int, ) -> fpos_t, >, arg5: ::std::option::Option ::std::os::raw::c_int>, ) -> *mut FILE; } pub type cookie_read_function_t = ::std::option::Option< unsafe extern "C" fn( arg1: *mut ::std::os::raw::c_void, arg2: *mut ::std::os::raw::c_char, arg3: usize, ) -> __ssize_t, >; pub type cookie_write_function_t = ::std::option::Option< unsafe extern "C" fn( arg1: *mut ::std::os::raw::c_void, arg2: *const ::std::os::raw::c_char, arg3: usize, ) -> __ssize_t, >; pub type cookie_seek_function_t = ::std::option::Option< unsafe extern "C" fn( arg1: *mut ::std::os::raw::c_void, arg2: *mut off64_t, arg3: ::std::os::raw::c_int, ) -> ::std::os::raw::c_int, >; pub type cookie_close_function_t = ::std::option::Option ::std::os::raw::c_int>; #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct cookie_io_functions_t { pub read: cookie_read_function_t, pub write: cookie_write_function_t, pub seek: cookie_seek_function_t, pub close: cookie_close_function_t, } #[test] fn bindgen_test_layout_cookie_io_functions_t() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 32usize, concat!("Size of: ", stringify!(cookie_io_functions_t)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(cookie_io_functions_t)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).read) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(cookie_io_functions_t), "::", stringify!(read) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).write) as usize - ptr as usize }, 8usize, concat!( "Offset of field: ", stringify!(cookie_io_functions_t), "::", stringify!(write) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).seek) as usize - ptr as usize }, 16usize, concat!( "Offset of field: ", stringify!(cookie_io_functions_t), "::", stringify!(seek) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).close) as usize - ptr as usize }, 24usize, concat!( "Offset of field: ", stringify!(cookie_io_functions_t), "::", stringify!(close) ) ); } unsafe extern "C" { pub fn fopencookie( arg1: *mut ::std::os::raw::c_void, arg2: *const ::std::os::raw::c_char, arg3: cookie_io_functions_t, ) -> *mut FILE; } unsafe extern "C" { pub fn __srget(arg1: *mut FILE) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn __swbuf(arg1: ::std::os::raw::c_int, arg2: *mut FILE) -> ::std::os::raw::c_int; } unsafe extern "C" { pub static mut __isthreaded: ::std::os::raw::c_int; } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct FreeBSD_nvlist { _unused: [u8; 0], } pub type FreeBSD_nvlist_t = FreeBSD_nvlist; unsafe extern "C" { pub fn FreeBSD_nvlist_create(flags: ::std::os::raw::c_int) -> *mut FreeBSD_nvlist_t; } unsafe extern "C" { pub fn FreeBSD_nvlist_destroy(nvl: *mut FreeBSD_nvlist_t); } unsafe extern "C" { pub fn FreeBSD_nvlist_error(nvl: *const FreeBSD_nvlist_t) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn FreeBSD_nvlist_empty(nvl: *const FreeBSD_nvlist_t) -> bool; } unsafe extern "C" { pub fn FreeBSD_nvlist_flags(nvl: *const FreeBSD_nvlist_t) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn FreeBSD_nvlist_set_error(nvl: *mut FreeBSD_nvlist_t, error: ::std::os::raw::c_int); } unsafe extern "C" { pub fn FreeBSD_nvlist_clone(nvl: *const FreeBSD_nvlist_t) -> *mut FreeBSD_nvlist_t; } unsafe extern "C" { pub fn FreeBSD_nvlist_dump(nvl: *const FreeBSD_nvlist_t, fd: ::std::os::raw::c_int); } unsafe extern "C" { pub fn FreeBSD_nvlist_fdump(nvl: *const FreeBSD_nvlist_t, fp: *mut FILE); } unsafe extern "C" { pub fn FreeBSD_nvlist_size(nvl: *const FreeBSD_nvlist_t) -> usize; } unsafe extern "C" { pub fn FreeBSD_nvlist_pack(nvl: *const FreeBSD_nvlist_t, sizep: *mut usize) -> *mut ::std::os::raw::c_void; } unsafe extern "C" { pub fn FreeBSD_nvlist_unpack( buf: *const ::std::os::raw::c_void, size: usize, flags: ::std::os::raw::c_int, ) -> *mut FreeBSD_nvlist_t; } unsafe extern "C" { pub fn FreeBSD_nvlist_send(sock: ::std::os::raw::c_int, nvl: *const FreeBSD_nvlist_t) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn FreeBSD_nvlist_recv(sock: ::std::os::raw::c_int, flags: ::std::os::raw::c_int) -> *mut FreeBSD_nvlist_t; } unsafe extern "C" { pub fn FreeBSD_nvlist_xfer( sock: ::std::os::raw::c_int, nvl: *mut FreeBSD_nvlist_t, flags: ::std::os::raw::c_int, ) -> *mut FreeBSD_nvlist_t; } unsafe extern "C" { pub fn FreeBSD_nvlist_next( nvl: *const FreeBSD_nvlist_t, typep: *mut ::std::os::raw::c_int, cookiep: *mut *mut ::std::os::raw::c_void, ) -> *const ::std::os::raw::c_char; } unsafe extern "C" { pub fn FreeBSD_nvlist_get_parent( nvl: *const FreeBSD_nvlist_t, cookiep: *mut *mut ::std::os::raw::c_void, ) -> *const FreeBSD_nvlist_t; } unsafe extern "C" { pub fn FreeBSD_nvlist_get_array_next(nvl: *const FreeBSD_nvlist_t) -> *const FreeBSD_nvlist_t; } unsafe extern "C" { pub fn FreeBSD_nvlist_in_array(nvl: *const FreeBSD_nvlist_t) -> bool; } unsafe extern "C" { pub fn FreeBSD_nvlist_get_pararr( nvl: *const FreeBSD_nvlist_t, cookiep: *mut *mut ::std::os::raw::c_void, ) -> *const FreeBSD_nvlist_t; } unsafe extern "C" { pub fn FreeBSD_nvlist_exists(nvl: *const FreeBSD_nvlist_t, name: *const ::std::os::raw::c_char) -> bool; } unsafe extern "C" { pub fn FreeBSD_nvlist_exists_type( nvl: *const FreeBSD_nvlist_t, name: *const ::std::os::raw::c_char, type_: ::std::os::raw::c_int, ) -> bool; } unsafe extern "C" { pub fn FreeBSD_nvlist_exists_null(nvl: *const FreeBSD_nvlist_t, name: *const ::std::os::raw::c_char) -> bool; } unsafe extern "C" { pub fn FreeBSD_nvlist_exists_bool(nvl: *const FreeBSD_nvlist_t, name: *const ::std::os::raw::c_char) -> bool; } unsafe extern "C" { pub fn FreeBSD_nvlist_exists_number(nvl: *const FreeBSD_nvlist_t, name: *const ::std::os::raw::c_char) -> bool; } unsafe extern "C" { pub fn FreeBSD_nvlist_exists_string(nvl: *const FreeBSD_nvlist_t, name: *const ::std::os::raw::c_char) -> bool; } unsafe extern "C" { pub fn FreeBSD_nvlist_exists_nvlist(nvl: *const FreeBSD_nvlist_t, name: *const ::std::os::raw::c_char) -> bool; } unsafe extern "C" { pub fn FreeBSD_nvlist_exists_binary(nvl: *const FreeBSD_nvlist_t, name: *const ::std::os::raw::c_char) -> bool; } unsafe extern "C" { pub fn FreeBSD_nvlist_exists_bool_array(nvl: *const FreeBSD_nvlist_t, name: *const ::std::os::raw::c_char) -> bool; } unsafe extern "C" { pub fn FreeBSD_nvlist_exists_number_array( nvl: *const FreeBSD_nvlist_t, name: *const ::std::os::raw::c_char, ) -> bool; } unsafe extern "C" { pub fn FreeBSD_nvlist_exists_string_array( nvl: *const FreeBSD_nvlist_t, name: *const ::std::os::raw::c_char, ) -> bool; } unsafe extern "C" { pub fn FreeBSD_nvlist_exists_nvlist_array( nvl: *const FreeBSD_nvlist_t, name: *const ::std::os::raw::c_char, ) -> bool; } unsafe extern "C" { pub fn FreeBSD_nvlist_exists_descriptor(nvl: *const FreeBSD_nvlist_t, name: *const ::std::os::raw::c_char) -> bool; } unsafe extern "C" { pub fn FreeBSD_nvlist_exists_descriptor_array( nvl: *const FreeBSD_nvlist_t, name: *const ::std::os::raw::c_char, ) -> bool; } unsafe extern "C" { pub fn FreeBSD_nvlist_add_null(nvl: *mut FreeBSD_nvlist_t, name: *const ::std::os::raw::c_char); } unsafe extern "C" { pub fn FreeBSD_nvlist_add_bool(nvl: *mut FreeBSD_nvlist_t, name: *const ::std::os::raw::c_char, value: bool); } unsafe extern "C" { pub fn FreeBSD_nvlist_add_number(nvl: *mut FreeBSD_nvlist_t, name: *const ::std::os::raw::c_char, value: u64); } unsafe extern "C" { pub fn FreeBSD_nvlist_add_string( nvl: *mut FreeBSD_nvlist_t, name: *const ::std::os::raw::c_char, value: *const ::std::os::raw::c_char, ); } unsafe extern "C" { pub fn FreeBSD_nvlist_add_stringf( nvl: *mut FreeBSD_nvlist_t, name: *const ::std::os::raw::c_char, valuefmt: *const ::std::os::raw::c_char, ... ); } unsafe extern "C" { pub fn FreeBSD_nvlist_add_stringv( nvl: *mut FreeBSD_nvlist_t, name: *const ::std::os::raw::c_char, valuefmt: *const ::std::os::raw::c_char, valueap: *mut __va_list_tag, ); } unsafe extern "C" { pub fn FreeBSD_nvlist_add_nvlist( nvl: *mut FreeBSD_nvlist_t, name: *const ::std::os::raw::c_char, value: *const FreeBSD_nvlist_t, ); } unsafe extern "C" { pub fn FreeBSD_nvlist_add_binary( nvl: *mut FreeBSD_nvlist_t, name: *const ::std::os::raw::c_char, value: *const ::std::os::raw::c_void, size: usize, ); } unsafe extern "C" { pub fn FreeBSD_nvlist_add_bool_array( nvl: *mut FreeBSD_nvlist_t, name: *const ::std::os::raw::c_char, value: *const bool, nitems: usize, ); } unsafe extern "C" { pub fn FreeBSD_nvlist_add_number_array( nvl: *mut FreeBSD_nvlist_t, name: *const ::std::os::raw::c_char, value: *const u64, nitems: usize, ); } unsafe extern "C" { pub fn FreeBSD_nvlist_add_string_array( nvl: *mut FreeBSD_nvlist_t, name: *const ::std::os::raw::c_char, value: *const *const ::std::os::raw::c_char, nitems: usize, ); } unsafe extern "C" { pub fn FreeBSD_nvlist_add_nvlist_array( nvl: *mut FreeBSD_nvlist_t, name: *const ::std::os::raw::c_char, value: *const *const FreeBSD_nvlist_t, nitems: usize, ); } unsafe extern "C" { pub fn FreeBSD_nvlist_add_descriptor( nvl: *mut FreeBSD_nvlist_t, name: *const ::std::os::raw::c_char, value: ::std::os::raw::c_int, ); } unsafe extern "C" { pub fn FreeBSD_nvlist_add_descriptor_array( nvl: *mut FreeBSD_nvlist_t, name: *const ::std::os::raw::c_char, value: *const ::std::os::raw::c_int, nitems: usize, ); } unsafe extern "C" { pub fn FreeBSD_nvlist_append_bool_array( nvl: *mut FreeBSD_nvlist_t, name: *const ::std::os::raw::c_char, value: bool, ); } unsafe extern "C" { pub fn FreeBSD_nvlist_append_number_array( nvl: *mut FreeBSD_nvlist_t, name: *const ::std::os::raw::c_char, value: u64, ); } unsafe extern "C" { pub fn FreeBSD_nvlist_append_string_array( nvl: *mut FreeBSD_nvlist_t, name: *const ::std::os::raw::c_char, value: *const ::std::os::raw::c_char, ); } unsafe extern "C" { pub fn FreeBSD_nvlist_append_nvlist_array( nvl: *mut FreeBSD_nvlist_t, name: *const ::std::os::raw::c_char, value: *const FreeBSD_nvlist_t, ); } unsafe extern "C" { pub fn FreeBSD_nvlist_append_descriptor_array( nvl: *mut FreeBSD_nvlist_t, name: *const ::std::os::raw::c_char, value: ::std::os::raw::c_int, ); } unsafe extern "C" { pub fn FreeBSD_nvlist_move_string( nvl: *mut FreeBSD_nvlist_t, name: *const ::std::os::raw::c_char, value: *mut ::std::os::raw::c_char, ); } unsafe extern "C" { pub fn FreeBSD_nvlist_move_nvlist( nvl: *mut FreeBSD_nvlist_t, name: *const ::std::os::raw::c_char, value: *mut FreeBSD_nvlist_t, ); } unsafe extern "C" { pub fn FreeBSD_nvlist_move_binary( nvl: *mut FreeBSD_nvlist_t, name: *const ::std::os::raw::c_char, value: *mut ::std::os::raw::c_void, size: usize, ); } unsafe extern "C" { pub fn FreeBSD_nvlist_move_bool_array( nvl: *mut FreeBSD_nvlist_t, name: *const ::std::os::raw::c_char, value: *mut bool, nitems: usize, ); } unsafe extern "C" { pub fn FreeBSD_nvlist_move_string_array( nvl: *mut FreeBSD_nvlist_t, name: *const ::std::os::raw::c_char, value: *mut *mut ::std::os::raw::c_char, nitems: usize, ); } unsafe extern "C" { pub fn FreeBSD_nvlist_move_nvlist_array( nvl: *mut FreeBSD_nvlist_t, name: *const ::std::os::raw::c_char, value: *mut *mut FreeBSD_nvlist_t, nitems: usize, ); } unsafe extern "C" { pub fn FreeBSD_nvlist_move_number_array( nvl: *mut FreeBSD_nvlist_t, name: *const ::std::os::raw::c_char, value: *mut u64, nitems: usize, ); } unsafe extern "C" { pub fn FreeBSD_nvlist_move_descriptor( nvl: *mut FreeBSD_nvlist_t, name: *const ::std::os::raw::c_char, value: ::std::os::raw::c_int, ); } unsafe extern "C" { pub fn FreeBSD_nvlist_move_descriptor_array( nvl: *mut FreeBSD_nvlist_t, name: *const ::std::os::raw::c_char, value: *mut ::std::os::raw::c_int, nitems: usize, ); } unsafe extern "C" { pub fn FreeBSD_nvlist_get_bool(nvl: *const FreeBSD_nvlist_t, name: *const ::std::os::raw::c_char) -> bool; } unsafe extern "C" { pub fn FreeBSD_nvlist_get_number(nvl: *const FreeBSD_nvlist_t, name: *const ::std::os::raw::c_char) -> u64; } unsafe extern "C" { pub fn FreeBSD_nvlist_get_string( nvl: *const FreeBSD_nvlist_t, name: *const ::std::os::raw::c_char, ) -> *const ::std::os::raw::c_char; } unsafe extern "C" { pub fn FreeBSD_nvlist_get_nvlist( nvl: *const FreeBSD_nvlist_t, name: *const ::std::os::raw::c_char, ) -> *const FreeBSD_nvlist_t; } unsafe extern "C" { pub fn FreeBSD_nvlist_get_binary( nvl: *const FreeBSD_nvlist_t, name: *const ::std::os::raw::c_char, sizep: *mut usize, ) -> *const ::std::os::raw::c_void; } unsafe extern "C" { pub fn FreeBSD_nvlist_get_bool_array( nvl: *const FreeBSD_nvlist_t, name: *const ::std::os::raw::c_char, nitemsp: *mut usize, ) -> *const bool; } unsafe extern "C" { pub fn FreeBSD_nvlist_get_number_array( nvl: *const FreeBSD_nvlist_t, name: *const ::std::os::raw::c_char, nitemsp: *mut usize, ) -> *const u64; } unsafe extern "C" { pub fn FreeBSD_nvlist_get_string_array( nvl: *const FreeBSD_nvlist_t, name: *const ::std::os::raw::c_char, nitemsp: *mut usize, ) -> *const *const ::std::os::raw::c_char; } unsafe extern "C" { pub fn FreeBSD_nvlist_get_nvlist_array( nvl: *const FreeBSD_nvlist_t, name: *const ::std::os::raw::c_char, nitemsp: *mut usize, ) -> *const *const FreeBSD_nvlist_t; } unsafe extern "C" { pub fn FreeBSD_nvlist_get_descriptor( nvl: *const FreeBSD_nvlist_t, name: *const ::std::os::raw::c_char, ) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn FreeBSD_nvlist_get_descriptor_array( nvl: *const FreeBSD_nvlist_t, name: *const ::std::os::raw::c_char, nitemsp: *mut usize, ) -> *const ::std::os::raw::c_int; } unsafe extern "C" { pub fn FreeBSD_nvlist_take_bool(nvl: *mut FreeBSD_nvlist_t, name: *const ::std::os::raw::c_char) -> bool; } unsafe extern "C" { pub fn FreeBSD_nvlist_take_number(nvl: *mut FreeBSD_nvlist_t, name: *const ::std::os::raw::c_char) -> u64; } unsafe extern "C" { pub fn FreeBSD_nvlist_take_string( nvl: *mut FreeBSD_nvlist_t, name: *const ::std::os::raw::c_char, ) -> *mut ::std::os::raw::c_char; } unsafe extern "C" { pub fn FreeBSD_nvlist_take_nvlist( nvl: *mut FreeBSD_nvlist_t, name: *const ::std::os::raw::c_char, ) -> *mut FreeBSD_nvlist_t; } unsafe extern "C" { pub fn FreeBSD_nvlist_take_binary( nvl: *mut FreeBSD_nvlist_t, name: *const ::std::os::raw::c_char, sizep: *mut usize, ) -> *mut ::std::os::raw::c_void; } unsafe extern "C" { pub fn FreeBSD_nvlist_take_bool_array( nvl: *mut FreeBSD_nvlist_t, name: *const ::std::os::raw::c_char, nitemsp: *mut usize, ) -> *mut bool; } unsafe extern "C" { pub fn FreeBSD_nvlist_take_number_array( nvl: *mut FreeBSD_nvlist_t, name: *const ::std::os::raw::c_char, nitemsp: *mut usize, ) -> *mut u64; } unsafe extern "C" { pub fn FreeBSD_nvlist_take_string_array( nvl: *mut FreeBSD_nvlist_t, name: *const ::std::os::raw::c_char, nitemsp: *mut usize, ) -> *mut *mut ::std::os::raw::c_char; } unsafe extern "C" { pub fn FreeBSD_nvlist_take_nvlist_array( nvl: *mut FreeBSD_nvlist_t, name: *const ::std::os::raw::c_char, nitemsp: *mut usize, ) -> *mut *mut FreeBSD_nvlist_t; } unsafe extern "C" { pub fn FreeBSD_nvlist_take_descriptor( nvl: *mut FreeBSD_nvlist_t, name: *const ::std::os::raw::c_char, ) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn FreeBSD_nvlist_take_descriptor_array( nvl: *mut FreeBSD_nvlist_t, name: *const ::std::os::raw::c_char, nitemsp: *mut usize, ) -> *mut ::std::os::raw::c_int; } unsafe extern "C" { pub fn FreeBSD_nvlist_free(nvl: *mut FreeBSD_nvlist_t, name: *const ::std::os::raw::c_char); } unsafe extern "C" { pub fn FreeBSD_nvlist_free_type( nvl: *mut FreeBSD_nvlist_t, name: *const ::std::os::raw::c_char, type_: ::std::os::raw::c_int, ); } unsafe extern "C" { pub fn FreeBSD_nvlist_free_null(nvl: *mut FreeBSD_nvlist_t, name: *const ::std::os::raw::c_char); } unsafe extern "C" { pub fn FreeBSD_nvlist_free_bool(nvl: *mut FreeBSD_nvlist_t, name: *const ::std::os::raw::c_char); } unsafe extern "C" { pub fn FreeBSD_nvlist_free_number(nvl: *mut FreeBSD_nvlist_t, name: *const ::std::os::raw::c_char); } unsafe extern "C" { pub fn FreeBSD_nvlist_free_string(nvl: *mut FreeBSD_nvlist_t, name: *const ::std::os::raw::c_char); } unsafe extern "C" { pub fn FreeBSD_nvlist_free_nvlist(nvl: *mut FreeBSD_nvlist_t, name: *const ::std::os::raw::c_char); } unsafe extern "C" { pub fn FreeBSD_nvlist_free_binary(nvl: *mut FreeBSD_nvlist_t, name: *const ::std::os::raw::c_char); } unsafe extern "C" { pub fn FreeBSD_nvlist_free_bool_array(nvl: *mut FreeBSD_nvlist_t, name: *const ::std::os::raw::c_char); } unsafe extern "C" { pub fn FreeBSD_nvlist_free_number_array(nvl: *mut FreeBSD_nvlist_t, name: *const ::std::os::raw::c_char); } unsafe extern "C" { pub fn FreeBSD_nvlist_free_string_array(nvl: *mut FreeBSD_nvlist_t, name: *const ::std::os::raw::c_char); } unsafe extern "C" { pub fn FreeBSD_nvlist_free_nvlist_array(nvl: *mut FreeBSD_nvlist_t, name: *const ::std::os::raw::c_char); } unsafe extern "C" { pub fn FreeBSD_nvlist_free_binary_array(nvl: *mut FreeBSD_nvlist_t, name: *const ::std::os::raw::c_char); } unsafe extern "C" { pub fn FreeBSD_nvlist_free_descriptor(nvl: *mut FreeBSD_nvlist_t, name: *const ::std::os::raw::c_char); } unsafe extern "C" { pub fn FreeBSD_nvlist_free_descriptor_array(nvl: *mut FreeBSD_nvlist_t, name: *const ::std::os::raw::c_char); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct __hack { _unused: [u8; 0], } unsafe extern "C" { pub fn sysctl( arg1: *const ::std::os::raw::c_int, arg2: ::std::os::raw::c_uint, arg3: *mut ::std::os::raw::c_void, arg4: *mut usize, arg5: *const ::std::os::raw::c_void, arg6: usize, ) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn sysctlbyname( arg1: *const ::std::os::raw::c_char, arg2: *mut ::std::os::raw::c_void, arg3: *mut usize, arg4: *const ::std::os::raw::c_void, arg5: usize, ) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn sysctlnametomib( arg1: *const ::std::os::raw::c_char, arg2: *mut ::std::os::raw::c_int, arg3: *mut usize, ) -> ::std::os::raw::c_int; } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct lock_list_entry { _unused: [u8; 0], } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct thread { _unused: [u8; 0], } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct lock_class { pub lc_name: *const ::std::os::raw::c_char, pub lc_flags: u_int, pub lc_assert: ::std::option::Option, pub lc_ddb_show: ::std::option::Option, pub lc_lock: ::std::option::Option, pub lc_owner: ::std::option::Option< unsafe extern "C" fn(lock: *const lock_object, owner: *mut *mut thread) -> ::std::os::raw::c_int, >, pub lc_unlock: ::std::option::Option usize>, } #[test] fn bindgen_test_layout_lock_class() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 56usize, concat!("Size of: ", stringify!(lock_class)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(lock_class)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).lc_name) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(lock_class), "::", stringify!(lc_name)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).lc_flags) as usize - ptr as usize }, 8usize, concat!("Offset of field: ", stringify!(lock_class), "::", stringify!(lc_flags)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).lc_assert) as usize - ptr as usize }, 16usize, concat!("Offset of field: ", stringify!(lock_class), "::", stringify!(lc_assert)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).lc_ddb_show) as usize - ptr as usize }, 24usize, concat!( "Offset of field: ", stringify!(lock_class), "::", stringify!(lc_ddb_show) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).lc_lock) as usize - ptr as usize }, 32usize, concat!("Offset of field: ", stringify!(lock_class), "::", stringify!(lc_lock)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).lc_owner) as usize - ptr as usize }, 40usize, concat!("Offset of field: ", stringify!(lock_class), "::", stringify!(lc_owner)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).lc_unlock) as usize - ptr as usize }, 48usize, concat!("Offset of field: ", stringify!(lock_class), "::", stringify!(lc_unlock)) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct sx { pub lock_object: lock_object, pub sx_lock: usize, } #[test] fn bindgen_test_layout_sx() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 32usize, concat!("Size of: ", stringify!(sx)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(sx)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).lock_object) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(sx), "::", stringify!(lock_object)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).sx_lock) as usize - ptr as usize }, 24usize, concat!("Offset of field: ", stringify!(sx), "::", stringify!(sx_lock)) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct rmpriolist { pub lh_first: *mut rm_priotracker, } #[test] fn bindgen_test_layout_rmpriolist() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 8usize, concat!("Size of: ", stringify!(rmpriolist)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(rmpriolist)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).lh_first) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(rmpriolist), "::", stringify!(lh_first)) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct rm_queue { pub rmq_next: *mut rm_queue, pub rmq_prev: *mut rm_queue, } #[test] fn bindgen_test_layout_rm_queue() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 16usize, concat!("Size of: ", stringify!(rm_queue)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(rm_queue)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rmq_next) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(rm_queue), "::", stringify!(rmq_next)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rmq_prev) as usize - ptr as usize }, 8usize, concat!("Offset of field: ", stringify!(rm_queue), "::", stringify!(rmq_prev)) ); } #[repr(C)] #[derive(Copy, Clone)] pub struct rmlock { pub lock_object: lock_object, pub rm_writecpus: cpuset_t, pub rm_activeReaders: rmlock__bindgen_ty_1, pub _rm_lock: rmlock__bindgen_ty_2, } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct rmlock__bindgen_ty_1 { pub lh_first: *mut rm_priotracker, } #[test] fn bindgen_test_layout_rmlock__bindgen_ty_1() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 8usize, concat!("Size of: ", stringify!(rmlock__bindgen_ty_1)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(rmlock__bindgen_ty_1)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).lh_first) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(rmlock__bindgen_ty_1), "::", stringify!(lh_first) ) ); } #[repr(C)] #[derive(Copy, Clone)] pub union rmlock__bindgen_ty_2 { pub _rm_wlock_object: lock_object, pub _rm_lock_mtx: mtx, pub _rm_lock_sx: sx, } #[test] fn bindgen_test_layout_rmlock__bindgen_ty_2() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 32usize, concat!("Size of: ", stringify!(rmlock__bindgen_ty_2)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(rmlock__bindgen_ty_2)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr)._rm_wlock_object) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(rmlock__bindgen_ty_2), "::", stringify!(_rm_wlock_object) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr)._rm_lock_mtx) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(rmlock__bindgen_ty_2), "::", stringify!(_rm_lock_mtx) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr)._rm_lock_sx) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(rmlock__bindgen_ty_2), "::", stringify!(_rm_lock_sx) ) ); } #[test] fn bindgen_test_layout_rmlock() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 192usize, concat!("Size of: ", stringify!(rmlock)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(rmlock)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).lock_object) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(rmlock), "::", stringify!(lock_object)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rm_writecpus) as usize - ptr as usize }, 24usize, concat!("Offset of field: ", stringify!(rmlock), "::", stringify!(rm_writecpus)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rm_activeReaders) as usize - ptr as usize }, 152usize, concat!( "Offset of field: ", stringify!(rmlock), "::", stringify!(rm_activeReaders) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr)._rm_lock) as usize - ptr as usize }, 160usize, concat!("Offset of field: ", stringify!(rmlock), "::", stringify!(_rm_lock)) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct rm_priotracker { pub rmp_cpuQueue: rm_queue, pub rmp_rmlock: *mut rmlock, pub rmp_thread: *mut thread, pub rmp_flags: ::std::os::raw::c_int, pub rmp_qentry: rm_priotracker__bindgen_ty_1, } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct rm_priotracker__bindgen_ty_1 { pub le_next: *mut rm_priotracker, pub le_prev: *mut *mut rm_priotracker, } #[test] fn bindgen_test_layout_rm_priotracker__bindgen_ty_1() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 16usize, concat!("Size of: ", stringify!(rm_priotracker__bindgen_ty_1)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(rm_priotracker__bindgen_ty_1)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).le_next) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(rm_priotracker__bindgen_ty_1), "::", stringify!(le_next) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).le_prev) as usize - ptr as usize }, 8usize, concat!( "Offset of field: ", stringify!(rm_priotracker__bindgen_ty_1), "::", stringify!(le_prev) ) ); } #[test] fn bindgen_test_layout_rm_priotracker() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 56usize, concat!("Size of: ", stringify!(rm_priotracker)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(rm_priotracker)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rmp_cpuQueue) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(rm_priotracker), "::", stringify!(rmp_cpuQueue) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rmp_rmlock) as usize - ptr as usize }, 16usize, concat!( "Offset of field: ", stringify!(rm_priotracker), "::", stringify!(rmp_rmlock) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rmp_thread) as usize - ptr as usize }, 24usize, concat!( "Offset of field: ", stringify!(rm_priotracker), "::", stringify!(rmp_thread) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rmp_flags) as usize - ptr as usize }, 32usize, concat!( "Offset of field: ", stringify!(rm_priotracker), "::", stringify!(rmp_flags) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rmp_qentry) as usize - ptr as usize }, 40usize, concat!( "Offset of field: ", stringify!(rm_priotracker), "::", stringify!(rmp_qentry) ) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct rmslock_pcpu { _unused: [u8; 0], } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct rmslock { pub mtx: mtx, pub owner: *mut thread, pub pcpu: *mut rmslock_pcpu, pub writers: ::std::os::raw::c_int, pub readers: ::std::os::raw::c_int, pub debug_readers: ::std::os::raw::c_int, } #[test] fn bindgen_test_layout_rmslock() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 64usize, concat!("Size of: ", stringify!(rmslock)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(rmslock)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).mtx) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(rmslock), "::", stringify!(mtx)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).owner) as usize - ptr as usize }, 32usize, concat!("Offset of field: ", stringify!(rmslock), "::", stringify!(owner)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pcpu) as usize - ptr as usize }, 40usize, concat!("Offset of field: ", stringify!(rmslock), "::", stringify!(pcpu)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).writers) as usize - ptr as usize }, 48usize, concat!("Offset of field: ", stringify!(rmslock), "::", stringify!(writers)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).readers) as usize - ptr as usize }, 52usize, concat!("Offset of field: ", stringify!(rmslock), "::", stringify!(readers)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).debug_readers) as usize - ptr as usize }, 56usize, concat!( "Offset of field: ", stringify!(rmslock), "::", stringify!(debug_readers) ) ); } pub type seqc_t = u32; pub type smr_seq_t = u32; pub type smr_delta_t = i32; #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct smr { _unused: [u8; 0], } pub type smr_t = *mut smr; #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct uma_zone { _unused: [u8; 0], } pub type uma_zone_t = *mut uma_zone; pub type uma_ctor = ::std::option::Option< unsafe extern "C" fn( mem: *mut ::std::os::raw::c_void, size: ::std::os::raw::c_int, arg: *mut ::std::os::raw::c_void, flags: ::std::os::raw::c_int, ) -> ::std::os::raw::c_int, >; pub type uma_dtor = ::std::option::Option< unsafe extern "C" fn( mem: *mut ::std::os::raw::c_void, size: ::std::os::raw::c_int, arg: *mut ::std::os::raw::c_void, ), >; pub type uma_init = ::std::option::Option< unsafe extern "C" fn( mem: *mut ::std::os::raw::c_void, size: ::std::os::raw::c_int, flags: ::std::os::raw::c_int, ) -> ::std::os::raw::c_int, >; pub type uma_fini = ::std::option::Option; pub type uma_import = ::std::option::Option< unsafe extern "C" fn( arg: *mut ::std::os::raw::c_void, store: *mut *mut ::std::os::raw::c_void, count: ::std::os::raw::c_int, domain: ::std::os::raw::c_int, flags: ::std::os::raw::c_int, ) -> ::std::os::raw::c_int, >; pub type uma_release = ::std::option::Option< unsafe extern "C" fn( arg: *mut ::std::os::raw::c_void, store: *mut *mut ::std::os::raw::c_void, count: ::std::os::raw::c_int, ), >; unsafe extern "C" { pub fn uma_zcreate( name: *const ::std::os::raw::c_char, size: usize, ctor: uma_ctor, dtor: uma_dtor, uminit: uma_init, fini: uma_fini, align: ::std::os::raw::c_int, flags: u32, ) -> uma_zone_t; } unsafe extern "C" { pub fn uma_zsecond_create( name: *const ::std::os::raw::c_char, ctor: uma_ctor, dtor: uma_dtor, zinit: uma_init, zfini: uma_fini, primary: uma_zone_t, ) -> uma_zone_t; } unsafe extern "C" { pub fn uma_zcache_create( name: *const ::std::os::raw::c_char, size: ::std::os::raw::c_int, ctor: uma_ctor, dtor: uma_dtor, zinit: uma_init, zfini: uma_fini, zimport: uma_import, zrelease: uma_release, arg: *mut ::std::os::raw::c_void, flags: ::std::os::raw::c_int, ) -> uma_zone_t; } unsafe extern "C" { pub fn uma_zdestroy(zone: uma_zone_t); } unsafe extern "C" { pub fn uma_zalloc_arg( zone: uma_zone_t, arg: *mut ::std::os::raw::c_void, flags: ::std::os::raw::c_int, ) -> *mut ::std::os::raw::c_void; } unsafe extern "C" { pub fn uma_zalloc_pcpu_arg( zone: uma_zone_t, arg: *mut ::std::os::raw::c_void, flags: ::std::os::raw::c_int, ) -> *mut ::std::os::raw::c_void; } unsafe extern "C" { pub fn uma_zalloc_smr(zone: uma_zone_t, flags: ::std::os::raw::c_int) -> *mut ::std::os::raw::c_void; } unsafe extern "C" { pub fn uma_zalloc_domain( zone: uma_zone_t, arg: *mut ::std::os::raw::c_void, domain: ::std::os::raw::c_int, flags: ::std::os::raw::c_int, ) -> *mut ::std::os::raw::c_void; } unsafe extern "C" { pub fn uma_zfree_arg(zone: uma_zone_t, item: *mut ::std::os::raw::c_void, arg: *mut ::std::os::raw::c_void); } unsafe extern "C" { pub fn uma_zfree_pcpu_arg(zone: uma_zone_t, item: *mut ::std::os::raw::c_void, arg: *mut ::std::os::raw::c_void); } unsafe extern "C" { pub fn uma_zfree_smr(zone: uma_zone_t, item: *mut ::std::os::raw::c_void); } unsafe extern "C" { pub fn uma_zwait(zone: uma_zone_t); } pub type uma_alloc = ::std::option::Option< unsafe extern "C" fn( zone: uma_zone_t, size: vm_size_t, domain: ::std::os::raw::c_int, pflag: *mut u8, wait: ::std::os::raw::c_int, ) -> *mut ::std::os::raw::c_void, >; pub type uma_free = ::std::option::Option; unsafe extern "C" { pub fn uma_reclaim(req: ::std::os::raw::c_int); } unsafe extern "C" { pub fn uma_reclaim_domain(req: ::std::os::raw::c_int, domain: ::std::os::raw::c_int); } unsafe extern "C" { pub fn uma_zone_reclaim(arg1: uma_zone_t, req: ::std::os::raw::c_int); } unsafe extern "C" { pub fn uma_zone_reclaim_domain(arg1: uma_zone_t, req: ::std::os::raw::c_int, domain: ::std::os::raw::c_int); } unsafe extern "C" { pub fn uma_set_align(align: ::std::os::raw::c_int); } unsafe extern "C" { pub fn uma_zone_reserve(zone: uma_zone_t, nitems: ::std::os::raw::c_int); } unsafe extern "C" { pub fn uma_zone_reserve_kva(zone: uma_zone_t, nitems: ::std::os::raw::c_int) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn uma_zone_set_max(zone: uma_zone_t, nitems: ::std::os::raw::c_int) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn uma_zone_set_maxcache(zone: uma_zone_t, nitems: ::std::os::raw::c_int); } unsafe extern "C" { pub fn uma_zone_get_max(zone: uma_zone_t) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn uma_zone_set_warning(zone: uma_zone_t, warning: *const ::std::os::raw::c_char); } pub type uma_maxaction_t = ::std::option::Option; unsafe extern "C" { pub fn uma_zone_set_maxaction(zone: uma_zone_t, arg1: uma_maxaction_t); } unsafe extern "C" { pub fn uma_zone_get_cur(zone: uma_zone_t) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn uma_zone_set_init(zone: uma_zone_t, uminit: uma_init); } unsafe extern "C" { pub fn uma_zone_set_fini(zone: uma_zone_t, fini: uma_fini); } unsafe extern "C" { pub fn uma_zone_set_zinit(zone: uma_zone_t, zinit: uma_init); } unsafe extern "C" { pub fn uma_zone_set_zfini(zone: uma_zone_t, zfini: uma_fini); } unsafe extern "C" { pub fn uma_zone_set_allocf(zone: uma_zone_t, allocf: uma_alloc); } unsafe extern "C" { pub fn uma_zone_set_freef(zone: uma_zone_t, freef: uma_free); } unsafe extern "C" { pub fn uma_zone_set_smr(zone: uma_zone_t, smr: smr_t); } unsafe extern "C" { pub fn uma_zone_get_smr(zone: uma_zone_t) -> smr_t; } unsafe extern "C" { pub fn uma_prealloc(zone: uma_zone_t, itemcnt: ::std::os::raw::c_int); } unsafe extern "C" { pub fn uma_zone_exhausted(zone: uma_zone_t) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn uma_zone_memory(zone: uma_zone_t) -> usize; } unsafe extern "C" { pub static mut pcpu_zone_4: uma_zone_t; } unsafe extern "C" { pub static mut pcpu_zone_8: uma_zone_t; } unsafe extern "C" { pub static mut pcpu_zone_16: uma_zone_t; } unsafe extern "C" { pub static mut pcpu_zone_32: uma_zone_t; } unsafe extern "C" { pub static mut pcpu_zone_64: uma_zone_t; } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct uma_stream_header { pub ush_version: u32, pub ush_maxcpus: u32, pub ush_count: u32, pub _ush_pad: u32, } #[test] fn bindgen_test_layout_uma_stream_header() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 16usize, concat!("Size of: ", stringify!(uma_stream_header)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(uma_stream_header)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ush_version) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(uma_stream_header), "::", stringify!(ush_version) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ush_maxcpus) as usize - ptr as usize }, 4usize, concat!( "Offset of field: ", stringify!(uma_stream_header), "::", stringify!(ush_maxcpus) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ush_count) as usize - ptr as usize }, 8usize, concat!( "Offset of field: ", stringify!(uma_stream_header), "::", stringify!(ush_count) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr)._ush_pad) as usize - ptr as usize }, 12usize, concat!( "Offset of field: ", stringify!(uma_stream_header), "::", stringify!(_ush_pad) ) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct uma_type_header { pub uth_name: [::std::os::raw::c_char; 32usize], pub uth_align: u32, pub uth_size: u32, pub uth_rsize: u32, pub uth_maxpages: u32, pub uth_limit: u32, pub uth_pages: u32, pub uth_keg_free: u32, pub uth_zone_free: u32, pub uth_bucketsize: u32, pub uth_zone_flags: u32, pub uth_allocs: u64, pub uth_frees: u64, pub uth_fails: u64, pub uth_sleeps: u64, pub uth_xdomain: u64, pub _uth_reserved1: [u64; 1usize], } #[test] fn bindgen_test_layout_uma_type_header() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 120usize, concat!("Size of: ", stringify!(uma_type_header)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(uma_type_header)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).uth_name) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(uma_type_header), "::", stringify!(uth_name) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).uth_align) as usize - ptr as usize }, 32usize, concat!( "Offset of field: ", stringify!(uma_type_header), "::", stringify!(uth_align) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).uth_size) as usize - ptr as usize }, 36usize, concat!( "Offset of field: ", stringify!(uma_type_header), "::", stringify!(uth_size) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).uth_rsize) as usize - ptr as usize }, 40usize, concat!( "Offset of field: ", stringify!(uma_type_header), "::", stringify!(uth_rsize) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).uth_maxpages) as usize - ptr as usize }, 44usize, concat!( "Offset of field: ", stringify!(uma_type_header), "::", stringify!(uth_maxpages) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).uth_limit) as usize - ptr as usize }, 48usize, concat!( "Offset of field: ", stringify!(uma_type_header), "::", stringify!(uth_limit) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).uth_pages) as usize - ptr as usize }, 52usize, concat!( "Offset of field: ", stringify!(uma_type_header), "::", stringify!(uth_pages) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).uth_keg_free) as usize - ptr as usize }, 56usize, concat!( "Offset of field: ", stringify!(uma_type_header), "::", stringify!(uth_keg_free) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).uth_zone_free) as usize - ptr as usize }, 60usize, concat!( "Offset of field: ", stringify!(uma_type_header), "::", stringify!(uth_zone_free) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).uth_bucketsize) as usize - ptr as usize }, 64usize, concat!( "Offset of field: ", stringify!(uma_type_header), "::", stringify!(uth_bucketsize) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).uth_zone_flags) as usize - ptr as usize }, 68usize, concat!( "Offset of field: ", stringify!(uma_type_header), "::", stringify!(uth_zone_flags) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).uth_allocs) as usize - ptr as usize }, 72usize, concat!( "Offset of field: ", stringify!(uma_type_header), "::", stringify!(uth_allocs) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).uth_frees) as usize - ptr as usize }, 80usize, concat!( "Offset of field: ", stringify!(uma_type_header), "::", stringify!(uth_frees) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).uth_fails) as usize - ptr as usize }, 88usize, concat!( "Offset of field: ", stringify!(uma_type_header), "::", stringify!(uth_fails) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).uth_sleeps) as usize - ptr as usize }, 96usize, concat!( "Offset of field: ", stringify!(uma_type_header), "::", stringify!(uth_sleeps) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).uth_xdomain) as usize - ptr as usize }, 104usize, concat!( "Offset of field: ", stringify!(uma_type_header), "::", stringify!(uth_xdomain) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr)._uth_reserved1) as usize - ptr as usize }, 112usize, concat!( "Offset of field: ", stringify!(uma_type_header), "::", stringify!(_uth_reserved1) ) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct uma_percpu_stat { pub ups_allocs: u64, pub ups_frees: u64, pub ups_cache_free: u64, pub _ups_reserved: [u64; 5usize], } #[test] fn bindgen_test_layout_uma_percpu_stat() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 64usize, concat!("Size of: ", stringify!(uma_percpu_stat)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(uma_percpu_stat)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ups_allocs) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(uma_percpu_stat), "::", stringify!(ups_allocs) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ups_frees) as usize - ptr as usize }, 8usize, concat!( "Offset of field: ", stringify!(uma_percpu_stat), "::", stringify!(ups_frees) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ups_cache_free) as usize - ptr as usize }, 16usize, concat!( "Offset of field: ", stringify!(uma_percpu_stat), "::", stringify!(ups_cache_free) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr)._ups_reserved) as usize - ptr as usize }, 24usize, concat!( "Offset of field: ", stringify!(uma_percpu_stat), "::", stringify!(_ups_reserved) ) ); } unsafe extern "C" { pub fn uma_reclaim_wakeup(); } unsafe extern "C" { pub fn uma_reclaim_worker(arg1: *mut ::std::os::raw::c_void); } unsafe extern "C" { pub fn uma_limit() -> ::std::os::raw::c_ulong; } unsafe extern "C" { pub fn uma_size() -> ::std::os::raw::c_ulong; } unsafe extern "C" { pub fn uma_avail() -> ::std::os::raw::c_long; } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct timezone { pub tz_minuteswest: ::std::os::raw::c_int, pub tz_dsttime: ::std::os::raw::c_int, } #[test] fn bindgen_test_layout_timezone() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 8usize, concat!("Size of: ", stringify!(timezone)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(timezone)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).tz_minuteswest) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(timezone), "::", stringify!(tz_minuteswest) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).tz_dsttime) as usize - ptr as usize }, 4usize, concat!("Offset of field: ", stringify!(timezone), "::", stringify!(tz_dsttime)) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct bintime { pub sec: time_t, pub frac: u64, } #[test] fn bindgen_test_layout_bintime() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 16usize, concat!("Size of: ", stringify!(bintime)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(bintime)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).sec) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(bintime), "::", stringify!(sec)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).frac) as usize - ptr as usize }, 8usize, concat!("Offset of field: ", stringify!(bintime), "::", stringify!(frac)) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct itimerval { pub it_interval: timeval, pub it_value: timeval, } #[test] fn bindgen_test_layout_itimerval() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 32usize, concat!("Size of: ", stringify!(itimerval)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(itimerval)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).it_interval) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(itimerval), "::", stringify!(it_interval) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).it_value) as usize - ptr as usize }, 16usize, concat!("Offset of field: ", stringify!(itimerval), "::", stringify!(it_value)) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct clockinfo { pub hz: ::std::os::raw::c_int, pub tick: ::std::os::raw::c_int, pub spare: ::std::os::raw::c_int, pub stathz: ::std::os::raw::c_int, pub profhz: ::std::os::raw::c_int, } #[test] fn bindgen_test_layout_clockinfo() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 20usize, concat!("Size of: ", stringify!(clockinfo)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(clockinfo)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).hz) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(clockinfo), "::", stringify!(hz)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).tick) as usize - ptr as usize }, 4usize, concat!("Offset of field: ", stringify!(clockinfo), "::", stringify!(tick)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).spare) as usize - ptr as usize }, 8usize, concat!("Offset of field: ", stringify!(clockinfo), "::", stringify!(spare)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).stathz) as usize - ptr as usize }, 12usize, concat!("Offset of field: ", stringify!(clockinfo), "::", stringify!(stathz)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).profhz) as usize - ptr as usize }, 16usize, concat!("Offset of field: ", stringify!(clockinfo), "::", stringify!(profhz)) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct tm { pub tm_sec: ::std::os::raw::c_int, pub tm_min: ::std::os::raw::c_int, pub tm_hour: ::std::os::raw::c_int, pub tm_mday: ::std::os::raw::c_int, pub tm_mon: ::std::os::raw::c_int, pub tm_year: ::std::os::raw::c_int, pub tm_wday: ::std::os::raw::c_int, pub tm_yday: ::std::os::raw::c_int, pub tm_isdst: ::std::os::raw::c_int, pub tm_gmtoff: ::std::os::raw::c_long, pub tm_zone: *mut ::std::os::raw::c_char, } #[test] fn bindgen_test_layout_tm() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 56usize, concat!("Size of: ", stringify!(tm)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(tm)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).tm_sec) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(tm), "::", stringify!(tm_sec)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).tm_min) as usize - ptr as usize }, 4usize, concat!("Offset of field: ", stringify!(tm), "::", stringify!(tm_min)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).tm_hour) as usize - ptr as usize }, 8usize, concat!("Offset of field: ", stringify!(tm), "::", stringify!(tm_hour)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).tm_mday) as usize - ptr as usize }, 12usize, concat!("Offset of field: ", stringify!(tm), "::", stringify!(tm_mday)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).tm_mon) as usize - ptr as usize }, 16usize, concat!("Offset of field: ", stringify!(tm), "::", stringify!(tm_mon)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).tm_year) as usize - ptr as usize }, 20usize, concat!("Offset of field: ", stringify!(tm), "::", stringify!(tm_year)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).tm_wday) as usize - ptr as usize }, 24usize, concat!("Offset of field: ", stringify!(tm), "::", stringify!(tm_wday)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).tm_yday) as usize - ptr as usize }, 28usize, concat!("Offset of field: ", stringify!(tm), "::", stringify!(tm_yday)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).tm_isdst) as usize - ptr as usize }, 32usize, concat!("Offset of field: ", stringify!(tm), "::", stringify!(tm_isdst)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).tm_gmtoff) as usize - ptr as usize }, 40usize, concat!("Offset of field: ", stringify!(tm), "::", stringify!(tm_gmtoff)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).tm_zone) as usize - ptr as usize }, 48usize, concat!("Offset of field: ", stringify!(tm), "::", stringify!(tm_zone)) ); } unsafe extern "C" { pub static mut tzname: [*mut ::std::os::raw::c_char; 0usize]; } unsafe extern "C" { pub fn asctime(arg1: *const tm) -> *mut ::std::os::raw::c_char; } unsafe extern "C" { pub fn clock() -> clock_t; } unsafe extern "C" { pub fn ctime(arg1: *const time_t) -> *mut ::std::os::raw::c_char; } unsafe extern "C" { pub fn difftime(arg1: time_t, arg2: time_t) -> f64; } unsafe extern "C" { pub fn gmtime(arg1: *const time_t) -> *mut tm; } unsafe extern "C" { pub fn localtime(arg1: *const time_t) -> *mut tm; } unsafe extern "C" { pub fn mktime(arg1: *mut tm) -> time_t; } unsafe extern "C" { pub fn strftime( arg1: *mut ::std::os::raw::c_char, arg2: usize, arg3: *const ::std::os::raw::c_char, arg4: *const tm, ) -> usize; } unsafe extern "C" { pub fn time(arg1: *mut time_t) -> time_t; } unsafe extern "C" { pub fn timer_create(arg1: clockid_t, arg2: *mut sigevent, arg3: *mut timer_t) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn timer_delete(arg1: timer_t) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn timer_gettime(arg1: timer_t, arg2: *mut itimerspec) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn timer_getoverrun(arg1: timer_t) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn timer_settime( arg1: timer_t, arg2: ::std::os::raw::c_int, arg3: *const itimerspec, arg4: *mut itimerspec, ) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn tzset(); } unsafe extern "C" { pub fn clock_getres(arg1: clockid_t, arg2: *mut timespec) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn clock_gettime(arg1: clockid_t, arg2: *mut timespec) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn clock_settime(arg1: clockid_t, arg2: *const timespec) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn nanosleep(arg1: *const timespec, arg2: *mut timespec) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn clock_getcpuclockid(arg1: pid_t, arg2: *mut clockid_t) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn clock_nanosleep( arg1: clockid_t, arg2: ::std::os::raw::c_int, arg3: *const timespec, arg4: *mut timespec, ) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn asctime_r(arg1: *const tm, arg2: *mut ::std::os::raw::c_char) -> *mut ::std::os::raw::c_char; } unsafe extern "C" { pub fn ctime_r(arg1: *const time_t, arg2: *mut ::std::os::raw::c_char) -> *mut ::std::os::raw::c_char; } unsafe extern "C" { pub fn gmtime_r(arg1: *const time_t, arg2: *mut tm) -> *mut tm; } unsafe extern "C" { pub fn localtime_r(arg1: *const time_t, arg2: *mut tm) -> *mut tm; } unsafe extern "C" { pub fn strptime( arg1: *const ::std::os::raw::c_char, arg2: *const ::std::os::raw::c_char, arg3: *mut tm, ) -> *mut ::std::os::raw::c_char; } unsafe extern "C" { pub fn timezone(arg1: ::std::os::raw::c_int, arg2: ::std::os::raw::c_int) -> *mut ::std::os::raw::c_char; } unsafe extern "C" { pub fn timelocal(arg1: *mut tm) -> time_t; } unsafe extern "C" { pub fn timegm(arg1: *mut tm) -> time_t; } unsafe extern "C" { pub fn timer_oshandle_np(timerid: timer_t) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn time2posix(t: time_t) -> time_t; } unsafe extern "C" { pub fn posix2time(t: time_t) -> time_t; } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct _xlocale { _unused: [u8; 0], } pub type locale_t = *mut _xlocale; unsafe extern "C" { pub fn strftime_l( arg1: *mut ::std::os::raw::c_char, arg2: usize, arg3: *const ::std::os::raw::c_char, arg4: *const tm, arg5: locale_t, ) -> usize; } unsafe extern "C" { pub fn timespec_get(ts: *mut timespec, base: ::std::os::raw::c_int) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn timespec_getres(arg1: *mut timespec, arg2: ::std::os::raw::c_int) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn setitimer( arg1: ::std::os::raw::c_int, arg2: *const itimerval, arg3: *mut itimerval, ) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn utimes(arg1: *const ::std::os::raw::c_char, arg2: *const timeval) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn adjtime(arg1: *const timeval, arg2: *mut timeval) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn clock_getcpuclockid2(arg1: id_t, arg2: ::std::os::raw::c_int, arg3: *mut clockid_t) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn futimes(arg1: ::std::os::raw::c_int, arg2: *const timeval) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn futimesat( arg1: ::std::os::raw::c_int, arg2: *const ::std::os::raw::c_char, arg3: *const timeval, ) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn lutimes(arg1: *const ::std::os::raw::c_char, arg2: *const timeval) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn settimeofday(arg1: *const timeval, arg2: *const timezone) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn getitimer(arg1: ::std::os::raw::c_int, arg2: *mut itimerval) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn gettimeofday(arg1: *mut timeval, arg2: *mut timezone) -> ::std::os::raw::c_int; } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct iovec { pub iov_base: *mut ::std::os::raw::c_void, pub iov_len: usize, } #[test] fn bindgen_test_layout_iovec() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 16usize, concat!("Size of: ", stringify!(iovec)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(iovec)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).iov_base) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(iovec), "::", stringify!(iov_base)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).iov_len) as usize - ptr as usize }, 8usize, concat!("Offset of field: ", stringify!(iovec), "::", stringify!(iov_len)) ); } pub type sa_family_t = __sa_family_t; pub type socklen_t = __socklen_t; #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct linger { pub l_onoff: ::std::os::raw::c_int, pub l_linger: ::std::os::raw::c_int, } #[test] fn bindgen_test_layout_linger() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 8usize, concat!("Size of: ", stringify!(linger)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(linger)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).l_onoff) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(linger), "::", stringify!(l_onoff)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).l_linger) as usize - ptr as usize }, 4usize, concat!("Offset of field: ", stringify!(linger), "::", stringify!(l_linger)) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct accept_filter_arg { pub af_name: [::std::os::raw::c_char; 16usize], pub af_arg: [::std::os::raw::c_char; 240usize], } #[test] fn bindgen_test_layout_accept_filter_arg() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 256usize, concat!("Size of: ", stringify!(accept_filter_arg)) ); assert_eq!( ::std::mem::align_of::(), 1usize, concat!("Alignment of ", stringify!(accept_filter_arg)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).af_name) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(accept_filter_arg), "::", stringify!(af_name) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).af_arg) as usize - ptr as usize }, 16usize, concat!( "Offset of field: ", stringify!(accept_filter_arg), "::", stringify!(af_arg) ) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct sockaddr { pub sa_len: ::std::os::raw::c_uchar, pub sa_family: sa_family_t, pub sa_data: [::std::os::raw::c_char; 14usize], } #[test] fn bindgen_test_layout_sockaddr() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 16usize, concat!("Size of: ", stringify!(sockaddr)) ); assert_eq!( ::std::mem::align_of::(), 1usize, concat!("Alignment of ", stringify!(sockaddr)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).sa_len) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(sockaddr), "::", stringify!(sa_len)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).sa_family) as usize - ptr as usize }, 1usize, concat!("Offset of field: ", stringify!(sockaddr), "::", stringify!(sa_family)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).sa_data) as usize - ptr as usize }, 2usize, concat!("Offset of field: ", stringify!(sockaddr), "::", stringify!(sa_data)) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct sockproto { pub sp_family: ::std::os::raw::c_ushort, pub sp_protocol: ::std::os::raw::c_ushort, } #[test] fn bindgen_test_layout_sockproto() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 4usize, concat!("Size of: ", stringify!(sockproto)) ); assert_eq!( ::std::mem::align_of::(), 2usize, concat!("Alignment of ", stringify!(sockproto)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).sp_family) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(sockproto), "::", stringify!(sp_family)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).sp_protocol) as usize - ptr as usize }, 2usize, concat!( "Offset of field: ", stringify!(sockproto), "::", stringify!(sp_protocol) ) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct sockaddr_storage { pub ss_len: ::std::os::raw::c_uchar, pub ss_family: sa_family_t, pub __ss_pad1: [::std::os::raw::c_char; 6usize], pub __ss_align: __int64_t, pub __ss_pad2: [::std::os::raw::c_char; 112usize], } #[test] fn bindgen_test_layout_sockaddr_storage() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 128usize, concat!("Size of: ", stringify!(sockaddr_storage)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(sockaddr_storage)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ss_len) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(sockaddr_storage), "::", stringify!(ss_len) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ss_family) as usize - ptr as usize }, 1usize, concat!( "Offset of field: ", stringify!(sockaddr_storage), "::", stringify!(ss_family) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__ss_pad1) as usize - ptr as usize }, 2usize, concat!( "Offset of field: ", stringify!(sockaddr_storage), "::", stringify!(__ss_pad1) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__ss_align) as usize - ptr as usize }, 8usize, concat!( "Offset of field: ", stringify!(sockaddr_storage), "::", stringify!(__ss_align) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__ss_pad2) as usize - ptr as usize }, 16usize, concat!( "Offset of field: ", stringify!(sockaddr_storage), "::", stringify!(__ss_pad2) ) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct msghdr { pub msg_name: *mut ::std::os::raw::c_void, pub msg_namelen: socklen_t, pub msg_iov: *mut iovec, pub msg_iovlen: ::std::os::raw::c_int, pub msg_control: *mut ::std::os::raw::c_void, pub msg_controllen: socklen_t, pub msg_flags: ::std::os::raw::c_int, } #[test] fn bindgen_test_layout_msghdr() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 48usize, concat!("Size of: ", stringify!(msghdr)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(msghdr)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).msg_name) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(msghdr), "::", stringify!(msg_name)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).msg_namelen) as usize - ptr as usize }, 8usize, concat!("Offset of field: ", stringify!(msghdr), "::", stringify!(msg_namelen)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).msg_iov) as usize - ptr as usize }, 16usize, concat!("Offset of field: ", stringify!(msghdr), "::", stringify!(msg_iov)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).msg_iovlen) as usize - ptr as usize }, 24usize, concat!("Offset of field: ", stringify!(msghdr), "::", stringify!(msg_iovlen)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).msg_control) as usize - ptr as usize }, 32usize, concat!("Offset of field: ", stringify!(msghdr), "::", stringify!(msg_control)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).msg_controllen) as usize - ptr as usize }, 40usize, concat!( "Offset of field: ", stringify!(msghdr), "::", stringify!(msg_controllen) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).msg_flags) as usize - ptr as usize }, 44usize, concat!("Offset of field: ", stringify!(msghdr), "::", stringify!(msg_flags)) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct cmsghdr { pub cmsg_len: socklen_t, pub cmsg_level: ::std::os::raw::c_int, pub cmsg_type: ::std::os::raw::c_int, } #[test] fn bindgen_test_layout_cmsghdr() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 12usize, concat!("Size of: ", stringify!(cmsghdr)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(cmsghdr)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).cmsg_len) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(cmsghdr), "::", stringify!(cmsg_len)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).cmsg_level) as usize - ptr as usize }, 4usize, concat!("Offset of field: ", stringify!(cmsghdr), "::", stringify!(cmsg_level)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).cmsg_type) as usize - ptr as usize }, 8usize, concat!("Offset of field: ", stringify!(cmsghdr), "::", stringify!(cmsg_type)) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct cmsgcred { pub cmcred_pid: pid_t, pub cmcred_uid: uid_t, pub cmcred_euid: uid_t, pub cmcred_gid: gid_t, pub cmcred_ngroups: ::std::os::raw::c_short, pub cmcred_groups: [gid_t; 16usize], } #[test] fn bindgen_test_layout_cmsgcred() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 84usize, concat!("Size of: ", stringify!(cmsgcred)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(cmsgcred)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).cmcred_pid) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(cmsgcred), "::", stringify!(cmcred_pid)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).cmcred_uid) as usize - ptr as usize }, 4usize, concat!("Offset of field: ", stringify!(cmsgcred), "::", stringify!(cmcred_uid)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).cmcred_euid) as usize - ptr as usize }, 8usize, concat!("Offset of field: ", stringify!(cmsgcred), "::", stringify!(cmcred_euid)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).cmcred_gid) as usize - ptr as usize }, 12usize, concat!("Offset of field: ", stringify!(cmsgcred), "::", stringify!(cmcred_gid)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).cmcred_ngroups) as usize - ptr as usize }, 16usize, concat!( "Offset of field: ", stringify!(cmsgcred), "::", stringify!(cmcred_ngroups) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).cmcred_groups) as usize - ptr as usize }, 20usize, concat!( "Offset of field: ", stringify!(cmsgcred), "::", stringify!(cmcred_groups) ) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct sockcred { pub sc_uid: uid_t, pub sc_euid: uid_t, pub sc_gid: gid_t, pub sc_egid: gid_t, pub sc_ngroups: ::std::os::raw::c_int, pub sc_groups: [gid_t; 1usize], } #[test] fn bindgen_test_layout_sockcred() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 24usize, concat!("Size of: ", stringify!(sockcred)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(sockcred)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).sc_uid) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(sockcred), "::", stringify!(sc_uid)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).sc_euid) as usize - ptr as usize }, 4usize, concat!("Offset of field: ", stringify!(sockcred), "::", stringify!(sc_euid)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).sc_gid) as usize - ptr as usize }, 8usize, concat!("Offset of field: ", stringify!(sockcred), "::", stringify!(sc_gid)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).sc_egid) as usize - ptr as usize }, 12usize, concat!("Offset of field: ", stringify!(sockcred), "::", stringify!(sc_egid)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).sc_ngroups) as usize - ptr as usize }, 16usize, concat!("Offset of field: ", stringify!(sockcred), "::", stringify!(sc_ngroups)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).sc_groups) as usize - ptr as usize }, 20usize, concat!("Offset of field: ", stringify!(sockcred), "::", stringify!(sc_groups)) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct sockcred2 { pub sc_version: ::std::os::raw::c_int, pub sc_pid: pid_t, pub sc_uid: uid_t, pub sc_euid: uid_t, pub sc_gid: gid_t, pub sc_egid: gid_t, pub sc_ngroups: ::std::os::raw::c_int, pub sc_groups: [gid_t; 1usize], } #[test] fn bindgen_test_layout_sockcred2() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 32usize, concat!("Size of: ", stringify!(sockcred2)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(sockcred2)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).sc_version) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(sockcred2), "::", stringify!(sc_version)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).sc_pid) as usize - ptr as usize }, 4usize, concat!("Offset of field: ", stringify!(sockcred2), "::", stringify!(sc_pid)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).sc_uid) as usize - ptr as usize }, 8usize, concat!("Offset of field: ", stringify!(sockcred2), "::", stringify!(sc_uid)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).sc_euid) as usize - ptr as usize }, 12usize, concat!("Offset of field: ", stringify!(sockcred2), "::", stringify!(sc_euid)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).sc_gid) as usize - ptr as usize }, 16usize, concat!("Offset of field: ", stringify!(sockcred2), "::", stringify!(sc_gid)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).sc_egid) as usize - ptr as usize }, 20usize, concat!("Offset of field: ", stringify!(sockcred2), "::", stringify!(sc_egid)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).sc_ngroups) as usize - ptr as usize }, 24usize, concat!("Offset of field: ", stringify!(sockcred2), "::", stringify!(sc_ngroups)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).sc_groups) as usize - ptr as usize }, 28usize, concat!("Offset of field: ", stringify!(sockcred2), "::", stringify!(sc_groups)) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct sock_timestamp_info { pub st_info_flags: __uint32_t, pub st_info_pad0: __uint32_t, pub st_info_rsv: [__uint64_t; 7usize], } #[test] fn bindgen_test_layout_sock_timestamp_info() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 64usize, concat!("Size of: ", stringify!(sock_timestamp_info)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(sock_timestamp_info)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).st_info_flags) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(sock_timestamp_info), "::", stringify!(st_info_flags) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).st_info_pad0) as usize - ptr as usize }, 4usize, concat!( "Offset of field: ", stringify!(sock_timestamp_info), "::", stringify!(st_info_pad0) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).st_info_rsv) as usize - ptr as usize }, 8usize, concat!( "Offset of field: ", stringify!(sock_timestamp_info), "::", stringify!(st_info_rsv) ) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct osockaddr { pub sa_family: ::std::os::raw::c_ushort, pub sa_data: [::std::os::raw::c_char; 14usize], } #[test] fn bindgen_test_layout_osockaddr() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 16usize, concat!("Size of: ", stringify!(osockaddr)) ); assert_eq!( ::std::mem::align_of::(), 2usize, concat!("Alignment of ", stringify!(osockaddr)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).sa_family) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(osockaddr), "::", stringify!(sa_family)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).sa_data) as usize - ptr as usize }, 2usize, concat!("Offset of field: ", stringify!(osockaddr), "::", stringify!(sa_data)) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct omsghdr { pub msg_name: *mut ::std::os::raw::c_char, pub msg_namelen: ::std::os::raw::c_int, pub msg_iov: *mut iovec, pub msg_iovlen: ::std::os::raw::c_int, pub msg_accrights: *mut ::std::os::raw::c_char, pub msg_accrightslen: ::std::os::raw::c_int, } #[test] fn bindgen_test_layout_omsghdr() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 48usize, concat!("Size of: ", stringify!(omsghdr)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(omsghdr)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).msg_name) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(omsghdr), "::", stringify!(msg_name)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).msg_namelen) as usize - ptr as usize }, 8usize, concat!("Offset of field: ", stringify!(omsghdr), "::", stringify!(msg_namelen)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).msg_iov) as usize - ptr as usize }, 16usize, concat!("Offset of field: ", stringify!(omsghdr), "::", stringify!(msg_iov)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).msg_iovlen) as usize - ptr as usize }, 24usize, concat!("Offset of field: ", stringify!(omsghdr), "::", stringify!(msg_iovlen)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).msg_accrights) as usize - ptr as usize }, 32usize, concat!( "Offset of field: ", stringify!(omsghdr), "::", stringify!(msg_accrights) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).msg_accrightslen) as usize - ptr as usize }, 40usize, concat!( "Offset of field: ", stringify!(omsghdr), "::", stringify!(msg_accrightslen) ) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct sf_hdtr { pub headers: *mut iovec, pub hdr_cnt: ::std::os::raw::c_int, pub trailers: *mut iovec, pub trl_cnt: ::std::os::raw::c_int, } #[test] fn bindgen_test_layout_sf_hdtr() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 32usize, concat!("Size of: ", stringify!(sf_hdtr)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(sf_hdtr)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).headers) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(sf_hdtr), "::", stringify!(headers)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).hdr_cnt) as usize - ptr as usize }, 8usize, concat!("Offset of field: ", stringify!(sf_hdtr), "::", stringify!(hdr_cnt)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).trailers) as usize - ptr as usize }, 16usize, concat!("Offset of field: ", stringify!(sf_hdtr), "::", stringify!(trailers)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).trl_cnt) as usize - ptr as usize }, 24usize, concat!("Offset of field: ", stringify!(sf_hdtr), "::", stringify!(trl_cnt)) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct mmsghdr { pub msg_hdr: msghdr, pub msg_len: isize, } #[test] fn bindgen_test_layout_mmsghdr() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 56usize, concat!("Size of: ", stringify!(mmsghdr)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(mmsghdr)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).msg_hdr) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(mmsghdr), "::", stringify!(msg_hdr)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).msg_len) as usize - ptr as usize }, 48usize, concat!("Offset of field: ", stringify!(mmsghdr), "::", stringify!(msg_len)) ); } unsafe extern "C" { pub fn accept(arg1: ::std::os::raw::c_int, arg2: *mut sockaddr, arg3: *mut socklen_t) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn bind(arg1: ::std::os::raw::c_int, arg2: *const sockaddr, arg3: socklen_t) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn connect(arg1: ::std::os::raw::c_int, arg2: *const sockaddr, arg3: socklen_t) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn accept4( arg1: ::std::os::raw::c_int, arg2: *mut sockaddr, arg3: *mut socklen_t, arg4: ::std::os::raw::c_int, ) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn bindat( arg1: ::std::os::raw::c_int, arg2: ::std::os::raw::c_int, arg3: *const sockaddr, arg4: socklen_t, ) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn connectat( arg1: ::std::os::raw::c_int, arg2: ::std::os::raw::c_int, arg3: *const sockaddr, arg4: socklen_t, ) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn getpeername(arg1: ::std::os::raw::c_int, arg2: *mut sockaddr, arg3: *mut socklen_t) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn getsockname(arg1: ::std::os::raw::c_int, arg2: *mut sockaddr, arg3: *mut socklen_t) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn getsockopt( arg1: ::std::os::raw::c_int, arg2: ::std::os::raw::c_int, arg3: ::std::os::raw::c_int, arg4: *mut ::std::os::raw::c_void, arg5: *mut socklen_t, ) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn listen(arg1: ::std::os::raw::c_int, arg2: ::std::os::raw::c_int) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn recv( arg1: ::std::os::raw::c_int, arg2: *mut ::std::os::raw::c_void, arg3: usize, arg4: ::std::os::raw::c_int, ) -> isize; } unsafe extern "C" { pub fn recvfrom( arg1: ::std::os::raw::c_int, arg2: *mut ::std::os::raw::c_void, arg3: usize, arg4: ::std::os::raw::c_int, arg5: *mut sockaddr, arg6: *mut socklen_t, ) -> isize; } unsafe extern "C" { pub fn recvmsg(arg1: ::std::os::raw::c_int, arg2: *mut msghdr, arg3: ::std::os::raw::c_int) -> isize; } unsafe extern "C" { pub fn recvmmsg( arg1: ::std::os::raw::c_int, arg2: *mut mmsghdr, arg3: usize, arg4: ::std::os::raw::c_int, arg5: *const timespec, ) -> isize; } unsafe extern "C" { pub fn send( arg1: ::std::os::raw::c_int, arg2: *const ::std::os::raw::c_void, arg3: usize, arg4: ::std::os::raw::c_int, ) -> isize; } unsafe extern "C" { pub fn sendto( arg1: ::std::os::raw::c_int, arg2: *const ::std::os::raw::c_void, arg3: usize, arg4: ::std::os::raw::c_int, arg5: *const sockaddr, arg6: socklen_t, ) -> isize; } unsafe extern "C" { pub fn sendmsg(arg1: ::std::os::raw::c_int, arg2: *const msghdr, arg3: ::std::os::raw::c_int) -> isize; } unsafe extern "C" { pub fn sendfile( arg1: ::std::os::raw::c_int, arg2: ::std::os::raw::c_int, arg3: off_t, arg4: usize, arg5: *mut sf_hdtr, arg6: *mut off_t, arg7: ::std::os::raw::c_int, ) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn sendmmsg(arg1: ::std::os::raw::c_int, arg2: *mut mmsghdr, arg3: usize, arg4: ::std::os::raw::c_int) -> isize; } unsafe extern "C" { pub fn setfib(arg1: ::std::os::raw::c_int) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn setsockopt( arg1: ::std::os::raw::c_int, arg2: ::std::os::raw::c_int, arg3: ::std::os::raw::c_int, arg4: *const ::std::os::raw::c_void, arg5: socklen_t, ) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn shutdown(arg1: ::std::os::raw::c_int, arg2: ::std::os::raw::c_int) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn sockatmark(arg1: ::std::os::raw::c_int) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn socket( arg1: ::std::os::raw::c_int, arg2: ::std::os::raw::c_int, arg3: ::std::os::raw::c_int, ) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn socketpair( arg1: ::std::os::raw::c_int, arg2: ::std::os::raw::c_int, arg3: ::std::os::raw::c_int, arg4: *mut ::std::os::raw::c_int, ) -> ::std::os::raw::c_int; } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct if_clonereq { pub ifcr_total: ::std::os::raw::c_int, pub ifcr_count: ::std::os::raw::c_int, pub ifcr_buffer: *mut ::std::os::raw::c_char, } #[test] fn bindgen_test_layout_if_clonereq() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 16usize, concat!("Size of: ", stringify!(if_clonereq)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(if_clonereq)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifcr_total) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(if_clonereq), "::", stringify!(ifcr_total) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifcr_count) as usize - ptr as usize }, 4usize, concat!( "Offset of field: ", stringify!(if_clonereq), "::", stringify!(ifcr_count) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifcr_buffer) as usize - ptr as usize }, 8usize, concat!( "Offset of field: ", stringify!(if_clonereq), "::", stringify!(ifcr_buffer) ) ); } #[repr(C)] #[derive(Copy, Clone)] pub struct if_data { pub ifi_type: u8, pub ifi_physical: u8, pub ifi_addrlen: u8, pub ifi_hdrlen: u8, pub ifi_link_state: u8, pub ifi_vhid: u8, pub ifi_datalen: u16, pub ifi_mtu: u32, pub ifi_metric: u32, pub ifi_baudrate: u64, pub ifi_ipackets: u64, pub ifi_ierrors: u64, pub ifi_opackets: u64, pub ifi_oerrors: u64, pub ifi_collisions: u64, pub ifi_ibytes: u64, pub ifi_obytes: u64, pub ifi_imcasts: u64, pub ifi_omcasts: u64, pub ifi_iqdrops: u64, pub ifi_oqdrops: u64, pub ifi_noproto: u64, pub ifi_hwassist: u64, pub __ifi_epoch: if_data__bindgen_ty_1, pub __ifi_lastchange: if_data__bindgen_ty_2, } #[repr(C)] #[derive(Copy, Clone)] pub union if_data__bindgen_ty_1 { pub tt: time_t, pub ph: u64, } #[test] fn bindgen_test_layout_if_data__bindgen_ty_1() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 8usize, concat!("Size of: ", stringify!(if_data__bindgen_ty_1)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(if_data__bindgen_ty_1)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).tt) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(if_data__bindgen_ty_1), "::", stringify!(tt) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ph) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(if_data__bindgen_ty_1), "::", stringify!(ph) ) ); } #[repr(C)] #[derive(Copy, Clone)] pub union if_data__bindgen_ty_2 { pub tv: timeval, pub ph: if_data__bindgen_ty_2__bindgen_ty_1, } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct if_data__bindgen_ty_2__bindgen_ty_1 { pub ph1: u64, pub ph2: u64, } #[test] fn bindgen_test_layout_if_data__bindgen_ty_2__bindgen_ty_1() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 16usize, concat!("Size of: ", stringify!(if_data__bindgen_ty_2__bindgen_ty_1)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(if_data__bindgen_ty_2__bindgen_ty_1)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ph1) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(if_data__bindgen_ty_2__bindgen_ty_1), "::", stringify!(ph1) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ph2) as usize - ptr as usize }, 8usize, concat!( "Offset of field: ", stringify!(if_data__bindgen_ty_2__bindgen_ty_1), "::", stringify!(ph2) ) ); } #[test] fn bindgen_test_layout_if_data__bindgen_ty_2() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 16usize, concat!("Size of: ", stringify!(if_data__bindgen_ty_2)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(if_data__bindgen_ty_2)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).tv) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(if_data__bindgen_ty_2), "::", stringify!(tv) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ph) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(if_data__bindgen_ty_2), "::", stringify!(ph) ) ); } #[test] fn bindgen_test_layout_if_data() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 152usize, concat!("Size of: ", stringify!(if_data)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(if_data)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifi_type) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(if_data), "::", stringify!(ifi_type)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifi_physical) as usize - ptr as usize }, 1usize, concat!("Offset of field: ", stringify!(if_data), "::", stringify!(ifi_physical)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifi_addrlen) as usize - ptr as usize }, 2usize, concat!("Offset of field: ", stringify!(if_data), "::", stringify!(ifi_addrlen)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifi_hdrlen) as usize - ptr as usize }, 3usize, concat!("Offset of field: ", stringify!(if_data), "::", stringify!(ifi_hdrlen)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifi_link_state) as usize - ptr as usize }, 4usize, concat!( "Offset of field: ", stringify!(if_data), "::", stringify!(ifi_link_state) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifi_vhid) as usize - ptr as usize }, 5usize, concat!("Offset of field: ", stringify!(if_data), "::", stringify!(ifi_vhid)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifi_datalen) as usize - ptr as usize }, 6usize, concat!("Offset of field: ", stringify!(if_data), "::", stringify!(ifi_datalen)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifi_mtu) as usize - ptr as usize }, 8usize, concat!("Offset of field: ", stringify!(if_data), "::", stringify!(ifi_mtu)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifi_metric) as usize - ptr as usize }, 12usize, concat!("Offset of field: ", stringify!(if_data), "::", stringify!(ifi_metric)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifi_baudrate) as usize - ptr as usize }, 16usize, concat!("Offset of field: ", stringify!(if_data), "::", stringify!(ifi_baudrate)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifi_ipackets) as usize - ptr as usize }, 24usize, concat!("Offset of field: ", stringify!(if_data), "::", stringify!(ifi_ipackets)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifi_ierrors) as usize - ptr as usize }, 32usize, concat!("Offset of field: ", stringify!(if_data), "::", stringify!(ifi_ierrors)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifi_opackets) as usize - ptr as usize }, 40usize, concat!("Offset of field: ", stringify!(if_data), "::", stringify!(ifi_opackets)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifi_oerrors) as usize - ptr as usize }, 48usize, concat!("Offset of field: ", stringify!(if_data), "::", stringify!(ifi_oerrors)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifi_collisions) as usize - ptr as usize }, 56usize, concat!( "Offset of field: ", stringify!(if_data), "::", stringify!(ifi_collisions) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifi_ibytes) as usize - ptr as usize }, 64usize, concat!("Offset of field: ", stringify!(if_data), "::", stringify!(ifi_ibytes)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifi_obytes) as usize - ptr as usize }, 72usize, concat!("Offset of field: ", stringify!(if_data), "::", stringify!(ifi_obytes)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifi_imcasts) as usize - ptr as usize }, 80usize, concat!("Offset of field: ", stringify!(if_data), "::", stringify!(ifi_imcasts)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifi_omcasts) as usize - ptr as usize }, 88usize, concat!("Offset of field: ", stringify!(if_data), "::", stringify!(ifi_omcasts)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifi_iqdrops) as usize - ptr as usize }, 96usize, concat!("Offset of field: ", stringify!(if_data), "::", stringify!(ifi_iqdrops)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifi_oqdrops) as usize - ptr as usize }, 104usize, concat!("Offset of field: ", stringify!(if_data), "::", stringify!(ifi_oqdrops)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifi_noproto) as usize - ptr as usize }, 112usize, concat!("Offset of field: ", stringify!(if_data), "::", stringify!(ifi_noproto)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifi_hwassist) as usize - ptr as usize }, 120usize, concat!("Offset of field: ", stringify!(if_data), "::", stringify!(ifi_hwassist)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__ifi_epoch) as usize - ptr as usize }, 128usize, concat!("Offset of field: ", stringify!(if_data), "::", stringify!(__ifi_epoch)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__ifi_lastchange) as usize - ptr as usize }, 136usize, concat!( "Offset of field: ", stringify!(if_data), "::", stringify!(__ifi_lastchange) ) ); } #[repr(C)] #[derive(Copy, Clone)] pub struct if_msghdr { pub ifm_msglen: u_short, pub ifm_version: u_char, pub ifm_type: u_char, pub ifm_addrs: ::std::os::raw::c_int, pub ifm_flags: ::std::os::raw::c_int, pub ifm_index: u_short, pub _ifm_spare1: u_short, pub ifm_data: if_data, } #[test] fn bindgen_test_layout_if_msghdr() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 168usize, concat!("Size of: ", stringify!(if_msghdr)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(if_msghdr)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifm_msglen) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(if_msghdr), "::", stringify!(ifm_msglen)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifm_version) as usize - ptr as usize }, 2usize, concat!( "Offset of field: ", stringify!(if_msghdr), "::", stringify!(ifm_version) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifm_type) as usize - ptr as usize }, 3usize, concat!("Offset of field: ", stringify!(if_msghdr), "::", stringify!(ifm_type)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifm_addrs) as usize - ptr as usize }, 4usize, concat!("Offset of field: ", stringify!(if_msghdr), "::", stringify!(ifm_addrs)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifm_flags) as usize - ptr as usize }, 8usize, concat!("Offset of field: ", stringify!(if_msghdr), "::", stringify!(ifm_flags)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifm_index) as usize - ptr as usize }, 12usize, concat!("Offset of field: ", stringify!(if_msghdr), "::", stringify!(ifm_index)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr)._ifm_spare1) as usize - ptr as usize }, 14usize, concat!( "Offset of field: ", stringify!(if_msghdr), "::", stringify!(_ifm_spare1) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifm_data) as usize - ptr as usize }, 16usize, concat!("Offset of field: ", stringify!(if_msghdr), "::", stringify!(ifm_data)) ); } #[repr(C)] #[derive(Copy, Clone)] pub struct if_msghdrl { pub ifm_msglen: u_short, pub ifm_version: u_char, pub ifm_type: u_char, pub ifm_addrs: ::std::os::raw::c_int, pub ifm_flags: ::std::os::raw::c_int, pub ifm_index: u_short, pub _ifm_spare1: u_short, pub ifm_len: u_short, pub ifm_data_off: u_short, pub _ifm_spare2: ::std::os::raw::c_int, pub ifm_data: if_data, } #[test] fn bindgen_test_layout_if_msghdrl() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 176usize, concat!("Size of: ", stringify!(if_msghdrl)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(if_msghdrl)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifm_msglen) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(if_msghdrl), "::", stringify!(ifm_msglen) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifm_version) as usize - ptr as usize }, 2usize, concat!( "Offset of field: ", stringify!(if_msghdrl), "::", stringify!(ifm_version) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifm_type) as usize - ptr as usize }, 3usize, concat!("Offset of field: ", stringify!(if_msghdrl), "::", stringify!(ifm_type)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifm_addrs) as usize - ptr as usize }, 4usize, concat!("Offset of field: ", stringify!(if_msghdrl), "::", stringify!(ifm_addrs)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifm_flags) as usize - ptr as usize }, 8usize, concat!("Offset of field: ", stringify!(if_msghdrl), "::", stringify!(ifm_flags)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifm_index) as usize - ptr as usize }, 12usize, concat!("Offset of field: ", stringify!(if_msghdrl), "::", stringify!(ifm_index)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr)._ifm_spare1) as usize - ptr as usize }, 14usize, concat!( "Offset of field: ", stringify!(if_msghdrl), "::", stringify!(_ifm_spare1) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifm_len) as usize - ptr as usize }, 16usize, concat!("Offset of field: ", stringify!(if_msghdrl), "::", stringify!(ifm_len)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifm_data_off) as usize - ptr as usize }, 18usize, concat!( "Offset of field: ", stringify!(if_msghdrl), "::", stringify!(ifm_data_off) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr)._ifm_spare2) as usize - ptr as usize }, 20usize, concat!( "Offset of field: ", stringify!(if_msghdrl), "::", stringify!(_ifm_spare2) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifm_data) as usize - ptr as usize }, 24usize, concat!("Offset of field: ", stringify!(if_msghdrl), "::", stringify!(ifm_data)) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct ifa_msghdr { pub ifam_msglen: u_short, pub ifam_version: u_char, pub ifam_type: u_char, pub ifam_addrs: ::std::os::raw::c_int, pub ifam_flags: ::std::os::raw::c_int, pub ifam_index: u_short, pub _ifam_spare1: u_short, pub ifam_metric: ::std::os::raw::c_int, } #[test] fn bindgen_test_layout_ifa_msghdr() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 20usize, concat!("Size of: ", stringify!(ifa_msghdr)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(ifa_msghdr)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifam_msglen) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(ifa_msghdr), "::", stringify!(ifam_msglen) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifam_version) as usize - ptr as usize }, 2usize, concat!( "Offset of field: ", stringify!(ifa_msghdr), "::", stringify!(ifam_version) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifam_type) as usize - ptr as usize }, 3usize, concat!("Offset of field: ", stringify!(ifa_msghdr), "::", stringify!(ifam_type)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifam_addrs) as usize - ptr as usize }, 4usize, concat!( "Offset of field: ", stringify!(ifa_msghdr), "::", stringify!(ifam_addrs) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifam_flags) as usize - ptr as usize }, 8usize, concat!( "Offset of field: ", stringify!(ifa_msghdr), "::", stringify!(ifam_flags) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifam_index) as usize - ptr as usize }, 12usize, concat!( "Offset of field: ", stringify!(ifa_msghdr), "::", stringify!(ifam_index) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr)._ifam_spare1) as usize - ptr as usize }, 14usize, concat!( "Offset of field: ", stringify!(ifa_msghdr), "::", stringify!(_ifam_spare1) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifam_metric) as usize - ptr as usize }, 16usize, concat!( "Offset of field: ", stringify!(ifa_msghdr), "::", stringify!(ifam_metric) ) ); } #[repr(C)] #[derive(Copy, Clone)] pub struct ifa_msghdrl { pub ifam_msglen: u_short, pub ifam_version: u_char, pub ifam_type: u_char, pub ifam_addrs: ::std::os::raw::c_int, pub ifam_flags: ::std::os::raw::c_int, pub ifam_index: u_short, pub _ifam_spare1: u_short, pub ifam_len: u_short, pub ifam_data_off: u_short, pub ifam_metric: ::std::os::raw::c_int, pub ifam_data: if_data, } #[test] fn bindgen_test_layout_ifa_msghdrl() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 176usize, concat!("Size of: ", stringify!(ifa_msghdrl)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(ifa_msghdrl)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifam_msglen) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(ifa_msghdrl), "::", stringify!(ifam_msglen) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifam_version) as usize - ptr as usize }, 2usize, concat!( "Offset of field: ", stringify!(ifa_msghdrl), "::", stringify!(ifam_version) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifam_type) as usize - ptr as usize }, 3usize, concat!( "Offset of field: ", stringify!(ifa_msghdrl), "::", stringify!(ifam_type) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifam_addrs) as usize - ptr as usize }, 4usize, concat!( "Offset of field: ", stringify!(ifa_msghdrl), "::", stringify!(ifam_addrs) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifam_flags) as usize - ptr as usize }, 8usize, concat!( "Offset of field: ", stringify!(ifa_msghdrl), "::", stringify!(ifam_flags) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifam_index) as usize - ptr as usize }, 12usize, concat!( "Offset of field: ", stringify!(ifa_msghdrl), "::", stringify!(ifam_index) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr)._ifam_spare1) as usize - ptr as usize }, 14usize, concat!( "Offset of field: ", stringify!(ifa_msghdrl), "::", stringify!(_ifam_spare1) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifam_len) as usize - ptr as usize }, 16usize, concat!("Offset of field: ", stringify!(ifa_msghdrl), "::", stringify!(ifam_len)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifam_data_off) as usize - ptr as usize }, 18usize, concat!( "Offset of field: ", stringify!(ifa_msghdrl), "::", stringify!(ifam_data_off) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifam_metric) as usize - ptr as usize }, 20usize, concat!( "Offset of field: ", stringify!(ifa_msghdrl), "::", stringify!(ifam_metric) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifam_data) as usize - ptr as usize }, 24usize, concat!( "Offset of field: ", stringify!(ifa_msghdrl), "::", stringify!(ifam_data) ) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct ifma_msghdr { pub ifmam_msglen: u_short, pub ifmam_version: u_char, pub ifmam_type: u_char, pub ifmam_addrs: ::std::os::raw::c_int, pub ifmam_flags: ::std::os::raw::c_int, pub ifmam_index: u_short, pub _ifmam_spare1: u_short, } #[test] fn bindgen_test_layout_ifma_msghdr() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 16usize, concat!("Size of: ", stringify!(ifma_msghdr)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(ifma_msghdr)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifmam_msglen) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(ifma_msghdr), "::", stringify!(ifmam_msglen) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifmam_version) as usize - ptr as usize }, 2usize, concat!( "Offset of field: ", stringify!(ifma_msghdr), "::", stringify!(ifmam_version) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifmam_type) as usize - ptr as usize }, 3usize, concat!( "Offset of field: ", stringify!(ifma_msghdr), "::", stringify!(ifmam_type) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifmam_addrs) as usize - ptr as usize }, 4usize, concat!( "Offset of field: ", stringify!(ifma_msghdr), "::", stringify!(ifmam_addrs) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifmam_flags) as usize - ptr as usize }, 8usize, concat!( "Offset of field: ", stringify!(ifma_msghdr), "::", stringify!(ifmam_flags) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifmam_index) as usize - ptr as usize }, 12usize, concat!( "Offset of field: ", stringify!(ifma_msghdr), "::", stringify!(ifmam_index) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr)._ifmam_spare1) as usize - ptr as usize }, 14usize, concat!( "Offset of field: ", stringify!(ifma_msghdr), "::", stringify!(_ifmam_spare1) ) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct if_announcemsghdr { pub ifan_msglen: u_short, pub ifan_version: u_char, pub ifan_type: u_char, pub ifan_index: u_short, pub ifan_name: [::std::os::raw::c_char; 16usize], pub ifan_what: u_short, } #[test] fn bindgen_test_layout_if_announcemsghdr() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 24usize, concat!("Size of: ", stringify!(if_announcemsghdr)) ); assert_eq!( ::std::mem::align_of::(), 2usize, concat!("Alignment of ", stringify!(if_announcemsghdr)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifan_msglen) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(if_announcemsghdr), "::", stringify!(ifan_msglen) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifan_version) as usize - ptr as usize }, 2usize, concat!( "Offset of field: ", stringify!(if_announcemsghdr), "::", stringify!(ifan_version) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifan_type) as usize - ptr as usize }, 3usize, concat!( "Offset of field: ", stringify!(if_announcemsghdr), "::", stringify!(ifan_type) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifan_index) as usize - ptr as usize }, 4usize, concat!( "Offset of field: ", stringify!(if_announcemsghdr), "::", stringify!(ifan_index) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifan_name) as usize - ptr as usize }, 6usize, concat!( "Offset of field: ", stringify!(if_announcemsghdr), "::", stringify!(ifan_name) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifan_what) as usize - ptr as usize }, 22usize, concat!( "Offset of field: ", stringify!(if_announcemsghdr), "::", stringify!(ifan_what) ) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct ifreq_buffer { pub length: usize, pub buffer: *mut ::std::os::raw::c_void, } #[test] fn bindgen_test_layout_ifreq_buffer() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 16usize, concat!("Size of: ", stringify!(ifreq_buffer)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(ifreq_buffer)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).length) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(ifreq_buffer), "::", stringify!(length)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).buffer) as usize - ptr as usize }, 8usize, concat!("Offset of field: ", stringify!(ifreq_buffer), "::", stringify!(buffer)) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct ifreq_nv_req { pub buf_length: u_int, pub length: u_int, pub buffer: *mut ::std::os::raw::c_void, } #[test] fn bindgen_test_layout_ifreq_nv_req() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 16usize, concat!("Size of: ", stringify!(ifreq_nv_req)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(ifreq_nv_req)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).buf_length) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(ifreq_nv_req), "::", stringify!(buf_length) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).length) as usize - ptr as usize }, 4usize, concat!("Offset of field: ", stringify!(ifreq_nv_req), "::", stringify!(length)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).buffer) as usize - ptr as usize }, 8usize, concat!("Offset of field: ", stringify!(ifreq_nv_req), "::", stringify!(buffer)) ); } #[repr(C)] #[derive(Copy, Clone)] pub struct ifreq { pub ifr_name: [::std::os::raw::c_char; 16usize], pub ifr_ifru: ifreq__bindgen_ty_1, } #[repr(C)] #[derive(Copy, Clone)] pub union ifreq__bindgen_ty_1 { pub ifru_addr: sockaddr, pub ifru_dstaddr: sockaddr, pub ifru_broadaddr: sockaddr, pub ifru_buffer: ifreq_buffer, pub ifru_flags: [::std::os::raw::c_short; 2usize], pub ifru_index: ::std::os::raw::c_short, pub ifru_jid: ::std::os::raw::c_int, pub ifru_metric: ::std::os::raw::c_int, pub ifru_mtu: ::std::os::raw::c_int, pub ifru_phys: ::std::os::raw::c_int, pub ifru_media: ::std::os::raw::c_int, pub ifru_data: caddr_t, pub ifru_cap: [::std::os::raw::c_int; 2usize], pub ifru_fib: u_int, pub ifru_vlan_pcp: u_char, pub ifru_nv: ifreq_nv_req, } #[test] fn bindgen_test_layout_ifreq__bindgen_ty_1() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 16usize, concat!("Size of: ", stringify!(ifreq__bindgen_ty_1)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(ifreq__bindgen_ty_1)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifru_addr) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(ifreq__bindgen_ty_1), "::", stringify!(ifru_addr) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifru_dstaddr) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(ifreq__bindgen_ty_1), "::", stringify!(ifru_dstaddr) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifru_broadaddr) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(ifreq__bindgen_ty_1), "::", stringify!(ifru_broadaddr) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifru_buffer) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(ifreq__bindgen_ty_1), "::", stringify!(ifru_buffer) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifru_flags) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(ifreq__bindgen_ty_1), "::", stringify!(ifru_flags) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifru_index) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(ifreq__bindgen_ty_1), "::", stringify!(ifru_index) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifru_jid) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(ifreq__bindgen_ty_1), "::", stringify!(ifru_jid) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifru_metric) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(ifreq__bindgen_ty_1), "::", stringify!(ifru_metric) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifru_mtu) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(ifreq__bindgen_ty_1), "::", stringify!(ifru_mtu) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifru_phys) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(ifreq__bindgen_ty_1), "::", stringify!(ifru_phys) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifru_media) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(ifreq__bindgen_ty_1), "::", stringify!(ifru_media) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifru_data) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(ifreq__bindgen_ty_1), "::", stringify!(ifru_data) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifru_cap) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(ifreq__bindgen_ty_1), "::", stringify!(ifru_cap) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifru_fib) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(ifreq__bindgen_ty_1), "::", stringify!(ifru_fib) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifru_vlan_pcp) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(ifreq__bindgen_ty_1), "::", stringify!(ifru_vlan_pcp) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifru_nv) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(ifreq__bindgen_ty_1), "::", stringify!(ifru_nv) ) ); } #[test] fn bindgen_test_layout_ifreq() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 32usize, concat!("Size of: ", stringify!(ifreq)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(ifreq)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifr_name) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(ifreq), "::", stringify!(ifr_name)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifr_ifru) as usize - ptr as usize }, 16usize, concat!("Offset of field: ", stringify!(ifreq), "::", stringify!(ifr_ifru)) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct ifaliasreq { pub ifra_name: [::std::os::raw::c_char; 16usize], pub ifra_addr: sockaddr, pub ifra_broadaddr: sockaddr, pub ifra_mask: sockaddr, pub ifra_vhid: ::std::os::raw::c_int, } #[test] fn bindgen_test_layout_ifaliasreq() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 68usize, concat!("Size of: ", stringify!(ifaliasreq)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(ifaliasreq)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifra_name) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(ifaliasreq), "::", stringify!(ifra_name)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifra_addr) as usize - ptr as usize }, 16usize, concat!("Offset of field: ", stringify!(ifaliasreq), "::", stringify!(ifra_addr)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifra_broadaddr) as usize - ptr as usize }, 32usize, concat!( "Offset of field: ", stringify!(ifaliasreq), "::", stringify!(ifra_broadaddr) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifra_mask) as usize - ptr as usize }, 48usize, concat!("Offset of field: ", stringify!(ifaliasreq), "::", stringify!(ifra_mask)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifra_vhid) as usize - ptr as usize }, 64usize, concat!("Offset of field: ", stringify!(ifaliasreq), "::", stringify!(ifra_vhid)) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct oifaliasreq { pub ifra_name: [::std::os::raw::c_char; 16usize], pub ifra_addr: sockaddr, pub ifra_broadaddr: sockaddr, pub ifra_mask: sockaddr, } #[test] fn bindgen_test_layout_oifaliasreq() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 64usize, concat!("Size of: ", stringify!(oifaliasreq)) ); assert_eq!( ::std::mem::align_of::(), 1usize, concat!("Alignment of ", stringify!(oifaliasreq)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifra_name) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(oifaliasreq), "::", stringify!(ifra_name) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifra_addr) as usize - ptr as usize }, 16usize, concat!( "Offset of field: ", stringify!(oifaliasreq), "::", stringify!(ifra_addr) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifra_broadaddr) as usize - ptr as usize }, 32usize, concat!( "Offset of field: ", stringify!(oifaliasreq), "::", stringify!(ifra_broadaddr) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifra_mask) as usize - ptr as usize }, 48usize, concat!( "Offset of field: ", stringify!(oifaliasreq), "::", stringify!(ifra_mask) ) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct ifmediareq { pub ifm_name: [::std::os::raw::c_char; 16usize], pub ifm_current: ::std::os::raw::c_int, pub ifm_mask: ::std::os::raw::c_int, pub ifm_status: ::std::os::raw::c_int, pub ifm_active: ::std::os::raw::c_int, pub ifm_count: ::std::os::raw::c_int, pub ifm_ulist: *mut ::std::os::raw::c_int, } #[test] fn bindgen_test_layout_ifmediareq() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 48usize, concat!("Size of: ", stringify!(ifmediareq)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(ifmediareq)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifm_name) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(ifmediareq), "::", stringify!(ifm_name)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifm_current) as usize - ptr as usize }, 16usize, concat!( "Offset of field: ", stringify!(ifmediareq), "::", stringify!(ifm_current) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifm_mask) as usize - ptr as usize }, 20usize, concat!("Offset of field: ", stringify!(ifmediareq), "::", stringify!(ifm_mask)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifm_status) as usize - ptr as usize }, 24usize, concat!( "Offset of field: ", stringify!(ifmediareq), "::", stringify!(ifm_status) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifm_active) as usize - ptr as usize }, 28usize, concat!( "Offset of field: ", stringify!(ifmediareq), "::", stringify!(ifm_active) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifm_count) as usize - ptr as usize }, 32usize, concat!("Offset of field: ", stringify!(ifmediareq), "::", stringify!(ifm_count)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifm_ulist) as usize - ptr as usize }, 40usize, concat!("Offset of field: ", stringify!(ifmediareq), "::", stringify!(ifm_ulist)) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct ifdrv { pub ifd_name: [::std::os::raw::c_char; 16usize], pub ifd_cmd: ::std::os::raw::c_ulong, pub ifd_len: usize, pub ifd_data: *mut ::std::os::raw::c_void, } #[test] fn bindgen_test_layout_ifdrv() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 40usize, concat!("Size of: ", stringify!(ifdrv)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(ifdrv)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifd_name) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(ifdrv), "::", stringify!(ifd_name)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifd_cmd) as usize - ptr as usize }, 16usize, concat!("Offset of field: ", stringify!(ifdrv), "::", stringify!(ifd_cmd)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifd_len) as usize - ptr as usize }, 24usize, concat!("Offset of field: ", stringify!(ifdrv), "::", stringify!(ifd_len)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifd_data) as usize - ptr as usize }, 32usize, concat!("Offset of field: ", stringify!(ifdrv), "::", stringify!(ifd_data)) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct ifstat { pub ifs_name: [::std::os::raw::c_char; 16usize], pub ascii: [::std::os::raw::c_char; 801usize], } #[test] fn bindgen_test_layout_ifstat() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 817usize, concat!("Size of: ", stringify!(ifstat)) ); assert_eq!( ::std::mem::align_of::(), 1usize, concat!("Alignment of ", stringify!(ifstat)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifs_name) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(ifstat), "::", stringify!(ifs_name)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ascii) as usize - ptr as usize }, 16usize, concat!("Offset of field: ", stringify!(ifstat), "::", stringify!(ascii)) ); } #[repr(C)] #[derive(Copy, Clone)] pub struct ifconf { pub ifc_len: ::std::os::raw::c_int, pub ifc_ifcu: ifconf__bindgen_ty_1, } #[repr(C)] #[derive(Copy, Clone)] pub union ifconf__bindgen_ty_1 { pub ifcu_buf: caddr_t, pub ifcu_req: *mut ifreq, } #[test] fn bindgen_test_layout_ifconf__bindgen_ty_1() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 8usize, concat!("Size of: ", stringify!(ifconf__bindgen_ty_1)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(ifconf__bindgen_ty_1)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifcu_buf) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(ifconf__bindgen_ty_1), "::", stringify!(ifcu_buf) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifcu_req) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(ifconf__bindgen_ty_1), "::", stringify!(ifcu_req) ) ); } #[test] fn bindgen_test_layout_ifconf() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 16usize, concat!("Size of: ", stringify!(ifconf)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(ifconf)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifc_len) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(ifconf), "::", stringify!(ifc_len)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifc_ifcu) as usize - ptr as usize }, 8usize, concat!("Offset of field: ", stringify!(ifconf), "::", stringify!(ifc_ifcu)) ); } #[repr(C)] #[derive(Copy, Clone)] pub struct ifg_req { pub ifgrq_ifgrqu: ifg_req__bindgen_ty_1, } #[repr(C)] #[derive(Copy, Clone)] pub union ifg_req__bindgen_ty_1 { pub ifgrqu_group: [::std::os::raw::c_char; 16usize], pub ifgrqu_member: [::std::os::raw::c_char; 16usize], } #[test] fn bindgen_test_layout_ifg_req__bindgen_ty_1() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 16usize, concat!("Size of: ", stringify!(ifg_req__bindgen_ty_1)) ); assert_eq!( ::std::mem::align_of::(), 1usize, concat!("Alignment of ", stringify!(ifg_req__bindgen_ty_1)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifgrqu_group) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(ifg_req__bindgen_ty_1), "::", stringify!(ifgrqu_group) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifgrqu_member) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(ifg_req__bindgen_ty_1), "::", stringify!(ifgrqu_member) ) ); } #[test] fn bindgen_test_layout_ifg_req() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 16usize, concat!("Size of: ", stringify!(ifg_req)) ); assert_eq!( ::std::mem::align_of::(), 1usize, concat!("Alignment of ", stringify!(ifg_req)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifgrq_ifgrqu) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(ifg_req), "::", stringify!(ifgrq_ifgrqu)) ); } #[repr(C)] #[derive(Copy, Clone)] pub struct ifgroupreq { pub ifgr_name: [::std::os::raw::c_char; 16usize], pub ifgr_len: u_int, pub ifgr_ifgru: ifgroupreq__bindgen_ty_1, } #[repr(C)] #[derive(Copy, Clone)] pub union ifgroupreq__bindgen_ty_1 { pub ifgru_group: [::std::os::raw::c_char; 16usize], pub ifgru_groups: *mut ifg_req, } #[test] fn bindgen_test_layout_ifgroupreq__bindgen_ty_1() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 16usize, concat!("Size of: ", stringify!(ifgroupreq__bindgen_ty_1)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(ifgroupreq__bindgen_ty_1)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifgru_group) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(ifgroupreq__bindgen_ty_1), "::", stringify!(ifgru_group) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifgru_groups) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(ifgroupreq__bindgen_ty_1), "::", stringify!(ifgru_groups) ) ); } #[test] fn bindgen_test_layout_ifgroupreq() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 40usize, concat!("Size of: ", stringify!(ifgroupreq)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(ifgroupreq)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifgr_name) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(ifgroupreq), "::", stringify!(ifgr_name)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifgr_len) as usize - ptr as usize }, 16usize, concat!("Offset of field: ", stringify!(ifgroupreq), "::", stringify!(ifgr_len)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifgr_ifgru) as usize - ptr as usize }, 24usize, concat!( "Offset of field: ", stringify!(ifgroupreq), "::", stringify!(ifgr_ifgru) ) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct ifi2creq { pub dev_addr: u8, pub offset: u8, pub len: u8, pub spare0: u8, pub spare1: u32, pub data: [u8; 8usize], } #[test] fn bindgen_test_layout_ifi2creq() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 16usize, concat!("Size of: ", stringify!(ifi2creq)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(ifi2creq)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).dev_addr) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(ifi2creq), "::", stringify!(dev_addr)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).offset) as usize - ptr as usize }, 1usize, concat!("Offset of field: ", stringify!(ifi2creq), "::", stringify!(offset)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).len) as usize - ptr as usize }, 2usize, concat!("Offset of field: ", stringify!(ifi2creq), "::", stringify!(len)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).spare0) as usize - ptr as usize }, 3usize, concat!("Offset of field: ", stringify!(ifi2creq), "::", stringify!(spare0)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).spare1) as usize - ptr as usize }, 4usize, concat!("Offset of field: ", stringify!(ifi2creq), "::", stringify!(spare1)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).data) as usize - ptr as usize }, 8usize, concat!("Offset of field: ", stringify!(ifi2creq), "::", stringify!(data)) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct ifrsskey { pub ifrk_name: [::std::os::raw::c_char; 16usize], pub ifrk_func: u8, pub ifrk_spare0: u8, pub ifrk_keylen: u16, pub ifrk_key: [u8; 128usize], } #[test] fn bindgen_test_layout_ifrsskey() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 148usize, concat!("Size of: ", stringify!(ifrsskey)) ); assert_eq!( ::std::mem::align_of::(), 2usize, concat!("Alignment of ", stringify!(ifrsskey)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifrk_name) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(ifrsskey), "::", stringify!(ifrk_name)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifrk_func) as usize - ptr as usize }, 16usize, concat!("Offset of field: ", stringify!(ifrsskey), "::", stringify!(ifrk_func)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifrk_spare0) as usize - ptr as usize }, 17usize, concat!("Offset of field: ", stringify!(ifrsskey), "::", stringify!(ifrk_spare0)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifrk_keylen) as usize - ptr as usize }, 18usize, concat!("Offset of field: ", stringify!(ifrsskey), "::", stringify!(ifrk_keylen)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifrk_key) as usize - ptr as usize }, 20usize, concat!("Offset of field: ", stringify!(ifrsskey), "::", stringify!(ifrk_key)) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct ifrsshash { pub ifrh_name: [::std::os::raw::c_char; 16usize], pub ifrh_func: u8, pub ifrh_spare0: u8, pub ifrh_spare1: u16, pub ifrh_types: u32, } #[test] fn bindgen_test_layout_ifrsshash() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 24usize, concat!("Size of: ", stringify!(ifrsshash)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(ifrsshash)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifrh_name) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(ifrsshash), "::", stringify!(ifrh_name)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifrh_func) as usize - ptr as usize }, 16usize, concat!("Offset of field: ", stringify!(ifrsshash), "::", stringify!(ifrh_func)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifrh_spare0) as usize - ptr as usize }, 17usize, concat!( "Offset of field: ", stringify!(ifrsshash), "::", stringify!(ifrh_spare0) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifrh_spare1) as usize - ptr as usize }, 18usize, concat!( "Offset of field: ", stringify!(ifrsshash), "::", stringify!(ifrh_spare1) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifrh_types) as usize - ptr as usize }, 20usize, concat!("Offset of field: ", stringify!(ifrsshash), "::", stringify!(ifrh_types)) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct ifdownreason { pub ifdr_name: [::std::os::raw::c_char; 16usize], pub ifdr_reason: u32, pub ifdr_vendor: u32, pub ifdr_msg: [::std::os::raw::c_char; 64usize], } #[test] fn bindgen_test_layout_ifdownreason() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 88usize, concat!("Size of: ", stringify!(ifdownreason)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(ifdownreason)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifdr_name) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(ifdownreason), "::", stringify!(ifdr_name) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifdr_reason) as usize - ptr as usize }, 16usize, concat!( "Offset of field: ", stringify!(ifdownreason), "::", stringify!(ifdr_reason) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifdr_vendor) as usize - ptr as usize }, 20usize, concat!( "Offset of field: ", stringify!(ifdownreason), "::", stringify!(ifdr_vendor) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifdr_msg) as usize - ptr as usize }, 24usize, concat!( "Offset of field: ", stringify!(ifdownreason), "::", stringify!(ifdr_msg) ) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct ifnet { _unused: [u8; 0], } pub type if_t = *mut ifnet; #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct if_nameindex { pub if_index: ::std::os::raw::c_uint, pub if_name: *mut ::std::os::raw::c_char, } #[test] fn bindgen_test_layout_if_nameindex() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 16usize, concat!("Size of: ", stringify!(if_nameindex)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(if_nameindex)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).if_index) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(if_nameindex), "::", stringify!(if_index) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).if_name) as usize - ptr as usize }, 8usize, concat!("Offset of field: ", stringify!(if_nameindex), "::", stringify!(if_name)) ); } unsafe extern "C" { pub fn if_freenameindex(arg1: *mut if_nameindex); } unsafe extern "C" { pub fn if_indextoname( arg1: ::std::os::raw::c_uint, arg2: *mut ::std::os::raw::c_char, ) -> *mut ::std::os::raw::c_char; } unsafe extern "C" { pub fn if_nameindex() -> *mut if_nameindex; } unsafe extern "C" { pub fn if_nametoindex(arg1: *const ::std::os::raw::c_char) -> ::std::os::raw::c_uint; } #[repr(C, packed)] #[derive(Debug, Copy, Clone)] pub struct ether_header { pub ether_dhost: [u_char; 6usize], pub ether_shost: [u_char; 6usize], pub ether_type: u_short, } #[test] fn bindgen_test_layout_ether_header() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 14usize, concat!("Size of: ", stringify!(ether_header)) ); assert_eq!( ::std::mem::align_of::(), 1usize, concat!("Alignment of ", stringify!(ether_header)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ether_dhost) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(ether_header), "::", stringify!(ether_dhost) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ether_shost) as usize - ptr as usize }, 6usize, concat!( "Offset of field: ", stringify!(ether_header), "::", stringify!(ether_shost) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ether_type) as usize - ptr as usize }, 12usize, concat!( "Offset of field: ", stringify!(ether_header), "::", stringify!(ether_type) ) ); } #[repr(C, packed)] #[derive(Debug, Copy, Clone)] pub struct ether_addr { pub octet: [u_char; 6usize], } #[test] fn bindgen_test_layout_ether_addr() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 6usize, concat!("Size of: ", stringify!(ether_addr)) ); assert_eq!( ::std::mem::align_of::(), 1usize, concat!("Alignment of ", stringify!(ether_addr)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).octet) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(ether_addr), "::", stringify!(octet)) ); } #[repr(C, packed)] #[derive(Debug, Copy, Clone)] pub struct ether_vlan_header { pub evl_dhost: [u8; 6usize], pub evl_shost: [u8; 6usize], pub evl_encap_proto: u16, pub evl_tag: u16, pub evl_proto: u16, } #[test] fn bindgen_test_layout_ether_vlan_header() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 18usize, concat!("Size of: ", stringify!(ether_vlan_header)) ); assert_eq!( ::std::mem::align_of::(), 1usize, concat!("Alignment of ", stringify!(ether_vlan_header)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).evl_dhost) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(ether_vlan_header), "::", stringify!(evl_dhost) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).evl_shost) as usize - ptr as usize }, 6usize, concat!( "Offset of field: ", stringify!(ether_vlan_header), "::", stringify!(evl_shost) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).evl_encap_proto) as usize - ptr as usize }, 12usize, concat!( "Offset of field: ", stringify!(ether_vlan_header), "::", stringify!(evl_encap_proto) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).evl_tag) as usize - ptr as usize }, 14usize, concat!( "Offset of field: ", stringify!(ether_vlan_header), "::", stringify!(evl_tag) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).evl_proto) as usize - ptr as usize }, 16usize, concat!( "Offset of field: ", stringify!(ether_vlan_header), "::", stringify!(evl_proto) ) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct mbuf { _unused: [u8; 0], } unsafe extern "C" { pub fn ether_bpf_mtap_if(ifp: *mut ifnet, m: *mut mbuf); } unsafe extern "C" { pub fn ether_aton(arg1: *const ::std::os::raw::c_char) -> *mut ether_addr; } unsafe extern "C" { pub fn ether_aton_r(arg1: *const ::std::os::raw::c_char, arg2: *mut ether_addr) -> *mut ether_addr; } unsafe extern "C" { pub fn ether_hostton(arg1: *const ::std::os::raw::c_char, arg2: *mut ether_addr) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn ether_line( arg1: *const ::std::os::raw::c_char, arg2: *mut ether_addr, arg3: *mut ::std::os::raw::c_char, ) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn ether_ntoa(arg1: *const ether_addr) -> *mut ::std::os::raw::c_char; } unsafe extern "C" { pub fn ether_ntoa_r(arg1: *const ether_addr, arg2: *mut ::std::os::raw::c_char) -> *mut ::std::os::raw::c_char; } unsafe extern "C" { pub fn ether_ntohost(arg1: *mut ::std::os::raw::c_char, arg2: *const ether_addr) -> ::std::os::raw::c_int; } #[repr(C)] #[derive(Copy, Clone)] pub struct radix_node { pub rn_mklist: *mut radix_mask, pub rn_parent: *mut radix_node, pub rn_bit: ::std::os::raw::c_short, pub rn_bmask: ::std::os::raw::c_char, pub rn_flags: u_char, pub rn_u: radix_node__bindgen_ty_1, } #[repr(C)] #[derive(Copy, Clone)] pub union radix_node__bindgen_ty_1 { pub rn_leaf: radix_node__bindgen_ty_1__bindgen_ty_1, pub rn_node: radix_node__bindgen_ty_1__bindgen_ty_2, } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct radix_node__bindgen_ty_1__bindgen_ty_1 { pub rn_Key: caddr_t, pub rn_Mask: caddr_t, pub rn_Dupedkey: *mut radix_node, } #[test] fn bindgen_test_layout_radix_node__bindgen_ty_1__bindgen_ty_1() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 24usize, concat!("Size of: ", stringify!(radix_node__bindgen_ty_1__bindgen_ty_1)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(radix_node__bindgen_ty_1__bindgen_ty_1)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rn_Key) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(radix_node__bindgen_ty_1__bindgen_ty_1), "::", stringify!(rn_Key) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rn_Mask) as usize - ptr as usize }, 8usize, concat!( "Offset of field: ", stringify!(radix_node__bindgen_ty_1__bindgen_ty_1), "::", stringify!(rn_Mask) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rn_Dupedkey) as usize - ptr as usize }, 16usize, concat!( "Offset of field: ", stringify!(radix_node__bindgen_ty_1__bindgen_ty_1), "::", stringify!(rn_Dupedkey) ) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct radix_node__bindgen_ty_1__bindgen_ty_2 { pub rn_Off: ::std::os::raw::c_int, pub rn_L: *mut radix_node, pub rn_R: *mut radix_node, } #[test] fn bindgen_test_layout_radix_node__bindgen_ty_1__bindgen_ty_2() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 24usize, concat!("Size of: ", stringify!(radix_node__bindgen_ty_1__bindgen_ty_2)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(radix_node__bindgen_ty_1__bindgen_ty_2)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rn_Off) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(radix_node__bindgen_ty_1__bindgen_ty_2), "::", stringify!(rn_Off) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rn_L) as usize - ptr as usize }, 8usize, concat!( "Offset of field: ", stringify!(radix_node__bindgen_ty_1__bindgen_ty_2), "::", stringify!(rn_L) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rn_R) as usize - ptr as usize }, 16usize, concat!( "Offset of field: ", stringify!(radix_node__bindgen_ty_1__bindgen_ty_2), "::", stringify!(rn_R) ) ); } #[test] fn bindgen_test_layout_radix_node__bindgen_ty_1() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 24usize, concat!("Size of: ", stringify!(radix_node__bindgen_ty_1)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(radix_node__bindgen_ty_1)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rn_leaf) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(radix_node__bindgen_ty_1), "::", stringify!(rn_leaf) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rn_node) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(radix_node__bindgen_ty_1), "::", stringify!(rn_node) ) ); } #[test] fn bindgen_test_layout_radix_node() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 48usize, concat!("Size of: ", stringify!(radix_node)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(radix_node)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rn_mklist) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(radix_node), "::", stringify!(rn_mklist)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rn_parent) as usize - ptr as usize }, 8usize, concat!("Offset of field: ", stringify!(radix_node), "::", stringify!(rn_parent)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rn_bit) as usize - ptr as usize }, 16usize, concat!("Offset of field: ", stringify!(radix_node), "::", stringify!(rn_bit)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rn_bmask) as usize - ptr as usize }, 18usize, concat!("Offset of field: ", stringify!(radix_node), "::", stringify!(rn_bmask)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rn_flags) as usize - ptr as usize }, 19usize, concat!("Offset of field: ", stringify!(radix_node), "::", stringify!(rn_flags)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rn_u) as usize - ptr as usize }, 24usize, concat!("Offset of field: ", stringify!(radix_node), "::", stringify!(rn_u)) ); } #[repr(C)] #[derive(Copy, Clone)] pub struct radix_mask { pub rm_bit: ::std::os::raw::c_short, pub rm_unused: ::std::os::raw::c_char, pub rm_flags: u_char, pub rm_mklist: *mut radix_mask, pub rm_rmu: radix_mask__bindgen_ty_1, pub rm_refs: ::std::os::raw::c_int, } #[repr(C)] #[derive(Copy, Clone)] pub union radix_mask__bindgen_ty_1 { pub rmu_mask: caddr_t, pub rmu_leaf: *mut radix_node, } #[test] fn bindgen_test_layout_radix_mask__bindgen_ty_1() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 8usize, concat!("Size of: ", stringify!(radix_mask__bindgen_ty_1)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(radix_mask__bindgen_ty_1)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rmu_mask) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(radix_mask__bindgen_ty_1), "::", stringify!(rmu_mask) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rmu_leaf) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(radix_mask__bindgen_ty_1), "::", stringify!(rmu_leaf) ) ); } #[test] fn bindgen_test_layout_radix_mask() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 32usize, concat!("Size of: ", stringify!(radix_mask)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(radix_mask)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rm_bit) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(radix_mask), "::", stringify!(rm_bit)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rm_unused) as usize - ptr as usize }, 2usize, concat!("Offset of field: ", stringify!(radix_mask), "::", stringify!(rm_unused)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rm_flags) as usize - ptr as usize }, 3usize, concat!("Offset of field: ", stringify!(radix_mask), "::", stringify!(rm_flags)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rm_mklist) as usize - ptr as usize }, 8usize, concat!("Offset of field: ", stringify!(radix_mask), "::", stringify!(rm_mklist)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rm_rmu) as usize - ptr as usize }, 16usize, concat!("Offset of field: ", stringify!(radix_mask), "::", stringify!(rm_rmu)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rm_refs) as usize - ptr as usize }, 24usize, concat!("Offset of field: ", stringify!(radix_mask), "::", stringify!(rm_refs)) ); } pub type walktree_f_t = ::std::option::Option< unsafe extern "C" fn(arg1: *mut radix_node, arg2: *mut ::std::os::raw::c_void) -> ::std::os::raw::c_int, >; pub type rn_matchaddr_f_t = ::std::option::Option< unsafe extern "C" fn(v: *const ::std::os::raw::c_void, head: *mut radix_head) -> *mut radix_node, >; pub type rn_addaddr_f_t = ::std::option::Option< unsafe extern "C" fn( v: *mut ::std::os::raw::c_void, mask: *const ::std::os::raw::c_void, head: *mut radix_head, nodes: *mut radix_node, ) -> *mut radix_node, >; pub type rn_deladdr_f_t = ::std::option::Option< unsafe extern "C" fn( v: *const ::std::os::raw::c_void, mask: *const ::std::os::raw::c_void, head: *mut radix_head, ) -> *mut radix_node, >; pub type rn_lookup_f_t = ::std::option::Option< unsafe extern "C" fn( v: *const ::std::os::raw::c_void, mask: *const ::std::os::raw::c_void, head: *mut radix_head, ) -> *mut radix_node, >; pub type rn_walktree_t = ::std::option::Option< unsafe extern "C" fn( head: *mut radix_head, f: walktree_f_t, w: *mut ::std::os::raw::c_void, ) -> ::std::os::raw::c_int, >; pub type rn_walktree_from_t = ::std::option::Option< unsafe extern "C" fn( head: *mut radix_head, a: *mut ::std::os::raw::c_void, m: *mut ::std::os::raw::c_void, f: walktree_f_t, w: *mut ::std::os::raw::c_void, ) -> ::std::os::raw::c_int, >; pub type rn_close_t = ::std::option::Option; unsafe extern "C" { pub fn rn_nextprefix(rn: *mut radix_node) -> *mut radix_node; } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct radix_head { pub rnh_treetop: *mut radix_node, pub rnh_masks: *mut radix_mask_head, } #[test] fn bindgen_test_layout_radix_head() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 16usize, concat!("Size of: ", stringify!(radix_head)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(radix_head)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rnh_treetop) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(radix_head), "::", stringify!(rnh_treetop) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rnh_masks) as usize - ptr as usize }, 8usize, concat!("Offset of field: ", stringify!(radix_head), "::", stringify!(rnh_masks)) ); } #[repr(C)] #[derive(Copy, Clone)] pub struct radix_node_head { pub rh: radix_head, pub rnh_matchaddr: rn_matchaddr_f_t, pub rnh_addaddr: rn_addaddr_f_t, pub rnh_deladdr: rn_deladdr_f_t, pub rnh_lookup: rn_lookup_f_t, pub rnh_walktree: rn_walktree_t, pub rnh_walktree_from: rn_walktree_from_t, pub rnh_close: rn_close_t, pub rnh_nodes: [radix_node; 3usize], } #[test] fn bindgen_test_layout_radix_node_head() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 216usize, concat!("Size of: ", stringify!(radix_node_head)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(radix_node_head)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rh) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(radix_node_head), "::", stringify!(rh)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rnh_matchaddr) as usize - ptr as usize }, 16usize, concat!( "Offset of field: ", stringify!(radix_node_head), "::", stringify!(rnh_matchaddr) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rnh_addaddr) as usize - ptr as usize }, 24usize, concat!( "Offset of field: ", stringify!(radix_node_head), "::", stringify!(rnh_addaddr) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rnh_deladdr) as usize - ptr as usize }, 32usize, concat!( "Offset of field: ", stringify!(radix_node_head), "::", stringify!(rnh_deladdr) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rnh_lookup) as usize - ptr as usize }, 40usize, concat!( "Offset of field: ", stringify!(radix_node_head), "::", stringify!(rnh_lookup) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rnh_walktree) as usize - ptr as usize }, 48usize, concat!( "Offset of field: ", stringify!(radix_node_head), "::", stringify!(rnh_walktree) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rnh_walktree_from) as usize - ptr as usize }, 56usize, concat!( "Offset of field: ", stringify!(radix_node_head), "::", stringify!(rnh_walktree_from) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rnh_close) as usize - ptr as usize }, 64usize, concat!( "Offset of field: ", stringify!(radix_node_head), "::", stringify!(rnh_close) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rnh_nodes) as usize - ptr as usize }, 72usize, concat!( "Offset of field: ", stringify!(radix_node_head), "::", stringify!(rnh_nodes) ) ); } #[repr(C)] #[derive(Copy, Clone)] pub struct radix_mask_head { pub head: radix_head, pub mask_nodes: [radix_node; 3usize], } #[test] fn bindgen_test_layout_radix_mask_head() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 160usize, concat!("Size of: ", stringify!(radix_mask_head)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(radix_mask_head)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).head) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(radix_mask_head), "::", stringify!(head)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).mask_nodes) as usize - ptr as usize }, 16usize, concat!( "Offset of field: ", stringify!(radix_mask_head), "::", stringify!(mask_nodes) ) ); } unsafe extern "C" { pub fn rn_inithead_internal(rh: *mut radix_head, base_nodes: *mut radix_node, off: ::std::os::raw::c_int); } unsafe extern "C" { pub fn rn_inithead(arg1: *mut *mut ::std::os::raw::c_void, arg2: ::std::os::raw::c_int) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn rn_detachhead(arg1: *mut *mut ::std::os::raw::c_void) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn rn_refines( arg1: *const ::std::os::raw::c_void, arg2: *const ::std::os::raw::c_void, ) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn rn_addroute( arg1: *mut ::std::os::raw::c_void, arg2: *const ::std::os::raw::c_void, arg3: *mut radix_head, arg4: *mut radix_node, ) -> *mut radix_node; } unsafe extern "C" { pub fn rn_delete( arg1: *const ::std::os::raw::c_void, arg2: *const ::std::os::raw::c_void, arg3: *mut radix_head, ) -> *mut radix_node; } unsafe extern "C" { pub fn rn_lookup( v_arg: *const ::std::os::raw::c_void, m_arg: *const ::std::os::raw::c_void, head: *mut radix_head, ) -> *mut radix_node; } unsafe extern "C" { pub fn rn_match(arg1: *const ::std::os::raw::c_void, arg2: *mut radix_head) -> *mut radix_node; } unsafe extern "C" { pub fn rn_walktree_from( h: *mut radix_head, a: *mut ::std::os::raw::c_void, m: *mut ::std::os::raw::c_void, f: walktree_f_t, w: *mut ::std::os::raw::c_void, ) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn rn_walktree( arg1: *mut radix_head, arg2: walktree_f_t, arg3: *mut ::std::os::raw::c_void, ) -> ::std::os::raw::c_int; } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct in_addr { pub s_addr: in_addr_t, } #[test] fn bindgen_test_layout_in_addr() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 4usize, concat!("Size of: ", stringify!(in_addr)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(in_addr)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).s_addr) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(in_addr), "::", stringify!(s_addr)) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct sockaddr_in { pub sin_len: u8, pub sin_family: sa_family_t, pub sin_port: in_port_t, pub sin_addr: in_addr, pub sin_zero: [::std::os::raw::c_char; 8usize], } #[test] fn bindgen_test_layout_sockaddr_in() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 16usize, concat!("Size of: ", stringify!(sockaddr_in)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(sockaddr_in)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).sin_len) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(sockaddr_in), "::", stringify!(sin_len)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).sin_family) as usize - ptr as usize }, 1usize, concat!( "Offset of field: ", stringify!(sockaddr_in), "::", stringify!(sin_family) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).sin_port) as usize - ptr as usize }, 2usize, concat!("Offset of field: ", stringify!(sockaddr_in), "::", stringify!(sin_port)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).sin_addr) as usize - ptr as usize }, 4usize, concat!("Offset of field: ", stringify!(sockaddr_in), "::", stringify!(sin_addr)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).sin_zero) as usize - ptr as usize }, 8usize, concat!("Offset of field: ", stringify!(sockaddr_in), "::", stringify!(sin_zero)) ); } unsafe extern "C" { pub fn htonl(arg1: u32) -> u32; } unsafe extern "C" { pub fn htons(arg1: u16) -> u16; } unsafe extern "C" { pub fn ntohl(arg1: u32) -> u32; } unsafe extern "C" { pub fn ntohs(arg1: u16) -> u16; } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct ip_mreq { pub imr_multiaddr: in_addr, pub imr_interface: in_addr, } #[test] fn bindgen_test_layout_ip_mreq() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 8usize, concat!("Size of: ", stringify!(ip_mreq)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(ip_mreq)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).imr_multiaddr) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(ip_mreq), "::", stringify!(imr_multiaddr) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).imr_interface) as usize - ptr as usize }, 4usize, concat!( "Offset of field: ", stringify!(ip_mreq), "::", stringify!(imr_interface) ) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct ip_mreqn { pub imr_multiaddr: in_addr, pub imr_address: in_addr, pub imr_ifindex: ::std::os::raw::c_int, } #[test] fn bindgen_test_layout_ip_mreqn() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 12usize, concat!("Size of: ", stringify!(ip_mreqn)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(ip_mreqn)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).imr_multiaddr) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(ip_mreqn), "::", stringify!(imr_multiaddr) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).imr_address) as usize - ptr as usize }, 4usize, concat!("Offset of field: ", stringify!(ip_mreqn), "::", stringify!(imr_address)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).imr_ifindex) as usize - ptr as usize }, 8usize, concat!("Offset of field: ", stringify!(ip_mreqn), "::", stringify!(imr_ifindex)) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct ip_mreq_source { pub imr_multiaddr: in_addr, pub imr_sourceaddr: in_addr, pub imr_interface: in_addr, } #[test] fn bindgen_test_layout_ip_mreq_source() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 12usize, concat!("Size of: ", stringify!(ip_mreq_source)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(ip_mreq_source)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).imr_multiaddr) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(ip_mreq_source), "::", stringify!(imr_multiaddr) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).imr_sourceaddr) as usize - ptr as usize }, 4usize, concat!( "Offset of field: ", stringify!(ip_mreq_source), "::", stringify!(imr_sourceaddr) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).imr_interface) as usize - ptr as usize }, 8usize, concat!( "Offset of field: ", stringify!(ip_mreq_source), "::", stringify!(imr_interface) ) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct group_req { pub gr_interface: u32, pub gr_group: sockaddr_storage, } #[test] fn bindgen_test_layout_group_req() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 136usize, concat!("Size of: ", stringify!(group_req)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(group_req)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).gr_interface) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(group_req), "::", stringify!(gr_interface) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).gr_group) as usize - ptr as usize }, 8usize, concat!("Offset of field: ", stringify!(group_req), "::", stringify!(gr_group)) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct group_source_req { pub gsr_interface: u32, pub gsr_group: sockaddr_storage, pub gsr_source: sockaddr_storage, } #[test] fn bindgen_test_layout_group_source_req() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 264usize, concat!("Size of: ", stringify!(group_source_req)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(group_source_req)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).gsr_interface) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(group_source_req), "::", stringify!(gsr_interface) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).gsr_group) as usize - ptr as usize }, 8usize, concat!( "Offset of field: ", stringify!(group_source_req), "::", stringify!(gsr_group) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).gsr_source) as usize - ptr as usize }, 136usize, concat!( "Offset of field: ", stringify!(group_source_req), "::", stringify!(gsr_source) ) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct __msfilterreq { pub msfr_ifindex: u32, pub msfr_fmode: u32, pub msfr_nsrcs: u32, pub msfr_group: sockaddr_storage, pub msfr_srcs: *mut sockaddr_storage, } #[test] fn bindgen_test_layout___msfilterreq() { const UNINIT: ::std::mem::MaybeUninit<__msfilterreq> = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::<__msfilterreq>(), 152usize, concat!("Size of: ", stringify!(__msfilterreq)) ); assert_eq!( ::std::mem::align_of::<__msfilterreq>(), 8usize, concat!("Alignment of ", stringify!(__msfilterreq)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).msfr_ifindex) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(__msfilterreq), "::", stringify!(msfr_ifindex) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).msfr_fmode) as usize - ptr as usize }, 4usize, concat!( "Offset of field: ", stringify!(__msfilterreq), "::", stringify!(msfr_fmode) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).msfr_nsrcs) as usize - ptr as usize }, 8usize, concat!( "Offset of field: ", stringify!(__msfilterreq), "::", stringify!(msfr_nsrcs) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).msfr_group) as usize - ptr as usize }, 16usize, concat!( "Offset of field: ", stringify!(__msfilterreq), "::", stringify!(msfr_group) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).msfr_srcs) as usize - ptr as usize }, 144usize, concat!( "Offset of field: ", stringify!(__msfilterreq), "::", stringify!(msfr_srcs) ) ); } unsafe extern "C" { pub fn setipv4sourcefilter( arg1: ::std::os::raw::c_int, arg2: in_addr, arg3: in_addr, arg4: u32, arg5: u32, arg6: *mut in_addr, ) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn getipv4sourcefilter( arg1: ::std::os::raw::c_int, arg2: in_addr, arg3: in_addr, arg4: *mut u32, arg5: *mut u32, arg6: *mut in_addr, ) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn setsourcefilter( arg1: ::std::os::raw::c_int, arg2: u32, arg3: *mut sockaddr, arg4: socklen_t, arg5: u32, arg6: u32, arg7: *mut sockaddr_storage, ) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn getsourcefilter( arg1: ::std::os::raw::c_int, arg2: u32, arg3: *mut sockaddr, arg4: socklen_t, arg5: *mut u32, arg6: *mut u32, arg7: *mut sockaddr_storage, ) -> ::std::os::raw::c_int; } #[repr(C)] #[derive(Copy, Clone)] pub struct in6_addr { pub __u6_addr: in6_addr__bindgen_ty_1, } #[repr(C)] #[derive(Copy, Clone)] pub union in6_addr__bindgen_ty_1 { pub __u6_addr8: [u8; 16usize], pub __u6_addr16: [u16; 8usize], pub __u6_addr32: [u32; 4usize], } #[test] fn bindgen_test_layout_in6_addr__bindgen_ty_1() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 16usize, concat!("Size of: ", stringify!(in6_addr__bindgen_ty_1)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(in6_addr__bindgen_ty_1)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__u6_addr8) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(in6_addr__bindgen_ty_1), "::", stringify!(__u6_addr8) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__u6_addr16) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(in6_addr__bindgen_ty_1), "::", stringify!(__u6_addr16) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__u6_addr32) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(in6_addr__bindgen_ty_1), "::", stringify!(__u6_addr32) ) ); } #[test] fn bindgen_test_layout_in6_addr() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 16usize, concat!("Size of: ", stringify!(in6_addr)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(in6_addr)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__u6_addr) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(in6_addr), "::", stringify!(__u6_addr)) ); } #[repr(C)] #[derive(Copy, Clone)] pub struct sockaddr_in6 { pub sin6_len: u8, pub sin6_family: sa_family_t, pub sin6_port: in_port_t, pub sin6_flowinfo: u32, pub sin6_addr: in6_addr, pub sin6_scope_id: u32, } #[test] fn bindgen_test_layout_sockaddr_in6() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 28usize, concat!("Size of: ", stringify!(sockaddr_in6)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(sockaddr_in6)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).sin6_len) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(sockaddr_in6), "::", stringify!(sin6_len) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).sin6_family) as usize - ptr as usize }, 1usize, concat!( "Offset of field: ", stringify!(sockaddr_in6), "::", stringify!(sin6_family) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).sin6_port) as usize - ptr as usize }, 2usize, concat!( "Offset of field: ", stringify!(sockaddr_in6), "::", stringify!(sin6_port) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).sin6_flowinfo) as usize - ptr as usize }, 4usize, concat!( "Offset of field: ", stringify!(sockaddr_in6), "::", stringify!(sin6_flowinfo) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).sin6_addr) as usize - ptr as usize }, 8usize, concat!( "Offset of field: ", stringify!(sockaddr_in6), "::", stringify!(sin6_addr) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).sin6_scope_id) as usize - ptr as usize }, 24usize, concat!( "Offset of field: ", stringify!(sockaddr_in6), "::", stringify!(sin6_scope_id) ) ); } unsafe extern "C" { pub static in6addr_any: in6_addr; } unsafe extern "C" { pub static in6addr_loopback: in6_addr; } unsafe extern "C" { pub static in6addr_nodelocal_allnodes: in6_addr; } unsafe extern "C" { pub static in6addr_linklocal_allnodes: in6_addr; } unsafe extern "C" { pub static in6addr_linklocal_allrouters: in6_addr; } unsafe extern "C" { pub static in6addr_linklocal_allv2routers: in6_addr; } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct nhop_object { _unused: [u8; 0], } #[repr(C)] #[derive(Copy, Clone)] pub struct route_in6 { pub ro_nh: *mut nhop_object, pub ro_lle: *mut llentry, pub ro_prepend: *mut ::std::os::raw::c_char, pub ro_plen: u16, pub ro_flags: u16, pub ro_mtu: u16, pub spare: u16, pub ro_dst: sockaddr_in6, } #[test] fn bindgen_test_layout_route_in6() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 64usize, concat!("Size of: ", stringify!(route_in6)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(route_in6)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ro_nh) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(route_in6), "::", stringify!(ro_nh)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ro_lle) as usize - ptr as usize }, 8usize, concat!("Offset of field: ", stringify!(route_in6), "::", stringify!(ro_lle)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ro_prepend) as usize - ptr as usize }, 16usize, concat!("Offset of field: ", stringify!(route_in6), "::", stringify!(ro_prepend)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ro_plen) as usize - ptr as usize }, 24usize, concat!("Offset of field: ", stringify!(route_in6), "::", stringify!(ro_plen)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ro_flags) as usize - ptr as usize }, 26usize, concat!("Offset of field: ", stringify!(route_in6), "::", stringify!(ro_flags)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ro_mtu) as usize - ptr as usize }, 28usize, concat!("Offset of field: ", stringify!(route_in6), "::", stringify!(ro_mtu)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).spare) as usize - ptr as usize }, 30usize, concat!("Offset of field: ", stringify!(route_in6), "::", stringify!(spare)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ro_dst) as usize - ptr as usize }, 32usize, concat!("Offset of field: ", stringify!(route_in6), "::", stringify!(ro_dst)) ); } #[repr(C)] #[derive(Copy, Clone)] pub struct ipv6_mreq { pub ipv6mr_multiaddr: in6_addr, pub ipv6mr_interface: ::std::os::raw::c_uint, } #[test] fn bindgen_test_layout_ipv6_mreq() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 20usize, concat!("Size of: ", stringify!(ipv6_mreq)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(ipv6_mreq)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ipv6mr_multiaddr) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(ipv6_mreq), "::", stringify!(ipv6mr_multiaddr) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ipv6mr_interface) as usize - ptr as usize }, 16usize, concat!( "Offset of field: ", stringify!(ipv6_mreq), "::", stringify!(ipv6mr_interface) ) ); } #[repr(C)] #[derive(Copy, Clone)] pub struct in6_pktinfo { pub ipi6_addr: in6_addr, pub ipi6_ifindex: ::std::os::raw::c_uint, } #[test] fn bindgen_test_layout_in6_pktinfo() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 20usize, concat!("Size of: ", stringify!(in6_pktinfo)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(in6_pktinfo)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ipi6_addr) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(in6_pktinfo), "::", stringify!(ipi6_addr) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ipi6_ifindex) as usize - ptr as usize }, 16usize, concat!( "Offset of field: ", stringify!(in6_pktinfo), "::", stringify!(ipi6_ifindex) ) ); } #[repr(C)] #[derive(Copy, Clone)] pub struct ip6_mtuinfo { pub ip6m_addr: sockaddr_in6, pub ip6m_mtu: u32, } #[test] fn bindgen_test_layout_ip6_mtuinfo() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 32usize, concat!("Size of: ", stringify!(ip6_mtuinfo)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(ip6_mtuinfo)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ip6m_addr) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(ip6_mtuinfo), "::", stringify!(ip6m_addr) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ip6m_mtu) as usize - ptr as usize }, 28usize, concat!("Offset of field: ", stringify!(ip6_mtuinfo), "::", stringify!(ip6m_mtu)) ); } unsafe extern "C" { pub fn inet6_option_space(arg1: ::std::os::raw::c_int) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn inet6_option_init( arg1: *mut ::std::os::raw::c_void, arg2: *mut *mut cmsghdr, arg3: ::std::os::raw::c_int, ) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn inet6_option_append( arg1: *mut cmsghdr, arg2: *const u8, arg3: ::std::os::raw::c_int, arg4: ::std::os::raw::c_int, ) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn inet6_option_alloc( arg1: *mut cmsghdr, arg2: ::std::os::raw::c_int, arg3: ::std::os::raw::c_int, arg4: ::std::os::raw::c_int, ) -> *mut u8; } unsafe extern "C" { pub fn inet6_option_next(arg1: *const cmsghdr, arg2: *mut *mut u8) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn inet6_option_find( arg1: *const cmsghdr, arg2: *mut *mut u8, arg3: ::std::os::raw::c_int, ) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn inet6_rthdr_space(arg1: ::std::os::raw::c_int, arg2: ::std::os::raw::c_int) -> usize; } unsafe extern "C" { pub fn inet6_rthdr_init(arg1: *mut ::std::os::raw::c_void, arg2: ::std::os::raw::c_int) -> *mut cmsghdr; } unsafe extern "C" { pub fn inet6_rthdr_add( arg1: *mut cmsghdr, arg2: *const in6_addr, arg3: ::std::os::raw::c_uint, ) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn inet6_rthdr_lasthop(arg1: *mut cmsghdr, arg2: ::std::os::raw::c_uint) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn inet6_rthdr_segments(arg1: *const cmsghdr) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn inet6_rthdr_getaddr(arg1: *mut cmsghdr, arg2: ::std::os::raw::c_int) -> *mut in6_addr; } unsafe extern "C" { pub fn inet6_rthdr_getflags(arg1: *const cmsghdr, arg2: ::std::os::raw::c_int) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn inet6_opt_init(arg1: *mut ::std::os::raw::c_void, arg2: socklen_t) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn inet6_opt_append( arg1: *mut ::std::os::raw::c_void, arg2: socklen_t, arg3: ::std::os::raw::c_int, arg4: u8, arg5: socklen_t, arg6: u8, arg7: *mut *mut ::std::os::raw::c_void, ) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn inet6_opt_finish( arg1: *mut ::std::os::raw::c_void, arg2: socklen_t, arg3: ::std::os::raw::c_int, ) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn inet6_opt_set_val( arg1: *mut ::std::os::raw::c_void, arg2: ::std::os::raw::c_int, arg3: *mut ::std::os::raw::c_void, arg4: socklen_t, ) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn inet6_opt_next( arg1: *mut ::std::os::raw::c_void, arg2: socklen_t, arg3: ::std::os::raw::c_int, arg4: *mut u8, arg5: *mut socklen_t, arg6: *mut *mut ::std::os::raw::c_void, ) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn inet6_opt_find( arg1: *mut ::std::os::raw::c_void, arg2: socklen_t, arg3: ::std::os::raw::c_int, arg4: u8, arg5: *mut socklen_t, arg6: *mut *mut ::std::os::raw::c_void, ) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn inet6_opt_get_val( arg1: *mut ::std::os::raw::c_void, arg2: ::std::os::raw::c_int, arg3: *mut ::std::os::raw::c_void, arg4: socklen_t, ) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn inet6_rth_space(arg1: ::std::os::raw::c_int, arg2: ::std::os::raw::c_int) -> socklen_t; } unsafe extern "C" { pub fn inet6_rth_init( arg1: *mut ::std::os::raw::c_void, arg2: socklen_t, arg3: ::std::os::raw::c_int, arg4: ::std::os::raw::c_int, ) -> *mut ::std::os::raw::c_void; } unsafe extern "C" { pub fn inet6_rth_add(arg1: *mut ::std::os::raw::c_void, arg2: *const in6_addr) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn inet6_rth_reverse( arg1: *const ::std::os::raw::c_void, arg2: *mut ::std::os::raw::c_void, ) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn inet6_rth_segments(arg1: *const ::std::os::raw::c_void) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn inet6_rth_getaddr(arg1: *const ::std::os::raw::c_void, arg2: ::std::os::raw::c_int) -> *mut in6_addr; } pub const PF_INOUT: _bindgen_ty_1 = 0; pub const PF_IN: _bindgen_ty_1 = 1; pub const PF_OUT: _bindgen_ty_1 = 2; pub type _bindgen_ty_1 = ::std::os::raw::c_uint; pub const PF_PASS: _bindgen_ty_2 = 0; pub const PF_DROP: _bindgen_ty_2 = 1; pub const PF_SCRUB: _bindgen_ty_2 = 2; pub const PF_NOSCRUB: _bindgen_ty_2 = 3; pub const PF_NAT: _bindgen_ty_2 = 4; pub const PF_NONAT: _bindgen_ty_2 = 5; pub const PF_BINAT: _bindgen_ty_2 = 6; pub const PF_NOBINAT: _bindgen_ty_2 = 7; pub const PF_RDR: _bindgen_ty_2 = 8; pub const PF_NORDR: _bindgen_ty_2 = 9; pub const PF_SYNPROXY_DROP: _bindgen_ty_2 = 10; pub const PF_DEFER: _bindgen_ty_2 = 11; pub const PF_MATCH: _bindgen_ty_2 = 12; pub type _bindgen_ty_2 = ::std::os::raw::c_uint; pub const PF_RULESET_SCRUB: _bindgen_ty_3 = 0; pub const PF_RULESET_FILTER: _bindgen_ty_3 = 1; pub const PF_RULESET_NAT: _bindgen_ty_3 = 2; pub const PF_RULESET_BINAT: _bindgen_ty_3 = 3; pub const PF_RULESET_RDR: _bindgen_ty_3 = 4; pub const PF_RULESET_MAX: _bindgen_ty_3 = 5; pub type _bindgen_ty_3 = ::std::os::raw::c_uint; pub const PF_OP_NONE: _bindgen_ty_4 = 0; pub const PF_OP_IRG: _bindgen_ty_4 = 1; pub const PF_OP_EQ: _bindgen_ty_4 = 2; pub const PF_OP_NE: _bindgen_ty_4 = 3; pub const PF_OP_LT: _bindgen_ty_4 = 4; pub const PF_OP_LE: _bindgen_ty_4 = 5; pub const PF_OP_GT: _bindgen_ty_4 = 6; pub const PF_OP_GE: _bindgen_ty_4 = 7; pub const PF_OP_XRG: _bindgen_ty_4 = 8; pub const PF_OP_RRG: _bindgen_ty_4 = 9; pub type _bindgen_ty_4 = ::std::os::raw::c_uint; pub const PF_DEBUG_NONE: _bindgen_ty_5 = 0; pub const PF_DEBUG_URGENT: _bindgen_ty_5 = 1; pub const PF_DEBUG_MISC: _bindgen_ty_5 = 2; pub const PF_DEBUG_NOISY: _bindgen_ty_5 = 3; pub type _bindgen_ty_5 = ::std::os::raw::c_uint; pub const PF_CHANGE_NONE: _bindgen_ty_6 = 0; pub const PF_CHANGE_ADD_HEAD: _bindgen_ty_6 = 1; pub const PF_CHANGE_ADD_TAIL: _bindgen_ty_6 = 2; pub const PF_CHANGE_ADD_BEFORE: _bindgen_ty_6 = 3; pub const PF_CHANGE_ADD_AFTER: _bindgen_ty_6 = 4; pub const PF_CHANGE_REMOVE: _bindgen_ty_6 = 5; pub const PF_CHANGE_GET_TICKET: _bindgen_ty_6 = 6; pub type _bindgen_ty_6 = ::std::os::raw::c_uint; pub const PF_GET_NONE: _bindgen_ty_7 = 0; pub const PF_GET_CLR_CNTR: _bindgen_ty_7 = 1; pub type _bindgen_ty_7 = ::std::os::raw::c_uint; pub const PF_SK_WIRE: _bindgen_ty_8 = 0; pub const PF_SK_STACK: _bindgen_ty_8 = 1; pub const PF_SK_BOTH: _bindgen_ty_8 = 2; pub type _bindgen_ty_8 = ::std::os::raw::c_uint; pub const PF_PEER_SRC: _bindgen_ty_9 = 0; pub const PF_PEER_DST: _bindgen_ty_9 = 1; pub const PF_PEER_BOTH: _bindgen_ty_9 = 2; pub type _bindgen_ty_9 = ::std::os::raw::c_uint; pub const PFTM_TCP_FIRST_PACKET: _bindgen_ty_10 = 0; pub const PFTM_TCP_OPENING: _bindgen_ty_10 = 1; pub const PFTM_TCP_ESTABLISHED: _bindgen_ty_10 = 2; pub const PFTM_TCP_CLOSING: _bindgen_ty_10 = 3; pub const PFTM_TCP_FIN_WAIT: _bindgen_ty_10 = 4; pub const PFTM_TCP_CLOSED: _bindgen_ty_10 = 5; pub const PFTM_UDP_FIRST_PACKET: _bindgen_ty_10 = 6; pub const PFTM_UDP_SINGLE: _bindgen_ty_10 = 7; pub const PFTM_UDP_MULTIPLE: _bindgen_ty_10 = 8; pub const PFTM_ICMP_FIRST_PACKET: _bindgen_ty_10 = 9; pub const PFTM_ICMP_ERROR_REPLY: _bindgen_ty_10 = 10; pub const PFTM_OTHER_FIRST_PACKET: _bindgen_ty_10 = 11; pub const PFTM_OTHER_SINGLE: _bindgen_ty_10 = 12; pub const PFTM_OTHER_MULTIPLE: _bindgen_ty_10 = 13; pub const PFTM_FRAG: _bindgen_ty_10 = 14; pub const PFTM_INTERVAL: _bindgen_ty_10 = 15; pub const PFTM_ADAPTIVE_START: _bindgen_ty_10 = 16; pub const PFTM_ADAPTIVE_END: _bindgen_ty_10 = 17; pub const PFTM_SRC_NODE: _bindgen_ty_10 = 18; pub const PFTM_TS_DIFF: _bindgen_ty_10 = 19; pub const PFTM_MAX: _bindgen_ty_10 = 20; pub const PFTM_PURGE: _bindgen_ty_10 = 21; pub const PFTM_UNLINKED: _bindgen_ty_10 = 22; pub type _bindgen_ty_10 = ::std::os::raw::c_uint; pub const PF_NOPFROUTE: _bindgen_ty_11 = 0; pub const PF_FASTROUTE: _bindgen_ty_11 = 1; pub const PF_ROUTETO: _bindgen_ty_11 = 2; pub const PF_DUPTO: _bindgen_ty_11 = 3; pub const PF_REPLYTO: _bindgen_ty_11 = 4; pub type _bindgen_ty_11 = ::std::os::raw::c_uint; pub const PF_LIMIT_STATES: _bindgen_ty_12 = 0; pub const PF_LIMIT_SRC_NODES: _bindgen_ty_12 = 1; pub const PF_LIMIT_FRAGS: _bindgen_ty_12 = 2; pub const PF_LIMIT_TABLE_ENTRIES: _bindgen_ty_12 = 3; pub const PF_LIMIT_MAX: _bindgen_ty_12 = 4; pub type _bindgen_ty_12 = ::std::os::raw::c_uint; pub const PF_POOL_NONE: _bindgen_ty_13 = 0; pub const PF_POOL_BITMASK: _bindgen_ty_13 = 1; pub const PF_POOL_RANDOM: _bindgen_ty_13 = 2; pub const PF_POOL_SRCHASH: _bindgen_ty_13 = 3; pub const PF_POOL_ROUNDROBIN: _bindgen_ty_13 = 4; pub type _bindgen_ty_13 = ::std::os::raw::c_uint; pub const PF_ADDR_ADDRMASK: _bindgen_ty_14 = 0; pub const PF_ADDR_NOROUTE: _bindgen_ty_14 = 1; pub const PF_ADDR_DYNIFTL: _bindgen_ty_14 = 2; pub const PF_ADDR_TABLE: _bindgen_ty_14 = 3; pub const PF_ADDR_URPFFAILED: _bindgen_ty_14 = 4; pub const PF_ADDR_RANGE: _bindgen_ty_14 = 5; pub type _bindgen_ty_14 = ::std::os::raw::c_uint; #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pfioc_nv { pub data: *mut ::std::os::raw::c_void, pub len: usize, pub size: usize, } #[test] fn bindgen_test_layout_pfioc_nv() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 24usize, concat!("Size of: ", stringify!(pfioc_nv)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pfioc_nv)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).data) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(pfioc_nv), "::", stringify!(data)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).len) as usize - ptr as usize }, 8usize, concat!("Offset of field: ", stringify!(pfioc_nv), "::", stringify!(len)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).size) as usize - ptr as usize }, 16usize, concat!("Offset of field: ", stringify!(pfioc_nv), "::", stringify!(size)) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pfi_kif_cmp { pub pfik_name: [::std::os::raw::c_char; 16usize], } #[test] fn bindgen_test_layout_pfi_kif_cmp() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 16usize, concat!("Size of: ", stringify!(pfi_kif_cmp)) ); assert_eq!( ::std::mem::align_of::(), 1usize, concat!("Alignment of ", stringify!(pfi_kif_cmp)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfik_name) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pfi_kif_cmp), "::", stringify!(pfik_name) ) ); } #[repr(C)] #[derive(Copy, Clone)] pub struct pfi_kif { pub pfik_name: [::std::os::raw::c_char; 16usize], pub __bindgen_anon_1: pfi_kif__bindgen_ty_1, pub pfik_packets: [[[u_int64_t; 2usize]; 2usize]; 2usize], pub pfik_bytes: [[[u_int64_t; 2usize]; 2usize]; 2usize], pub pfik_tzero: u_int32_t, pub pfik_flags: u_int, pub pfik_ifp: *mut ifnet, pub pfik_group: *mut ifg_group, pub pfik_rulerefs: u_int, pub pfik_dynaddrs: pfi_kif__bindgen_ty_2, } #[repr(C)] #[derive(Copy, Clone)] pub union pfi_kif__bindgen_ty_1 { pub pfik_tree: pfi_kif__bindgen_ty_1__bindgen_ty_1, pub pfik_list: pfi_kif__bindgen_ty_1__bindgen_ty_2, } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pfi_kif__bindgen_ty_1__bindgen_ty_1 { pub rbe_link: [*mut pfi_kif; 3usize], } #[test] fn bindgen_test_layout_pfi_kif__bindgen_ty_1__bindgen_ty_1() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 24usize, concat!("Size of: ", stringify!(pfi_kif__bindgen_ty_1__bindgen_ty_1)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pfi_kif__bindgen_ty_1__bindgen_ty_1)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rbe_link) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pfi_kif__bindgen_ty_1__bindgen_ty_1), "::", stringify!(rbe_link) ) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pfi_kif__bindgen_ty_1__bindgen_ty_2 { pub le_next: *mut pfi_kif, pub le_prev: *mut *mut pfi_kif, } #[test] fn bindgen_test_layout_pfi_kif__bindgen_ty_1__bindgen_ty_2() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 16usize, concat!("Size of: ", stringify!(pfi_kif__bindgen_ty_1__bindgen_ty_2)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pfi_kif__bindgen_ty_1__bindgen_ty_2)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).le_next) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pfi_kif__bindgen_ty_1__bindgen_ty_2), "::", stringify!(le_next) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).le_prev) as usize - ptr as usize }, 8usize, concat!( "Offset of field: ", stringify!(pfi_kif__bindgen_ty_1__bindgen_ty_2), "::", stringify!(le_prev) ) ); } #[test] fn bindgen_test_layout_pfi_kif__bindgen_ty_1() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 24usize, concat!("Size of: ", stringify!(pfi_kif__bindgen_ty_1)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pfi_kif__bindgen_ty_1)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfik_tree) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pfi_kif__bindgen_ty_1), "::", stringify!(pfik_tree) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfik_list) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pfi_kif__bindgen_ty_1), "::", stringify!(pfik_list) ) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pfi_kif__bindgen_ty_2 { pub tqh_first: *mut pfi_dynaddr, pub tqh_last: *mut *mut pfi_dynaddr, } #[test] fn bindgen_test_layout_pfi_kif__bindgen_ty_2() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 16usize, concat!("Size of: ", stringify!(pfi_kif__bindgen_ty_2)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pfi_kif__bindgen_ty_2)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).tqh_first) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pfi_kif__bindgen_ty_2), "::", stringify!(tqh_first) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).tqh_last) as usize - ptr as usize }, 8usize, concat!( "Offset of field: ", stringify!(pfi_kif__bindgen_ty_2), "::", stringify!(tqh_last) ) ); } #[test] fn bindgen_test_layout_pfi_kif() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 216usize, concat!("Size of: ", stringify!(pfi_kif)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pfi_kif)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfik_name) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(pfi_kif), "::", stringify!(pfik_name)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfik_packets) as usize - ptr as usize }, 40usize, concat!("Offset of field: ", stringify!(pfi_kif), "::", stringify!(pfik_packets)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfik_bytes) as usize - ptr as usize }, 104usize, concat!("Offset of field: ", stringify!(pfi_kif), "::", stringify!(pfik_bytes)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfik_tzero) as usize - ptr as usize }, 168usize, concat!("Offset of field: ", stringify!(pfi_kif), "::", stringify!(pfik_tzero)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfik_flags) as usize - ptr as usize }, 172usize, concat!("Offset of field: ", stringify!(pfi_kif), "::", stringify!(pfik_flags)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfik_ifp) as usize - ptr as usize }, 176usize, concat!("Offset of field: ", stringify!(pfi_kif), "::", stringify!(pfik_ifp)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfik_group) as usize - ptr as usize }, 184usize, concat!("Offset of field: ", stringify!(pfi_kif), "::", stringify!(pfik_group)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfik_rulerefs) as usize - ptr as usize }, 192usize, concat!( "Offset of field: ", stringify!(pfi_kif), "::", stringify!(pfik_rulerefs) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfik_dynaddrs) as usize - ptr as usize }, 200usize, concat!( "Offset of field: ", stringify!(pfi_kif), "::", stringify!(pfik_dynaddrs) ) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pf_status { pub counters: [u64; 16usize], pub lcounters: [u64; 7usize], pub fcounters: [u64; 3usize], pub scounters: [u64; 3usize], pub pcounters: [[[u64; 3usize]; 2usize]; 2usize], pub bcounters: [[u64; 2usize]; 2usize], pub running: u32, pub states: u32, pub src_nodes: u32, pub since: u32, pub debug: u32, pub hostid: u32, pub ifname: [::std::os::raw::c_char; 16usize], pub pf_chksum: [u8; 16usize], } #[test] fn bindgen_test_layout_pf_status() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 416usize, concat!("Size of: ", stringify!(pf_status)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pf_status)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).counters) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(pf_status), "::", stringify!(counters)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).lcounters) as usize - ptr as usize }, 128usize, concat!("Offset of field: ", stringify!(pf_status), "::", stringify!(lcounters)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).fcounters) as usize - ptr as usize }, 184usize, concat!("Offset of field: ", stringify!(pf_status), "::", stringify!(fcounters)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).scounters) as usize - ptr as usize }, 208usize, concat!("Offset of field: ", stringify!(pf_status), "::", stringify!(scounters)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pcounters) as usize - ptr as usize }, 232usize, concat!("Offset of field: ", stringify!(pf_status), "::", stringify!(pcounters)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).bcounters) as usize - ptr as usize }, 328usize, concat!("Offset of field: ", stringify!(pf_status), "::", stringify!(bcounters)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).running) as usize - ptr as usize }, 360usize, concat!("Offset of field: ", stringify!(pf_status), "::", stringify!(running)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).states) as usize - ptr as usize }, 364usize, concat!("Offset of field: ", stringify!(pf_status), "::", stringify!(states)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).src_nodes) as usize - ptr as usize }, 368usize, concat!("Offset of field: ", stringify!(pf_status), "::", stringify!(src_nodes)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).since) as usize - ptr as usize }, 372usize, concat!("Offset of field: ", stringify!(pf_status), "::", stringify!(since)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).debug) as usize - ptr as usize }, 376usize, concat!("Offset of field: ", stringify!(pf_status), "::", stringify!(debug)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).hostid) as usize - ptr as usize }, 380usize, concat!("Offset of field: ", stringify!(pf_status), "::", stringify!(hostid)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifname) as usize - ptr as usize }, 384usize, concat!("Offset of field: ", stringify!(pf_status), "::", stringify!(ifname)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pf_chksum) as usize - ptr as usize }, 400usize, concat!("Offset of field: ", stringify!(pf_status), "::", stringify!(pf_chksum)) ); } #[repr(C)] #[derive(Copy, Clone)] pub struct pf_addr { pub pfa: pf_addr__bindgen_ty_1, } #[repr(C)] #[derive(Copy, Clone)] pub union pf_addr__bindgen_ty_1 { pub v4: in_addr, pub v6: in6_addr, pub addr8: [u_int8_t; 16usize], pub addr16: [u_int16_t; 8usize], pub addr32: [u_int32_t; 4usize], } #[test] fn bindgen_test_layout_pf_addr__bindgen_ty_1() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 16usize, concat!("Size of: ", stringify!(pf_addr__bindgen_ty_1)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(pf_addr__bindgen_ty_1)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).v4) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pf_addr__bindgen_ty_1), "::", stringify!(v4) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).v6) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pf_addr__bindgen_ty_1), "::", stringify!(v6) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).addr8) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pf_addr__bindgen_ty_1), "::", stringify!(addr8) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).addr16) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pf_addr__bindgen_ty_1), "::", stringify!(addr16) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).addr32) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pf_addr__bindgen_ty_1), "::", stringify!(addr32) ) ); } #[test] fn bindgen_test_layout_pf_addr() { assert_eq!( ::std::mem::size_of::(), 16usize, concat!("Size of: ", stringify!(pf_addr)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(pf_addr)) ); } #[repr(C)] #[derive(Copy, Clone)] pub struct pf_addr_wrap { pub v: pf_addr_wrap__bindgen_ty_1, pub p: pf_addr_wrap__bindgen_ty_2, pub type_: u_int8_t, pub iflags: u_int8_t, } #[repr(C)] #[derive(Copy, Clone)] pub union pf_addr_wrap__bindgen_ty_1 { pub a: pf_addr_wrap__bindgen_ty_1__bindgen_ty_1, pub ifname: [::std::os::raw::c_char; 16usize], pub tblname: [::std::os::raw::c_char; 32usize], } #[repr(C)] #[derive(Copy, Clone)] pub struct pf_addr_wrap__bindgen_ty_1__bindgen_ty_1 { pub addr: pf_addr, pub mask: pf_addr, } #[test] fn bindgen_test_layout_pf_addr_wrap__bindgen_ty_1__bindgen_ty_1() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 32usize, concat!("Size of: ", stringify!(pf_addr_wrap__bindgen_ty_1__bindgen_ty_1)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(pf_addr_wrap__bindgen_ty_1__bindgen_ty_1)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).addr) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pf_addr_wrap__bindgen_ty_1__bindgen_ty_1), "::", stringify!(addr) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).mask) as usize - ptr as usize }, 16usize, concat!( "Offset of field: ", stringify!(pf_addr_wrap__bindgen_ty_1__bindgen_ty_1), "::", stringify!(mask) ) ); } #[test] fn bindgen_test_layout_pf_addr_wrap__bindgen_ty_1() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 32usize, concat!("Size of: ", stringify!(pf_addr_wrap__bindgen_ty_1)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(pf_addr_wrap__bindgen_ty_1)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).a) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pf_addr_wrap__bindgen_ty_1), "::", stringify!(a) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifname) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pf_addr_wrap__bindgen_ty_1), "::", stringify!(ifname) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).tblname) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pf_addr_wrap__bindgen_ty_1), "::", stringify!(tblname) ) ); } #[repr(C)] #[derive(Copy, Clone)] pub union pf_addr_wrap__bindgen_ty_2 { pub dyn_: *mut pfi_dynaddr, pub tbl: *mut pfr_ktable, pub dyncnt: ::std::os::raw::c_int, pub tblcnt: ::std::os::raw::c_int, } #[test] fn bindgen_test_layout_pf_addr_wrap__bindgen_ty_2() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 8usize, concat!("Size of: ", stringify!(pf_addr_wrap__bindgen_ty_2)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pf_addr_wrap__bindgen_ty_2)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).dyn_) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pf_addr_wrap__bindgen_ty_2), "::", stringify!(dyn_) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).tbl) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pf_addr_wrap__bindgen_ty_2), "::", stringify!(tbl) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).dyncnt) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pf_addr_wrap__bindgen_ty_2), "::", stringify!(dyncnt) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).tblcnt) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pf_addr_wrap__bindgen_ty_2), "::", stringify!(tblcnt) ) ); } #[test] fn bindgen_test_layout_pf_addr_wrap() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 48usize, concat!("Size of: ", stringify!(pf_addr_wrap)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pf_addr_wrap)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).v) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(pf_addr_wrap), "::", stringify!(v)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).p) as usize - ptr as usize }, 32usize, concat!("Offset of field: ", stringify!(pf_addr_wrap), "::", stringify!(p)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).type_) as usize - ptr as usize }, 40usize, concat!("Offset of field: ", stringify!(pf_addr_wrap), "::", stringify!(type_)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).iflags) as usize - ptr as usize }, 41usize, concat!("Offset of field: ", stringify!(pf_addr_wrap), "::", stringify!(iflags)) ); } #[repr(C)] #[derive(Copy, Clone)] pub union pf_rule_ptr { pub ptr: *mut pf_rule, pub nr: u_int32_t, } #[test] fn bindgen_test_layout_pf_rule_ptr() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 8usize, concat!("Size of: ", stringify!(pf_rule_ptr)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pf_rule_ptr)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ptr) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(pf_rule_ptr), "::", stringify!(ptr)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).nr) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(pf_rule_ptr), "::", stringify!(nr)) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pf_rule_uid { pub uid: [uid_t; 2usize], pub op: u_int8_t, } #[test] fn bindgen_test_layout_pf_rule_uid() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 12usize, concat!("Size of: ", stringify!(pf_rule_uid)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(pf_rule_uid)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).uid) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(pf_rule_uid), "::", stringify!(uid)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).op) as usize - ptr as usize }, 8usize, concat!("Offset of field: ", stringify!(pf_rule_uid), "::", stringify!(op)) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pf_rule_gid { pub gid: [uid_t; 2usize], pub op: u_int8_t, } #[test] fn bindgen_test_layout_pf_rule_gid() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 12usize, concat!("Size of: ", stringify!(pf_rule_gid)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(pf_rule_gid)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).gid) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(pf_rule_gid), "::", stringify!(gid)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).op) as usize - ptr as usize }, 8usize, concat!("Offset of field: ", stringify!(pf_rule_gid), "::", stringify!(op)) ); } #[repr(C)] #[derive(Copy, Clone)] pub struct pf_rule_addr { pub addr: pf_addr_wrap, pub port: [u_int16_t; 2usize], pub neg: u_int8_t, pub port_op: u_int8_t, } #[test] fn bindgen_test_layout_pf_rule_addr() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 56usize, concat!("Size of: ", stringify!(pf_rule_addr)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pf_rule_addr)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).addr) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(pf_rule_addr), "::", stringify!(addr)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).port) as usize - ptr as usize }, 48usize, concat!("Offset of field: ", stringify!(pf_rule_addr), "::", stringify!(port)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).neg) as usize - ptr as usize }, 52usize, concat!("Offset of field: ", stringify!(pf_rule_addr), "::", stringify!(neg)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).port_op) as usize - ptr as usize }, 53usize, concat!("Offset of field: ", stringify!(pf_rule_addr), "::", stringify!(port_op)) ); } #[repr(C)] #[derive(Copy, Clone)] pub struct pf_pooladdr { pub addr: pf_addr_wrap, pub entries: pf_pooladdr__bindgen_ty_1, pub ifname: [::std::os::raw::c_char; 16usize], pub kif: *mut pfi_kif, } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pf_pooladdr__bindgen_ty_1 { pub tqe_next: *mut pf_pooladdr, pub tqe_prev: *mut *mut pf_pooladdr, } #[test] fn bindgen_test_layout_pf_pooladdr__bindgen_ty_1() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 16usize, concat!("Size of: ", stringify!(pf_pooladdr__bindgen_ty_1)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pf_pooladdr__bindgen_ty_1)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).tqe_next) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pf_pooladdr__bindgen_ty_1), "::", stringify!(tqe_next) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).tqe_prev) as usize - ptr as usize }, 8usize, concat!( "Offset of field: ", stringify!(pf_pooladdr__bindgen_ty_1), "::", stringify!(tqe_prev) ) ); } #[test] fn bindgen_test_layout_pf_pooladdr() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 88usize, concat!("Size of: ", stringify!(pf_pooladdr)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pf_pooladdr)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).addr) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(pf_pooladdr), "::", stringify!(addr)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).entries) as usize - ptr as usize }, 48usize, concat!("Offset of field: ", stringify!(pf_pooladdr), "::", stringify!(entries)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifname) as usize - ptr as usize }, 64usize, concat!("Offset of field: ", stringify!(pf_pooladdr), "::", stringify!(ifname)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).kif) as usize - ptr as usize }, 80usize, concat!("Offset of field: ", stringify!(pf_pooladdr), "::", stringify!(kif)) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pf_palist { pub tqh_first: *mut pf_pooladdr, pub tqh_last: *mut *mut pf_pooladdr, } #[test] fn bindgen_test_layout_pf_palist() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 16usize, concat!("Size of: ", stringify!(pf_palist)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pf_palist)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).tqh_first) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(pf_palist), "::", stringify!(tqh_first)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).tqh_last) as usize - ptr as usize }, 8usize, concat!("Offset of field: ", stringify!(pf_palist), "::", stringify!(tqh_last)) ); } #[repr(C)] #[derive(Copy, Clone)] pub struct pf_poolhashkey { pub __bindgen_anon_1: pf_poolhashkey__bindgen_ty_1, } #[repr(C)] #[derive(Copy, Clone)] pub union pf_poolhashkey__bindgen_ty_1 { pub key8: [u_int8_t; 16usize], pub key16: [u_int16_t; 8usize], pub key32: [u_int32_t; 4usize], } #[test] fn bindgen_test_layout_pf_poolhashkey__bindgen_ty_1() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 16usize, concat!("Size of: ", stringify!(pf_poolhashkey__bindgen_ty_1)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(pf_poolhashkey__bindgen_ty_1)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).key8) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pf_poolhashkey__bindgen_ty_1), "::", stringify!(key8) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).key16) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pf_poolhashkey__bindgen_ty_1), "::", stringify!(key16) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).key32) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pf_poolhashkey__bindgen_ty_1), "::", stringify!(key32) ) ); } #[test] fn bindgen_test_layout_pf_poolhashkey() { assert_eq!( ::std::mem::size_of::(), 16usize, concat!("Size of: ", stringify!(pf_poolhashkey)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(pf_poolhashkey)) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pf_mape_portset { pub offset: u_int8_t, pub psidlen: u_int8_t, pub psid: u_int16_t, } #[test] fn bindgen_test_layout_pf_mape_portset() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 4usize, concat!("Size of: ", stringify!(pf_mape_portset)) ); assert_eq!( ::std::mem::align_of::(), 2usize, concat!("Alignment of ", stringify!(pf_mape_portset)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).offset) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pf_mape_portset), "::", stringify!(offset) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).psidlen) as usize - ptr as usize }, 1usize, concat!( "Offset of field: ", stringify!(pf_mape_portset), "::", stringify!(psidlen) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).psid) as usize - ptr as usize }, 2usize, concat!("Offset of field: ", stringify!(pf_mape_portset), "::", stringify!(psid)) ); } #[repr(C)] #[derive(Copy, Clone)] pub struct pf_pool { pub list: pf_palist, pub cur: *mut pf_pooladdr, pub key: pf_poolhashkey, pub counter: pf_addr, pub tblidx: ::std::os::raw::c_int, pub proxy_port: [u_int16_t; 2usize], pub opts: u_int8_t, } #[test] fn bindgen_test_layout_pf_pool() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 72usize, concat!("Size of: ", stringify!(pf_pool)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pf_pool)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).list) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(pf_pool), "::", stringify!(list)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).cur) as usize - ptr as usize }, 16usize, concat!("Offset of field: ", stringify!(pf_pool), "::", stringify!(cur)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).key) as usize - ptr as usize }, 24usize, concat!("Offset of field: ", stringify!(pf_pool), "::", stringify!(key)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).counter) as usize - ptr as usize }, 40usize, concat!("Offset of field: ", stringify!(pf_pool), "::", stringify!(counter)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).tblidx) as usize - ptr as usize }, 56usize, concat!("Offset of field: ", stringify!(pf_pool), "::", stringify!(tblidx)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).proxy_port) as usize - ptr as usize }, 60usize, concat!("Offset of field: ", stringify!(pf_pool), "::", stringify!(proxy_port)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).opts) as usize - ptr as usize }, 64usize, concat!("Offset of field: ", stringify!(pf_pool), "::", stringify!(opts)) ); } pub type pf_osfp_t = u_int32_t; #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pf_osfp_entry { pub fp_entry: pf_osfp_entry__bindgen_ty_1, pub fp_os: pf_osfp_t, pub fp_enflags: ::std::os::raw::c_int, pub fp_class_nm: [::std::os::raw::c_char; 32usize], pub fp_version_nm: [::std::os::raw::c_char; 32usize], pub fp_subtype_nm: [::std::os::raw::c_char; 32usize], } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pf_osfp_entry__bindgen_ty_1 { pub sle_next: *mut pf_osfp_entry, } #[test] fn bindgen_test_layout_pf_osfp_entry__bindgen_ty_1() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 8usize, concat!("Size of: ", stringify!(pf_osfp_entry__bindgen_ty_1)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pf_osfp_entry__bindgen_ty_1)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).sle_next) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pf_osfp_entry__bindgen_ty_1), "::", stringify!(sle_next) ) ); } #[test] fn bindgen_test_layout_pf_osfp_entry() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 112usize, concat!("Size of: ", stringify!(pf_osfp_entry)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pf_osfp_entry)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).fp_entry) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pf_osfp_entry), "::", stringify!(fp_entry) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).fp_os) as usize - ptr as usize }, 8usize, concat!("Offset of field: ", stringify!(pf_osfp_entry), "::", stringify!(fp_os)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).fp_enflags) as usize - ptr as usize }, 12usize, concat!( "Offset of field: ", stringify!(pf_osfp_entry), "::", stringify!(fp_enflags) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).fp_class_nm) as usize - ptr as usize }, 16usize, concat!( "Offset of field: ", stringify!(pf_osfp_entry), "::", stringify!(fp_class_nm) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).fp_version_nm) as usize - ptr as usize }, 48usize, concat!( "Offset of field: ", stringify!(pf_osfp_entry), "::", stringify!(fp_version_nm) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).fp_subtype_nm) as usize - ptr as usize }, 80usize, concat!( "Offset of field: ", stringify!(pf_osfp_entry), "::", stringify!(fp_subtype_nm) ) ); } pub type pf_tcpopts_t = u_int64_t; #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pf_os_fingerprint { pub fp_oses: pf_os_fingerprint_pf_osfp_enlist, pub fp_tcpopts: pf_tcpopts_t, pub fp_wsize: u_int16_t, pub fp_psize: u_int16_t, pub fp_mss: u_int16_t, pub fp_flags: u_int16_t, pub fp_optcnt: u_int8_t, pub fp_wscale: u_int8_t, pub fp_ttl: u_int8_t, pub fp_next: pf_os_fingerprint__bindgen_ty_1, } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pf_os_fingerprint_pf_osfp_enlist { pub slh_first: *mut pf_osfp_entry, } #[test] fn bindgen_test_layout_pf_os_fingerprint_pf_osfp_enlist() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 8usize, concat!("Size of: ", stringify!(pf_os_fingerprint_pf_osfp_enlist)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pf_os_fingerprint_pf_osfp_enlist)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).slh_first) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pf_os_fingerprint_pf_osfp_enlist), "::", stringify!(slh_first) ) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pf_os_fingerprint__bindgen_ty_1 { pub sle_next: *mut pf_os_fingerprint, } #[test] fn bindgen_test_layout_pf_os_fingerprint__bindgen_ty_1() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 8usize, concat!("Size of: ", stringify!(pf_os_fingerprint__bindgen_ty_1)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pf_os_fingerprint__bindgen_ty_1)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).sle_next) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pf_os_fingerprint__bindgen_ty_1), "::", stringify!(sle_next) ) ); } #[test] fn bindgen_test_layout_pf_os_fingerprint() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 40usize, concat!("Size of: ", stringify!(pf_os_fingerprint)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pf_os_fingerprint)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).fp_oses) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pf_os_fingerprint), "::", stringify!(fp_oses) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).fp_tcpopts) as usize - ptr as usize }, 8usize, concat!( "Offset of field: ", stringify!(pf_os_fingerprint), "::", stringify!(fp_tcpopts) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).fp_wsize) as usize - ptr as usize }, 16usize, concat!( "Offset of field: ", stringify!(pf_os_fingerprint), "::", stringify!(fp_wsize) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).fp_psize) as usize - ptr as usize }, 18usize, concat!( "Offset of field: ", stringify!(pf_os_fingerprint), "::", stringify!(fp_psize) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).fp_mss) as usize - ptr as usize }, 20usize, concat!( "Offset of field: ", stringify!(pf_os_fingerprint), "::", stringify!(fp_mss) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).fp_flags) as usize - ptr as usize }, 22usize, concat!( "Offset of field: ", stringify!(pf_os_fingerprint), "::", stringify!(fp_flags) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).fp_optcnt) as usize - ptr as usize }, 24usize, concat!( "Offset of field: ", stringify!(pf_os_fingerprint), "::", stringify!(fp_optcnt) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).fp_wscale) as usize - ptr as usize }, 25usize, concat!( "Offset of field: ", stringify!(pf_os_fingerprint), "::", stringify!(fp_wscale) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).fp_ttl) as usize - ptr as usize }, 26usize, concat!( "Offset of field: ", stringify!(pf_os_fingerprint), "::", stringify!(fp_ttl) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).fp_next) as usize - ptr as usize }, 32usize, concat!( "Offset of field: ", stringify!(pf_os_fingerprint), "::", stringify!(fp_next) ) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pf_osfp_ioctl { pub fp_os: pf_osfp_entry, pub fp_tcpopts: pf_tcpopts_t, pub fp_wsize: u_int16_t, pub fp_psize: u_int16_t, pub fp_mss: u_int16_t, pub fp_flags: u_int16_t, pub fp_optcnt: u_int8_t, pub fp_wscale: u_int8_t, pub fp_ttl: u_int8_t, pub fp_getnum: ::std::os::raw::c_int, } #[test] fn bindgen_test_layout_pf_osfp_ioctl() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 136usize, concat!("Size of: ", stringify!(pf_osfp_ioctl)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pf_osfp_ioctl)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).fp_os) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(pf_osfp_ioctl), "::", stringify!(fp_os)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).fp_tcpopts) as usize - ptr as usize }, 112usize, concat!( "Offset of field: ", stringify!(pf_osfp_ioctl), "::", stringify!(fp_tcpopts) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).fp_wsize) as usize - ptr as usize }, 120usize, concat!( "Offset of field: ", stringify!(pf_osfp_ioctl), "::", stringify!(fp_wsize) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).fp_psize) as usize - ptr as usize }, 122usize, concat!( "Offset of field: ", stringify!(pf_osfp_ioctl), "::", stringify!(fp_psize) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).fp_mss) as usize - ptr as usize }, 124usize, concat!("Offset of field: ", stringify!(pf_osfp_ioctl), "::", stringify!(fp_mss)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).fp_flags) as usize - ptr as usize }, 126usize, concat!( "Offset of field: ", stringify!(pf_osfp_ioctl), "::", stringify!(fp_flags) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).fp_optcnt) as usize - ptr as usize }, 128usize, concat!( "Offset of field: ", stringify!(pf_osfp_ioctl), "::", stringify!(fp_optcnt) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).fp_wscale) as usize - ptr as usize }, 129usize, concat!( "Offset of field: ", stringify!(pf_osfp_ioctl), "::", stringify!(fp_wscale) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).fp_ttl) as usize - ptr as usize }, 130usize, concat!("Offset of field: ", stringify!(pf_osfp_ioctl), "::", stringify!(fp_ttl)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).fp_getnum) as usize - ptr as usize }, 132usize, concat!( "Offset of field: ", stringify!(pf_osfp_ioctl), "::", stringify!(fp_getnum) ) ); } #[repr(C)] #[derive(Copy, Clone)] pub struct pf_rule { pub src: pf_rule_addr, pub dst: pf_rule_addr, pub skip: [pf_rule_ptr; 8usize], pub label: [::std::os::raw::c_char; 64usize], pub ifname: [::std::os::raw::c_char; 16usize], pub qname: [::std::os::raw::c_char; 64usize], pub pqname: [::std::os::raw::c_char; 64usize], pub tagname: [::std::os::raw::c_char; 64usize], pub match_tagname: [::std::os::raw::c_char; 64usize], pub overload_tblname: [::std::os::raw::c_char; 32usize], pub entries: pf_rule__bindgen_ty_1, pub rpool: pf_pool, pub evaluations: u_int64_t, pub packets: [u_int64_t; 2usize], pub bytes: [u_int64_t; 2usize], pub kif: *mut pfi_kif, pub anchor: *mut pf_anchor, pub overload_tbl: *mut pfr_ktable, pub os_fingerprint: pf_osfp_t, pub rtableid: ::std::os::raw::c_int, pub timeout: [u_int32_t; 20usize], pub max_states: u_int32_t, pub max_src_nodes: u_int32_t, pub max_src_states: u_int32_t, pub max_src_conn: u_int32_t, pub max_src_conn_rate: pf_rule__bindgen_ty_2, pub qid: u_int32_t, pub pqid: u_int32_t, pub rt_listid: u_int32_t, pub nr: u_int32_t, pub prob: u_int32_t, pub cuid: uid_t, pub cpid: pid_t, pub states_cur: counter_u64_t, pub states_tot: counter_u64_t, pub src_nodes: counter_u64_t, pub return_icmp: u_int16_t, pub return_icmp6: u_int16_t, pub max_mss: u_int16_t, pub tag: u_int16_t, pub match_tag: u_int16_t, pub scrub_flags: u_int16_t, pub uid: pf_rule_uid, pub gid: pf_rule_gid, pub rule_flag: u_int32_t, pub action: u_int8_t, pub direction: u_int8_t, pub log: u_int8_t, pub logif: u_int8_t, pub quick: u_int8_t, pub ifnot: u_int8_t, pub match_tag_not: u_int8_t, pub natpass: u_int8_t, pub keep_state: u_int8_t, pub af: sa_family_t, pub proto: u_int8_t, pub type_: u_int8_t, pub code: u_int8_t, pub flags: u_int8_t, pub flagset: u_int8_t, pub min_ttl: u_int8_t, pub allow_opts: u_int8_t, pub rt: u_int8_t, pub return_ttl: u_int8_t, pub tos: u_int8_t, pub set_tos: u_int8_t, pub anchor_relative: u_int8_t, pub anchor_wildcard: u_int8_t, pub flush: u_int8_t, pub prio: u_int8_t, pub set_prio: [u_int8_t; 2usize], pub divert: pf_rule__bindgen_ty_3, pub u_states_cur: u64, pub u_states_tot: u64, pub u_src_nodes: u64, } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pf_rule__bindgen_ty_1 { pub tqe_next: *mut pf_rule, pub tqe_prev: *mut *mut pf_rule, } #[test] fn bindgen_test_layout_pf_rule__bindgen_ty_1() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 16usize, concat!("Size of: ", stringify!(pf_rule__bindgen_ty_1)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pf_rule__bindgen_ty_1)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).tqe_next) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pf_rule__bindgen_ty_1), "::", stringify!(tqe_next) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).tqe_prev) as usize - ptr as usize }, 8usize, concat!( "Offset of field: ", stringify!(pf_rule__bindgen_ty_1), "::", stringify!(tqe_prev) ) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pf_rule__bindgen_ty_2 { pub limit: u_int32_t, pub seconds: u_int32_t, } #[test] fn bindgen_test_layout_pf_rule__bindgen_ty_2() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 8usize, concat!("Size of: ", stringify!(pf_rule__bindgen_ty_2)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(pf_rule__bindgen_ty_2)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).limit) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pf_rule__bindgen_ty_2), "::", stringify!(limit) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).seconds) as usize - ptr as usize }, 4usize, concat!( "Offset of field: ", stringify!(pf_rule__bindgen_ty_2), "::", stringify!(seconds) ) ); } #[repr(C)] #[derive(Copy, Clone)] pub struct pf_rule__bindgen_ty_3 { pub addr: pf_addr, pub port: u_int16_t, } #[test] fn bindgen_test_layout_pf_rule__bindgen_ty_3() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 20usize, concat!("Size of: ", stringify!(pf_rule__bindgen_ty_3)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(pf_rule__bindgen_ty_3)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).addr) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pf_rule__bindgen_ty_3), "::", stringify!(addr) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).port) as usize - ptr as usize }, 16usize, concat!( "Offset of field: ", stringify!(pf_rule__bindgen_ty_3), "::", stringify!(port) ) ); } #[test] fn bindgen_test_layout_pf_rule() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 976usize, concat!("Size of: ", stringify!(pf_rule)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pf_rule)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).src) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(src)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).dst) as usize - ptr as usize }, 56usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(dst)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).skip) as usize - ptr as usize }, 112usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(skip)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).label) as usize - ptr as usize }, 176usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(label)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifname) as usize - ptr as usize }, 240usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(ifname)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).qname) as usize - ptr as usize }, 256usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(qname)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pqname) as usize - ptr as usize }, 320usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(pqname)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).tagname) as usize - ptr as usize }, 384usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(tagname)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).match_tagname) as usize - ptr as usize }, 448usize, concat!( "Offset of field: ", stringify!(pf_rule), "::", stringify!(match_tagname) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).overload_tblname) as usize - ptr as usize }, 512usize, concat!( "Offset of field: ", stringify!(pf_rule), "::", stringify!(overload_tblname) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).entries) as usize - ptr as usize }, 544usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(entries)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rpool) as usize - ptr as usize }, 560usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(rpool)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).evaluations) as usize - ptr as usize }, 632usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(evaluations)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).packets) as usize - ptr as usize }, 640usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(packets)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).bytes) as usize - ptr as usize }, 656usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(bytes)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).kif) as usize - ptr as usize }, 672usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(kif)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).anchor) as usize - ptr as usize }, 680usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(anchor)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).overload_tbl) as usize - ptr as usize }, 688usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(overload_tbl)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).os_fingerprint) as usize - ptr as usize }, 696usize, concat!( "Offset of field: ", stringify!(pf_rule), "::", stringify!(os_fingerprint) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rtableid) as usize - ptr as usize }, 700usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(rtableid)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).timeout) as usize - ptr as usize }, 704usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(timeout)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).max_states) as usize - ptr as usize }, 784usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(max_states)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).max_src_nodes) as usize - ptr as usize }, 788usize, concat!( "Offset of field: ", stringify!(pf_rule), "::", stringify!(max_src_nodes) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).max_src_states) as usize - ptr as usize }, 792usize, concat!( "Offset of field: ", stringify!(pf_rule), "::", stringify!(max_src_states) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).max_src_conn) as usize - ptr as usize }, 796usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(max_src_conn)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).max_src_conn_rate) as usize - ptr as usize }, 800usize, concat!( "Offset of field: ", stringify!(pf_rule), "::", stringify!(max_src_conn_rate) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).qid) as usize - ptr as usize }, 808usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(qid)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pqid) as usize - ptr as usize }, 812usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(pqid)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rt_listid) as usize - ptr as usize }, 816usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(rt_listid)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).nr) as usize - ptr as usize }, 820usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(nr)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).prob) as usize - ptr as usize }, 824usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(prob)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).cuid) as usize - ptr as usize }, 828usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(cuid)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).cpid) as usize - ptr as usize }, 832usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(cpid)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).states_cur) as usize - ptr as usize }, 840usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(states_cur)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).states_tot) as usize - ptr as usize }, 848usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(states_tot)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).src_nodes) as usize - ptr as usize }, 856usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(src_nodes)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).return_icmp) as usize - ptr as usize }, 864usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(return_icmp)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).return_icmp6) as usize - ptr as usize }, 866usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(return_icmp6)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).max_mss) as usize - ptr as usize }, 868usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(max_mss)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).tag) as usize - ptr as usize }, 870usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(tag)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).match_tag) as usize - ptr as usize }, 872usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(match_tag)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).scrub_flags) as usize - ptr as usize }, 874usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(scrub_flags)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).uid) as usize - ptr as usize }, 876usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(uid)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).gid) as usize - ptr as usize }, 888usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(gid)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rule_flag) as usize - ptr as usize }, 900usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(rule_flag)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).action) as usize - ptr as usize }, 904usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(action)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).direction) as usize - ptr as usize }, 905usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(direction)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).log) as usize - ptr as usize }, 906usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(log)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).logif) as usize - ptr as usize }, 907usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(logif)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).quick) as usize - ptr as usize }, 908usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(quick)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifnot) as usize - ptr as usize }, 909usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(ifnot)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).match_tag_not) as usize - ptr as usize }, 910usize, concat!( "Offset of field: ", stringify!(pf_rule), "::", stringify!(match_tag_not) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).natpass) as usize - ptr as usize }, 911usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(natpass)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).keep_state) as usize - ptr as usize }, 912usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(keep_state)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).af) as usize - ptr as usize }, 913usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(af)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).proto) as usize - ptr as usize }, 914usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(proto)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).type_) as usize - ptr as usize }, 915usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(type_)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).code) as usize - ptr as usize }, 916usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(code)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).flags) as usize - ptr as usize }, 917usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(flags)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).flagset) as usize - ptr as usize }, 918usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(flagset)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).min_ttl) as usize - ptr as usize }, 919usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(min_ttl)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).allow_opts) as usize - ptr as usize }, 920usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(allow_opts)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rt) as usize - ptr as usize }, 921usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(rt)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).return_ttl) as usize - ptr as usize }, 922usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(return_ttl)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).tos) as usize - ptr as usize }, 923usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(tos)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).set_tos) as usize - ptr as usize }, 924usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(set_tos)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).anchor_relative) as usize - ptr as usize }, 925usize, concat!( "Offset of field: ", stringify!(pf_rule), "::", stringify!(anchor_relative) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).anchor_wildcard) as usize - ptr as usize }, 926usize, concat!( "Offset of field: ", stringify!(pf_rule), "::", stringify!(anchor_wildcard) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).flush) as usize - ptr as usize }, 927usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(flush)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).prio) as usize - ptr as usize }, 928usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(prio)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).set_prio) as usize - ptr as usize }, 929usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(set_prio)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).divert) as usize - ptr as usize }, 932usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(divert)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).u_states_cur) as usize - ptr as usize }, 952usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(u_states_cur)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).u_states_tot) as usize - ptr as usize }, 960usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(u_states_tot)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).u_src_nodes) as usize - ptr as usize }, 968usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(u_src_nodes)) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pf_threshold { pub limit: u_int32_t, pub seconds: u_int32_t, pub count: u_int32_t, pub last: u_int32_t, } #[test] fn bindgen_test_layout_pf_threshold() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 16usize, concat!("Size of: ", stringify!(pf_threshold)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(pf_threshold)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).limit) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(pf_threshold), "::", stringify!(limit)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).seconds) as usize - ptr as usize }, 4usize, concat!("Offset of field: ", stringify!(pf_threshold), "::", stringify!(seconds)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).count) as usize - ptr as usize }, 8usize, concat!("Offset of field: ", stringify!(pf_threshold), "::", stringify!(count)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).last) as usize - ptr as usize }, 12usize, concat!("Offset of field: ", stringify!(pf_threshold), "::", stringify!(last)) ); } #[repr(C)] #[derive(Copy, Clone)] pub struct pf_src_node { pub entry: pf_src_node__bindgen_ty_1, pub addr: pf_addr, pub raddr: pf_addr, pub rule: pf_rule_ptr, pub kif: *mut pfi_kif, pub bytes: [u_int64_t; 2usize], pub packets: [u_int64_t; 2usize], pub states: u_int32_t, pub conn: u_int32_t, pub conn_rate: pf_threshold, pub creation: u_int32_t, pub expire: u_int32_t, pub af: sa_family_t, pub ruletype: u_int8_t, } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pf_src_node__bindgen_ty_1 { pub le_next: *mut pf_src_node, pub le_prev: *mut *mut pf_src_node, } #[test] fn bindgen_test_layout_pf_src_node__bindgen_ty_1() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 16usize, concat!("Size of: ", stringify!(pf_src_node__bindgen_ty_1)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pf_src_node__bindgen_ty_1)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).le_next) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pf_src_node__bindgen_ty_1), "::", stringify!(le_next) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).le_prev) as usize - ptr as usize }, 8usize, concat!( "Offset of field: ", stringify!(pf_src_node__bindgen_ty_1), "::", stringify!(le_prev) ) ); } #[test] fn bindgen_test_layout_pf_src_node() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 136usize, concat!("Size of: ", stringify!(pf_src_node)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pf_src_node)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).entry) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(pf_src_node), "::", stringify!(entry)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).addr) as usize - ptr as usize }, 16usize, concat!("Offset of field: ", stringify!(pf_src_node), "::", stringify!(addr)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).raddr) as usize - ptr as usize }, 32usize, concat!("Offset of field: ", stringify!(pf_src_node), "::", stringify!(raddr)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rule) as usize - ptr as usize }, 48usize, concat!("Offset of field: ", stringify!(pf_src_node), "::", stringify!(rule)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).kif) as usize - ptr as usize }, 56usize, concat!("Offset of field: ", stringify!(pf_src_node), "::", stringify!(kif)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).bytes) as usize - ptr as usize }, 64usize, concat!("Offset of field: ", stringify!(pf_src_node), "::", stringify!(bytes)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).packets) as usize - ptr as usize }, 80usize, concat!("Offset of field: ", stringify!(pf_src_node), "::", stringify!(packets)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).states) as usize - ptr as usize }, 96usize, concat!("Offset of field: ", stringify!(pf_src_node), "::", stringify!(states)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).conn) as usize - ptr as usize }, 100usize, concat!("Offset of field: ", stringify!(pf_src_node), "::", stringify!(conn)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).conn_rate) as usize - ptr as usize }, 104usize, concat!( "Offset of field: ", stringify!(pf_src_node), "::", stringify!(conn_rate) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).creation) as usize - ptr as usize }, 120usize, concat!("Offset of field: ", stringify!(pf_src_node), "::", stringify!(creation)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).expire) as usize - ptr as usize }, 124usize, concat!("Offset of field: ", stringify!(pf_src_node), "::", stringify!(expire)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).af) as usize - ptr as usize }, 128usize, concat!("Offset of field: ", stringify!(pf_src_node), "::", stringify!(af)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ruletype) as usize - ptr as usize }, 129usize, concat!("Offset of field: ", stringify!(pf_src_node), "::", stringify!(ruletype)) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pf_rulequeue { pub tqh_first: *mut pf_rule, pub tqh_last: *mut *mut pf_rule, } #[test] fn bindgen_test_layout_pf_rulequeue() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 16usize, concat!("Size of: ", stringify!(pf_rulequeue)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pf_rulequeue)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).tqh_first) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pf_rulequeue), "::", stringify!(tqh_first) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).tqh_last) as usize - ptr as usize }, 8usize, concat!( "Offset of field: ", stringify!(pf_rulequeue), "::", stringify!(tqh_last) ) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pf_ruleset { pub rules: [pf_ruleset__bindgen_ty_1; 5usize], pub anchor: *mut pf_anchor, pub tticket: u_int32_t, pub tables: ::std::os::raw::c_int, pub topen: ::std::os::raw::c_int, } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pf_ruleset__bindgen_ty_1 { pub queues: [pf_rulequeue; 2usize], pub active: pf_ruleset__bindgen_ty_1__bindgen_ty_1, pub inactive: pf_ruleset__bindgen_ty_1__bindgen_ty_1, } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pf_ruleset__bindgen_ty_1__bindgen_ty_1 { pub ptr: *mut pf_rulequeue, pub ptr_array: *mut *mut pf_rule, pub rcount: u_int32_t, pub ticket: u_int32_t, pub open: ::std::os::raw::c_int, } #[test] fn bindgen_test_layout_pf_ruleset__bindgen_ty_1__bindgen_ty_1() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 32usize, concat!("Size of: ", stringify!(pf_ruleset__bindgen_ty_1__bindgen_ty_1)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pf_ruleset__bindgen_ty_1__bindgen_ty_1)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ptr) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pf_ruleset__bindgen_ty_1__bindgen_ty_1), "::", stringify!(ptr) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ptr_array) as usize - ptr as usize }, 8usize, concat!( "Offset of field: ", stringify!(pf_ruleset__bindgen_ty_1__bindgen_ty_1), "::", stringify!(ptr_array) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rcount) as usize - ptr as usize }, 16usize, concat!( "Offset of field: ", stringify!(pf_ruleset__bindgen_ty_1__bindgen_ty_1), "::", stringify!(rcount) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ticket) as usize - ptr as usize }, 20usize, concat!( "Offset of field: ", stringify!(pf_ruleset__bindgen_ty_1__bindgen_ty_1), "::", stringify!(ticket) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).open) as usize - ptr as usize }, 24usize, concat!( "Offset of field: ", stringify!(pf_ruleset__bindgen_ty_1__bindgen_ty_1), "::", stringify!(open) ) ); } #[test] fn bindgen_test_layout_pf_ruleset__bindgen_ty_1() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 96usize, concat!("Size of: ", stringify!(pf_ruleset__bindgen_ty_1)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pf_ruleset__bindgen_ty_1)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).queues) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pf_ruleset__bindgen_ty_1), "::", stringify!(queues) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).active) as usize - ptr as usize }, 32usize, concat!( "Offset of field: ", stringify!(pf_ruleset__bindgen_ty_1), "::", stringify!(active) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).inactive) as usize - ptr as usize }, 64usize, concat!( "Offset of field: ", stringify!(pf_ruleset__bindgen_ty_1), "::", stringify!(inactive) ) ); } #[test] fn bindgen_test_layout_pf_ruleset() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 504usize, concat!("Size of: ", stringify!(pf_ruleset)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pf_ruleset)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rules) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(pf_ruleset), "::", stringify!(rules)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).anchor) as usize - ptr as usize }, 480usize, concat!("Offset of field: ", stringify!(pf_ruleset), "::", stringify!(anchor)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).tticket) as usize - ptr as usize }, 488usize, concat!("Offset of field: ", stringify!(pf_ruleset), "::", stringify!(tticket)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).tables) as usize - ptr as usize }, 492usize, concat!("Offset of field: ", stringify!(pf_ruleset), "::", stringify!(tables)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).topen) as usize - ptr as usize }, 496usize, concat!("Offset of field: ", stringify!(pf_ruleset), "::", stringify!(topen)) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pf_anchor_global { pub rbh_root: *mut pf_anchor, } #[test] fn bindgen_test_layout_pf_anchor_global() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 8usize, concat!("Size of: ", stringify!(pf_anchor_global)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pf_anchor_global)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rbh_root) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pf_anchor_global), "::", stringify!(rbh_root) ) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pf_anchor_node { pub rbh_root: *mut pf_anchor, } #[test] fn bindgen_test_layout_pf_anchor_node() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 8usize, concat!("Size of: ", stringify!(pf_anchor_node)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pf_anchor_node)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rbh_root) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pf_anchor_node), "::", stringify!(rbh_root) ) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pf_anchor { pub entry_global: pf_anchor__bindgen_ty_1, pub entry_node: pf_anchor__bindgen_ty_2, pub parent: *mut pf_anchor, pub children: pf_anchor_node, pub name: [::std::os::raw::c_char; 64usize], pub path: [::std::os::raw::c_char; 1024usize], pub ruleset: pf_ruleset, pub refcnt: ::std::os::raw::c_int, pub match_: ::std::os::raw::c_int, } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pf_anchor__bindgen_ty_1 { pub rbe_link: [*mut pf_anchor; 3usize], } #[test] fn bindgen_test_layout_pf_anchor__bindgen_ty_1() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 24usize, concat!("Size of: ", stringify!(pf_anchor__bindgen_ty_1)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pf_anchor__bindgen_ty_1)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rbe_link) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pf_anchor__bindgen_ty_1), "::", stringify!(rbe_link) ) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pf_anchor__bindgen_ty_2 { pub rbe_link: [*mut pf_anchor; 3usize], } #[test] fn bindgen_test_layout_pf_anchor__bindgen_ty_2() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 24usize, concat!("Size of: ", stringify!(pf_anchor__bindgen_ty_2)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pf_anchor__bindgen_ty_2)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rbe_link) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pf_anchor__bindgen_ty_2), "::", stringify!(rbe_link) ) ); } #[test] fn bindgen_test_layout_pf_anchor() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 1664usize, concat!("Size of: ", stringify!(pf_anchor)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pf_anchor)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).entry_global) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pf_anchor), "::", stringify!(entry_global) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).entry_node) as usize - ptr as usize }, 24usize, concat!("Offset of field: ", stringify!(pf_anchor), "::", stringify!(entry_node)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).parent) as usize - ptr as usize }, 48usize, concat!("Offset of field: ", stringify!(pf_anchor), "::", stringify!(parent)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).children) as usize - ptr as usize }, 56usize, concat!("Offset of field: ", stringify!(pf_anchor), "::", stringify!(children)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).name) as usize - ptr as usize }, 64usize, concat!("Offset of field: ", stringify!(pf_anchor), "::", stringify!(name)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).path) as usize - ptr as usize }, 128usize, concat!("Offset of field: ", stringify!(pf_anchor), "::", stringify!(path)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ruleset) as usize - ptr as usize }, 1152usize, concat!("Offset of field: ", stringify!(pf_anchor), "::", stringify!(ruleset)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).refcnt) as usize - ptr as usize }, 1656usize, concat!("Offset of field: ", stringify!(pf_anchor), "::", stringify!(refcnt)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).match_) as usize - ptr as usize }, 1660usize, concat!("Offset of field: ", stringify!(pf_anchor), "::", stringify!(match_)) ); } unsafe extern "C" { pub fn pf_anchor_global_RB_INSERT_COLOR( arg1: *mut pf_anchor_global, arg2: *mut pf_anchor, arg3: *mut pf_anchor, ) -> *mut pf_anchor; } unsafe extern "C" { pub fn pf_anchor_global_RB_REMOVE_COLOR( arg1: *mut pf_anchor_global, arg2: *mut pf_anchor, arg3: *mut pf_anchor, ) -> *mut pf_anchor; } unsafe extern "C" { pub fn pf_anchor_global_RB_INSERT_FINISH( arg1: *mut pf_anchor_global, arg2: *mut pf_anchor, arg3: *mut *mut pf_anchor, arg4: *mut pf_anchor, ) -> *mut pf_anchor; } unsafe extern "C" { pub fn pf_anchor_global_RB_INSERT(arg1: *mut pf_anchor_global, arg2: *mut pf_anchor) -> *mut pf_anchor; } unsafe extern "C" { pub fn pf_anchor_global_RB_REMOVE(arg1: *mut pf_anchor_global, arg2: *mut pf_anchor) -> *mut pf_anchor; } unsafe extern "C" { pub fn pf_anchor_global_RB_FIND(arg1: *mut pf_anchor_global, arg2: *mut pf_anchor) -> *mut pf_anchor; } unsafe extern "C" { pub fn pf_anchor_global_RB_NFIND(arg1: *mut pf_anchor_global, arg2: *mut pf_anchor) -> *mut pf_anchor; } unsafe extern "C" { pub fn pf_anchor_global_RB_NEXT(arg1: *mut pf_anchor) -> *mut pf_anchor; } unsafe extern "C" { pub fn pf_anchor_global_RB_INSERT_NEXT( arg1: *mut pf_anchor_global, arg2: *mut pf_anchor, arg3: *mut pf_anchor, ) -> *mut pf_anchor; } unsafe extern "C" { pub fn pf_anchor_global_RB_PREV(arg1: *mut pf_anchor) -> *mut pf_anchor; } unsafe extern "C" { pub fn pf_anchor_global_RB_INSERT_PREV( arg1: *mut pf_anchor_global, arg2: *mut pf_anchor, arg3: *mut pf_anchor, ) -> *mut pf_anchor; } unsafe extern "C" { pub fn pf_anchor_global_RB_MINMAX(arg1: *mut pf_anchor_global, arg2: ::std::os::raw::c_int) -> *mut pf_anchor; } unsafe extern "C" { pub fn pf_anchor_global_RB_REINSERT(arg1: *mut pf_anchor_global, arg2: *mut pf_anchor) -> *mut pf_anchor; } unsafe extern "C" { pub fn pf_anchor_node_RB_INSERT_COLOR( arg1: *mut pf_anchor_node, arg2: *mut pf_anchor, arg3: *mut pf_anchor, ) -> *mut pf_anchor; } unsafe extern "C" { pub fn pf_anchor_node_RB_REMOVE_COLOR( arg1: *mut pf_anchor_node, arg2: *mut pf_anchor, arg3: *mut pf_anchor, ) -> *mut pf_anchor; } unsafe extern "C" { pub fn pf_anchor_node_RB_INSERT_FINISH( arg1: *mut pf_anchor_node, arg2: *mut pf_anchor, arg3: *mut *mut pf_anchor, arg4: *mut pf_anchor, ) -> *mut pf_anchor; } unsafe extern "C" { pub fn pf_anchor_node_RB_INSERT(arg1: *mut pf_anchor_node, arg2: *mut pf_anchor) -> *mut pf_anchor; } unsafe extern "C" { pub fn pf_anchor_node_RB_REMOVE(arg1: *mut pf_anchor_node, arg2: *mut pf_anchor) -> *mut pf_anchor; } unsafe extern "C" { pub fn pf_anchor_node_RB_FIND(arg1: *mut pf_anchor_node, arg2: *mut pf_anchor) -> *mut pf_anchor; } unsafe extern "C" { pub fn pf_anchor_node_RB_NFIND(arg1: *mut pf_anchor_node, arg2: *mut pf_anchor) -> *mut pf_anchor; } unsafe extern "C" { pub fn pf_anchor_node_RB_NEXT(arg1: *mut pf_anchor) -> *mut pf_anchor; } unsafe extern "C" { pub fn pf_anchor_node_RB_INSERT_NEXT( arg1: *mut pf_anchor_node, arg2: *mut pf_anchor, arg3: *mut pf_anchor, ) -> *mut pf_anchor; } unsafe extern "C" { pub fn pf_anchor_node_RB_PREV(arg1: *mut pf_anchor) -> *mut pf_anchor; } unsafe extern "C" { pub fn pf_anchor_node_RB_INSERT_PREV( arg1: *mut pf_anchor_node, arg2: *mut pf_anchor, arg3: *mut pf_anchor, ) -> *mut pf_anchor; } unsafe extern "C" { pub fn pf_anchor_node_RB_MINMAX(arg1: *mut pf_anchor_node, arg2: ::std::os::raw::c_int) -> *mut pf_anchor; } unsafe extern "C" { pub fn pf_anchor_node_RB_REINSERT(arg1: *mut pf_anchor_node, arg2: *mut pf_anchor) -> *mut pf_anchor; } unsafe extern "C" { pub fn pf_get_ruleset_number(arg1: u_int8_t) -> ::std::os::raw::c_int; } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct cbq_opts { pub minburst: u_int, pub maxburst: u_int, pub pktsize: u_int, pub maxpktsize: u_int, pub ns_per_byte: u_int, pub maxidle: u_int, pub minidle: ::std::os::raw::c_int, pub offtime: u_int, pub flags: ::std::os::raw::c_int, } #[test] fn bindgen_test_layout_cbq_opts() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 36usize, concat!("Size of: ", stringify!(cbq_opts)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(cbq_opts)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).minburst) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(cbq_opts), "::", stringify!(minburst)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).maxburst) as usize - ptr as usize }, 4usize, concat!("Offset of field: ", stringify!(cbq_opts), "::", stringify!(maxburst)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pktsize) as usize - ptr as usize }, 8usize, concat!("Offset of field: ", stringify!(cbq_opts), "::", stringify!(pktsize)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).maxpktsize) as usize - ptr as usize }, 12usize, concat!("Offset of field: ", stringify!(cbq_opts), "::", stringify!(maxpktsize)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ns_per_byte) as usize - ptr as usize }, 16usize, concat!("Offset of field: ", stringify!(cbq_opts), "::", stringify!(ns_per_byte)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).maxidle) as usize - ptr as usize }, 20usize, concat!("Offset of field: ", stringify!(cbq_opts), "::", stringify!(maxidle)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).minidle) as usize - ptr as usize }, 24usize, concat!("Offset of field: ", stringify!(cbq_opts), "::", stringify!(minidle)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).offtime) as usize - ptr as usize }, 28usize, concat!("Offset of field: ", stringify!(cbq_opts), "::", stringify!(offtime)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).flags) as usize - ptr as usize }, 32usize, concat!("Offset of field: ", stringify!(cbq_opts), "::", stringify!(flags)) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct codel_opts { pub target: u_int, pub interval: u_int, pub ecn: ::std::os::raw::c_int, } #[test] fn bindgen_test_layout_codel_opts() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 12usize, concat!("Size of: ", stringify!(codel_opts)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(codel_opts)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).target) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(codel_opts), "::", stringify!(target)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).interval) as usize - ptr as usize }, 4usize, concat!("Offset of field: ", stringify!(codel_opts), "::", stringify!(interval)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ecn) as usize - ptr as usize }, 8usize, concat!("Offset of field: ", stringify!(codel_opts), "::", stringify!(ecn)) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct priq_opts { pub flags: ::std::os::raw::c_int, } #[test] fn bindgen_test_layout_priq_opts() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 4usize, concat!("Size of: ", stringify!(priq_opts)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(priq_opts)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).flags) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(priq_opts), "::", stringify!(flags)) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct hfsc_opts_v0 { pub rtsc_m1: u_int, pub rtsc_d: u_int, pub rtsc_m2: u_int, pub lssc_m1: u_int, pub lssc_d: u_int, pub lssc_m2: u_int, pub ulsc_m1: u_int, pub ulsc_d: u_int, pub ulsc_m2: u_int, pub flags: ::std::os::raw::c_int, } #[test] fn bindgen_test_layout_hfsc_opts_v0() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 40usize, concat!("Size of: ", stringify!(hfsc_opts_v0)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(hfsc_opts_v0)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rtsc_m1) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(hfsc_opts_v0), "::", stringify!(rtsc_m1)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rtsc_d) as usize - ptr as usize }, 4usize, concat!("Offset of field: ", stringify!(hfsc_opts_v0), "::", stringify!(rtsc_d)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rtsc_m2) as usize - ptr as usize }, 8usize, concat!("Offset of field: ", stringify!(hfsc_opts_v0), "::", stringify!(rtsc_m2)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).lssc_m1) as usize - ptr as usize }, 12usize, concat!("Offset of field: ", stringify!(hfsc_opts_v0), "::", stringify!(lssc_m1)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).lssc_d) as usize - ptr as usize }, 16usize, concat!("Offset of field: ", stringify!(hfsc_opts_v0), "::", stringify!(lssc_d)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).lssc_m2) as usize - ptr as usize }, 20usize, concat!("Offset of field: ", stringify!(hfsc_opts_v0), "::", stringify!(lssc_m2)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ulsc_m1) as usize - ptr as usize }, 24usize, concat!("Offset of field: ", stringify!(hfsc_opts_v0), "::", stringify!(ulsc_m1)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ulsc_d) as usize - ptr as usize }, 28usize, concat!("Offset of field: ", stringify!(hfsc_opts_v0), "::", stringify!(ulsc_d)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ulsc_m2) as usize - ptr as usize }, 32usize, concat!("Offset of field: ", stringify!(hfsc_opts_v0), "::", stringify!(ulsc_m2)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).flags) as usize - ptr as usize }, 36usize, concat!("Offset of field: ", stringify!(hfsc_opts_v0), "::", stringify!(flags)) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct hfsc_opts_v1 { pub rtsc_m1: u_int64_t, pub rtsc_d: u_int, pub rtsc_m2: u_int64_t, pub lssc_m1: u_int64_t, pub lssc_d: u_int, pub lssc_m2: u_int64_t, pub ulsc_m1: u_int64_t, pub ulsc_d: u_int, pub ulsc_m2: u_int64_t, pub flags: ::std::os::raw::c_int, } #[test] fn bindgen_test_layout_hfsc_opts_v1() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 80usize, concat!("Size of: ", stringify!(hfsc_opts_v1)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(hfsc_opts_v1)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rtsc_m1) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(hfsc_opts_v1), "::", stringify!(rtsc_m1)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rtsc_d) as usize - ptr as usize }, 8usize, concat!("Offset of field: ", stringify!(hfsc_opts_v1), "::", stringify!(rtsc_d)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rtsc_m2) as usize - ptr as usize }, 16usize, concat!("Offset of field: ", stringify!(hfsc_opts_v1), "::", stringify!(rtsc_m2)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).lssc_m1) as usize - ptr as usize }, 24usize, concat!("Offset of field: ", stringify!(hfsc_opts_v1), "::", stringify!(lssc_m1)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).lssc_d) as usize - ptr as usize }, 32usize, concat!("Offset of field: ", stringify!(hfsc_opts_v1), "::", stringify!(lssc_d)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).lssc_m2) as usize - ptr as usize }, 40usize, concat!("Offset of field: ", stringify!(hfsc_opts_v1), "::", stringify!(lssc_m2)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ulsc_m1) as usize - ptr as usize }, 48usize, concat!("Offset of field: ", stringify!(hfsc_opts_v1), "::", stringify!(ulsc_m1)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ulsc_d) as usize - ptr as usize }, 56usize, concat!("Offset of field: ", stringify!(hfsc_opts_v1), "::", stringify!(ulsc_d)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ulsc_m2) as usize - ptr as usize }, 64usize, concat!("Offset of field: ", stringify!(hfsc_opts_v1), "::", stringify!(ulsc_m2)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).flags) as usize - ptr as usize }, 72usize, concat!("Offset of field: ", stringify!(hfsc_opts_v1), "::", stringify!(flags)) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct fairq_opts { pub nbuckets: u_int, pub hogs_m1: u_int, pub flags: ::std::os::raw::c_int, pub lssc_m1: u_int, pub lssc_d: u_int, pub lssc_m2: u_int, } #[test] fn bindgen_test_layout_fairq_opts() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 24usize, concat!("Size of: ", stringify!(fairq_opts)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(fairq_opts)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).nbuckets) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(fairq_opts), "::", stringify!(nbuckets)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).hogs_m1) as usize - ptr as usize }, 4usize, concat!("Offset of field: ", stringify!(fairq_opts), "::", stringify!(hogs_m1)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).flags) as usize - ptr as usize }, 8usize, concat!("Offset of field: ", stringify!(fairq_opts), "::", stringify!(flags)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).lssc_m1) as usize - ptr as usize }, 12usize, concat!("Offset of field: ", stringify!(fairq_opts), "::", stringify!(lssc_m1)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).lssc_d) as usize - ptr as usize }, 16usize, concat!("Offset of field: ", stringify!(fairq_opts), "::", stringify!(lssc_d)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).lssc_m2) as usize - ptr as usize }, 20usize, concat!("Offset of field: ", stringify!(fairq_opts), "::", stringify!(lssc_m2)) ); } #[repr(C)] #[derive(Copy, Clone)] pub struct pf_altq_v0 { pub ifname: [::std::os::raw::c_char; 16usize], pub unused1: *mut ::std::os::raw::c_void, pub entries: pf_altq_v0__bindgen_ty_1, pub scheduler: u8, pub tbrsize: u16, pub ifbandwidth: u32, pub qname: [::std::os::raw::c_char; 64usize], pub parent: [::std::os::raw::c_char; 64usize], pub parent_qid: u32, pub bandwidth: u32, pub priority: u8, pub local_flags: u8, pub qlimit: u16, pub flags: u16, pub pq_u: pf_altq_v0__bindgen_ty_2, pub qid: u32, } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pf_altq_v0__bindgen_ty_1 { pub tqe_next: *mut pf_altq_v0, pub tqe_prev: *mut *mut pf_altq_v0, } #[test] fn bindgen_test_layout_pf_altq_v0__bindgen_ty_1() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 16usize, concat!("Size of: ", stringify!(pf_altq_v0__bindgen_ty_1)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pf_altq_v0__bindgen_ty_1)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).tqe_next) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pf_altq_v0__bindgen_ty_1), "::", stringify!(tqe_next) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).tqe_prev) as usize - ptr as usize }, 8usize, concat!( "Offset of field: ", stringify!(pf_altq_v0__bindgen_ty_1), "::", stringify!(tqe_prev) ) ); } #[repr(C)] #[derive(Copy, Clone)] pub union pf_altq_v0__bindgen_ty_2 { pub cbq_opts: cbq_opts, pub codel_opts: codel_opts, pub priq_opts: priq_opts, pub hfsc_opts: hfsc_opts_v0, pub fairq_opts: fairq_opts, } #[test] fn bindgen_test_layout_pf_altq_v0__bindgen_ty_2() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 40usize, concat!("Size of: ", stringify!(pf_altq_v0__bindgen_ty_2)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(pf_altq_v0__bindgen_ty_2)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).cbq_opts) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pf_altq_v0__bindgen_ty_2), "::", stringify!(cbq_opts) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).codel_opts) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pf_altq_v0__bindgen_ty_2), "::", stringify!(codel_opts) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).priq_opts) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pf_altq_v0__bindgen_ty_2), "::", stringify!(priq_opts) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).hfsc_opts) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pf_altq_v0__bindgen_ty_2), "::", stringify!(hfsc_opts) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).fairq_opts) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pf_altq_v0__bindgen_ty_2), "::", stringify!(fairq_opts) ) ); } #[test] fn bindgen_test_layout_pf_altq_v0() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 240usize, concat!("Size of: ", stringify!(pf_altq_v0)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pf_altq_v0)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifname) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(pf_altq_v0), "::", stringify!(ifname)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).unused1) as usize - ptr as usize }, 16usize, concat!("Offset of field: ", stringify!(pf_altq_v0), "::", stringify!(unused1)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).entries) as usize - ptr as usize }, 24usize, concat!("Offset of field: ", stringify!(pf_altq_v0), "::", stringify!(entries)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).scheduler) as usize - ptr as usize }, 40usize, concat!("Offset of field: ", stringify!(pf_altq_v0), "::", stringify!(scheduler)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).tbrsize) as usize - ptr as usize }, 42usize, concat!("Offset of field: ", stringify!(pf_altq_v0), "::", stringify!(tbrsize)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifbandwidth) as usize - ptr as usize }, 44usize, concat!( "Offset of field: ", stringify!(pf_altq_v0), "::", stringify!(ifbandwidth) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).qname) as usize - ptr as usize }, 48usize, concat!("Offset of field: ", stringify!(pf_altq_v0), "::", stringify!(qname)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).parent) as usize - ptr as usize }, 112usize, concat!("Offset of field: ", stringify!(pf_altq_v0), "::", stringify!(parent)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).parent_qid) as usize - ptr as usize }, 176usize, concat!( "Offset of field: ", stringify!(pf_altq_v0), "::", stringify!(parent_qid) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).bandwidth) as usize - ptr as usize }, 180usize, concat!("Offset of field: ", stringify!(pf_altq_v0), "::", stringify!(bandwidth)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).priority) as usize - ptr as usize }, 184usize, concat!("Offset of field: ", stringify!(pf_altq_v0), "::", stringify!(priority)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).local_flags) as usize - ptr as usize }, 185usize, concat!( "Offset of field: ", stringify!(pf_altq_v0), "::", stringify!(local_flags) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).qlimit) as usize - ptr as usize }, 186usize, concat!("Offset of field: ", stringify!(pf_altq_v0), "::", stringify!(qlimit)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).flags) as usize - ptr as usize }, 188usize, concat!("Offset of field: ", stringify!(pf_altq_v0), "::", stringify!(flags)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pq_u) as usize - ptr as usize }, 192usize, concat!("Offset of field: ", stringify!(pf_altq_v0), "::", stringify!(pq_u)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).qid) as usize - ptr as usize }, 232usize, concat!("Offset of field: ", stringify!(pf_altq_v0), "::", stringify!(qid)) ); } #[repr(C)] #[derive(Copy, Clone)] pub struct pf_altq_v1 { pub ifname: [::std::os::raw::c_char; 16usize], pub entries: pf_altq_v1__bindgen_ty_1, pub scheduler: u8, pub tbrsize: u32, pub ifbandwidth: u64, pub qname: [::std::os::raw::c_char; 64usize], pub parent: [::std::os::raw::c_char; 64usize], pub parent_qid: u32, pub bandwidth: u64, pub priority: u8, pub local_flags: u8, pub qlimit: u16, pub flags: u16, pub pq_u: pf_altq_v1__bindgen_ty_2, pub qid: u32, } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pf_altq_v1__bindgen_ty_1 { pub tqe_next: *mut pf_altq_v1, pub tqe_prev: *mut *mut pf_altq_v1, } #[test] fn bindgen_test_layout_pf_altq_v1__bindgen_ty_1() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 16usize, concat!("Size of: ", stringify!(pf_altq_v1__bindgen_ty_1)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pf_altq_v1__bindgen_ty_1)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).tqe_next) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pf_altq_v1__bindgen_ty_1), "::", stringify!(tqe_next) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).tqe_prev) as usize - ptr as usize }, 8usize, concat!( "Offset of field: ", stringify!(pf_altq_v1__bindgen_ty_1), "::", stringify!(tqe_prev) ) ); } #[repr(C)] #[derive(Copy, Clone)] pub union pf_altq_v1__bindgen_ty_2 { pub cbq_opts: cbq_opts, pub codel_opts: codel_opts, pub priq_opts: priq_opts, pub hfsc_opts: hfsc_opts_v1, pub fairq_opts: fairq_opts, } #[test] fn bindgen_test_layout_pf_altq_v1__bindgen_ty_2() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 80usize, concat!("Size of: ", stringify!(pf_altq_v1__bindgen_ty_2)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pf_altq_v1__bindgen_ty_2)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).cbq_opts) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pf_altq_v1__bindgen_ty_2), "::", stringify!(cbq_opts) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).codel_opts) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pf_altq_v1__bindgen_ty_2), "::", stringify!(codel_opts) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).priq_opts) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pf_altq_v1__bindgen_ty_2), "::", stringify!(priq_opts) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).hfsc_opts) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pf_altq_v1__bindgen_ty_2), "::", stringify!(hfsc_opts) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).fairq_opts) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pf_altq_v1__bindgen_ty_2), "::", stringify!(fairq_opts) ) ); } #[test] fn bindgen_test_layout_pf_altq_v1() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 288usize, concat!("Size of: ", stringify!(pf_altq_v1)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pf_altq_v1)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifname) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(pf_altq_v1), "::", stringify!(ifname)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).entries) as usize - ptr as usize }, 16usize, concat!("Offset of field: ", stringify!(pf_altq_v1), "::", stringify!(entries)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).scheduler) as usize - ptr as usize }, 32usize, concat!("Offset of field: ", stringify!(pf_altq_v1), "::", stringify!(scheduler)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).tbrsize) as usize - ptr as usize }, 36usize, concat!("Offset of field: ", stringify!(pf_altq_v1), "::", stringify!(tbrsize)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifbandwidth) as usize - ptr as usize }, 40usize, concat!( "Offset of field: ", stringify!(pf_altq_v1), "::", stringify!(ifbandwidth) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).qname) as usize - ptr as usize }, 48usize, concat!("Offset of field: ", stringify!(pf_altq_v1), "::", stringify!(qname)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).parent) as usize - ptr as usize }, 112usize, concat!("Offset of field: ", stringify!(pf_altq_v1), "::", stringify!(parent)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).parent_qid) as usize - ptr as usize }, 176usize, concat!( "Offset of field: ", stringify!(pf_altq_v1), "::", stringify!(parent_qid) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).bandwidth) as usize - ptr as usize }, 184usize, concat!("Offset of field: ", stringify!(pf_altq_v1), "::", stringify!(bandwidth)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).priority) as usize - ptr as usize }, 192usize, concat!("Offset of field: ", stringify!(pf_altq_v1), "::", stringify!(priority)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).local_flags) as usize - ptr as usize }, 193usize, concat!( "Offset of field: ", stringify!(pf_altq_v1), "::", stringify!(local_flags) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).qlimit) as usize - ptr as usize }, 194usize, concat!("Offset of field: ", stringify!(pf_altq_v1), "::", stringify!(qlimit)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).flags) as usize - ptr as usize }, 196usize, concat!("Offset of field: ", stringify!(pf_altq_v1), "::", stringify!(flags)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pq_u) as usize - ptr as usize }, 200usize, concat!("Offset of field: ", stringify!(pf_altq_v1), "::", stringify!(pq_u)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).qid) as usize - ptr as usize }, 280usize, concat!("Offset of field: ", stringify!(pf_altq_v1), "::", stringify!(qid)) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pf_state_scrub { pub pfss_last: timeval, pub pfss_tsecr: u_int32_t, pub pfss_tsval: u_int32_t, pub pfss_tsval0: u_int32_t, pub pfss_flags: u_int16_t, pub pfss_ttl: u_int8_t, pub pad: u_int8_t, pub pfss_ts_mod: u_int32_t, } #[test] fn bindgen_test_layout_pf_state_scrub() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 40usize, concat!("Size of: ", stringify!(pf_state_scrub)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pf_state_scrub)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfss_last) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pf_state_scrub), "::", stringify!(pfss_last) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfss_tsecr) as usize - ptr as usize }, 16usize, concat!( "Offset of field: ", stringify!(pf_state_scrub), "::", stringify!(pfss_tsecr) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfss_tsval) as usize - ptr as usize }, 20usize, concat!( "Offset of field: ", stringify!(pf_state_scrub), "::", stringify!(pfss_tsval) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfss_tsval0) as usize - ptr as usize }, 24usize, concat!( "Offset of field: ", stringify!(pf_state_scrub), "::", stringify!(pfss_tsval0) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfss_flags) as usize - ptr as usize }, 28usize, concat!( "Offset of field: ", stringify!(pf_state_scrub), "::", stringify!(pfss_flags) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfss_ttl) as usize - ptr as usize }, 30usize, concat!( "Offset of field: ", stringify!(pf_state_scrub), "::", stringify!(pfss_ttl) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pad) as usize - ptr as usize }, 31usize, concat!("Offset of field: ", stringify!(pf_state_scrub), "::", stringify!(pad)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfss_ts_mod) as usize - ptr as usize }, 32usize, concat!( "Offset of field: ", stringify!(pf_state_scrub), "::", stringify!(pfss_ts_mod) ) ); } #[repr(C)] #[derive(Copy, Clone)] pub struct pf_state_host { pub addr: pf_addr, pub port: u_int16_t, pub pad: u_int16_t, } #[test] fn bindgen_test_layout_pf_state_host() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 20usize, concat!("Size of: ", stringify!(pf_state_host)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(pf_state_host)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).addr) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(pf_state_host), "::", stringify!(addr)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).port) as usize - ptr as usize }, 16usize, concat!("Offset of field: ", stringify!(pf_state_host), "::", stringify!(port)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pad) as usize - ptr as usize }, 18usize, concat!("Offset of field: ", stringify!(pf_state_host), "::", stringify!(pad)) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pf_state_peer { pub scrub: *mut pf_state_scrub, pub seqlo: u_int32_t, pub seqhi: u_int32_t, pub seqdiff: u_int32_t, pub max_win: u_int16_t, pub mss: u_int16_t, pub state: u_int8_t, pub wscale: u_int8_t, pub tcp_est: u_int8_t, pub pad: [u_int8_t; 1usize], } #[test] fn bindgen_test_layout_pf_state_peer() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 32usize, concat!("Size of: ", stringify!(pf_state_peer)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pf_state_peer)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).scrub) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(pf_state_peer), "::", stringify!(scrub)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).seqlo) as usize - ptr as usize }, 8usize, concat!("Offset of field: ", stringify!(pf_state_peer), "::", stringify!(seqlo)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).seqhi) as usize - ptr as usize }, 12usize, concat!("Offset of field: ", stringify!(pf_state_peer), "::", stringify!(seqhi)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).seqdiff) as usize - ptr as usize }, 16usize, concat!( "Offset of field: ", stringify!(pf_state_peer), "::", stringify!(seqdiff) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).max_win) as usize - ptr as usize }, 20usize, concat!( "Offset of field: ", stringify!(pf_state_peer), "::", stringify!(max_win) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).mss) as usize - ptr as usize }, 22usize, concat!("Offset of field: ", stringify!(pf_state_peer), "::", stringify!(mss)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).state) as usize - ptr as usize }, 24usize, concat!("Offset of field: ", stringify!(pf_state_peer), "::", stringify!(state)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).wscale) as usize - ptr as usize }, 25usize, concat!("Offset of field: ", stringify!(pf_state_peer), "::", stringify!(wscale)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).tcp_est) as usize - ptr as usize }, 26usize, concat!( "Offset of field: ", stringify!(pf_state_peer), "::", stringify!(tcp_est) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pad) as usize - ptr as usize }, 27usize, concat!("Offset of field: ", stringify!(pf_state_peer), "::", stringify!(pad)) ); } #[repr(C)] #[derive(Copy, Clone)] pub struct pf_state_key_cmp { pub addr: [pf_addr; 2usize], pub port: [u_int16_t; 2usize], pub af: sa_family_t, pub proto: u_int8_t, pub pad: [u_int8_t; 2usize], } #[test] fn bindgen_test_layout_pf_state_key_cmp() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 40usize, concat!("Size of: ", stringify!(pf_state_key_cmp)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(pf_state_key_cmp)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).addr) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pf_state_key_cmp), "::", stringify!(addr) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).port) as usize - ptr as usize }, 32usize, concat!( "Offset of field: ", stringify!(pf_state_key_cmp), "::", stringify!(port) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).af) as usize - ptr as usize }, 36usize, concat!("Offset of field: ", stringify!(pf_state_key_cmp), "::", stringify!(af)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).proto) as usize - ptr as usize }, 37usize, concat!( "Offset of field: ", stringify!(pf_state_key_cmp), "::", stringify!(proto) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pad) as usize - ptr as usize }, 38usize, concat!("Offset of field: ", stringify!(pf_state_key_cmp), "::", stringify!(pad)) ); } #[repr(C)] #[derive(Copy, Clone)] pub struct pf_state_key { pub addr: [pf_addr; 2usize], pub port: [u_int16_t; 2usize], pub af: sa_family_t, pub proto: u_int8_t, pub pad: [u_int8_t; 2usize], pub entry: pf_state_key__bindgen_ty_1, pub states: [pf_state_key__bindgen_ty_2; 2usize], } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pf_state_key__bindgen_ty_1 { pub le_next: *mut pf_state_key, pub le_prev: *mut *mut pf_state_key, } #[test] fn bindgen_test_layout_pf_state_key__bindgen_ty_1() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 16usize, concat!("Size of: ", stringify!(pf_state_key__bindgen_ty_1)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pf_state_key__bindgen_ty_1)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).le_next) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pf_state_key__bindgen_ty_1), "::", stringify!(le_next) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).le_prev) as usize - ptr as usize }, 8usize, concat!( "Offset of field: ", stringify!(pf_state_key__bindgen_ty_1), "::", stringify!(le_prev) ) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pf_state_key__bindgen_ty_2 { pub tqh_first: *mut pf_kstate, pub tqh_last: *mut *mut pf_kstate, } #[test] fn bindgen_test_layout_pf_state_key__bindgen_ty_2() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 16usize, concat!("Size of: ", stringify!(pf_state_key__bindgen_ty_2)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pf_state_key__bindgen_ty_2)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).tqh_first) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pf_state_key__bindgen_ty_2), "::", stringify!(tqh_first) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).tqh_last) as usize - ptr as usize }, 8usize, concat!( "Offset of field: ", stringify!(pf_state_key__bindgen_ty_2), "::", stringify!(tqh_last) ) ); } #[test] fn bindgen_test_layout_pf_state_key() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 88usize, concat!("Size of: ", stringify!(pf_state_key)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pf_state_key)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).addr) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(pf_state_key), "::", stringify!(addr)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).port) as usize - ptr as usize }, 32usize, concat!("Offset of field: ", stringify!(pf_state_key), "::", stringify!(port)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).af) as usize - ptr as usize }, 36usize, concat!("Offset of field: ", stringify!(pf_state_key), "::", stringify!(af)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).proto) as usize - ptr as usize }, 37usize, concat!("Offset of field: ", stringify!(pf_state_key), "::", stringify!(proto)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pad) as usize - ptr as usize }, 38usize, concat!("Offset of field: ", stringify!(pf_state_key), "::", stringify!(pad)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).entry) as usize - ptr as usize }, 40usize, concat!("Offset of field: ", stringify!(pf_state_key), "::", stringify!(entry)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).states) as usize - ptr as usize }, 56usize, concat!("Offset of field: ", stringify!(pf_state_key), "::", stringify!(states)) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pf_state_cmp { pub id: u_int64_t, pub creatorid: u_int32_t, pub direction: u_int8_t, pub pad: [u_int8_t; 3usize], } #[test] fn bindgen_test_layout_pf_state_cmp() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 16usize, concat!("Size of: ", stringify!(pf_state_cmp)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pf_state_cmp)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).id) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(pf_state_cmp), "::", stringify!(id)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).creatorid) as usize - ptr as usize }, 8usize, concat!( "Offset of field: ", stringify!(pf_state_cmp), "::", stringify!(creatorid) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).direction) as usize - ptr as usize }, 12usize, concat!( "Offset of field: ", stringify!(pf_state_cmp), "::", stringify!(direction) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pad) as usize - ptr as usize }, 13usize, concat!("Offset of field: ", stringify!(pf_state_cmp), "::", stringify!(pad)) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pf_state_scrub_export { pub pfss_flags: u16, pub pfss_ttl: u8, pub scrub_flag: u8, pub pfss_ts_mod: u32, } #[test] fn bindgen_test_layout_pf_state_scrub_export() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 8usize, concat!("Size of: ", stringify!(pf_state_scrub_export)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(pf_state_scrub_export)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfss_flags) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pf_state_scrub_export), "::", stringify!(pfss_flags) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfss_ttl) as usize - ptr as usize }, 2usize, concat!( "Offset of field: ", stringify!(pf_state_scrub_export), "::", stringify!(pfss_ttl) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).scrub_flag) as usize - ptr as usize }, 3usize, concat!( "Offset of field: ", stringify!(pf_state_scrub_export), "::", stringify!(scrub_flag) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfss_ts_mod) as usize - ptr as usize }, 4usize, concat!( "Offset of field: ", stringify!(pf_state_scrub_export), "::", stringify!(pfss_ts_mod) ) ); } #[repr(C)] #[derive(Copy, Clone)] pub struct pf_state_key_export { pub addr: [pf_addr; 2usize], pub port: [u16; 2usize], } #[test] fn bindgen_test_layout_pf_state_key_export() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 36usize, concat!("Size of: ", stringify!(pf_state_key_export)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(pf_state_key_export)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).addr) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pf_state_key_export), "::", stringify!(addr) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).port) as usize - ptr as usize }, 32usize, concat!( "Offset of field: ", stringify!(pf_state_key_export), "::", stringify!(port) ) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pf_state_peer_export { pub scrub: pf_state_scrub_export, pub seqlo: u32, pub seqhi: u32, pub seqdiff: u32, pub max_win: u16, pub mss: u16, pub state: u8, pub wscale: u8, pub dummy: [u8; 6usize], } #[test] fn bindgen_test_layout_pf_state_peer_export() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 32usize, concat!("Size of: ", stringify!(pf_state_peer_export)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(pf_state_peer_export)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).scrub) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pf_state_peer_export), "::", stringify!(scrub) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).seqlo) as usize - ptr as usize }, 8usize, concat!( "Offset of field: ", stringify!(pf_state_peer_export), "::", stringify!(seqlo) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).seqhi) as usize - ptr as usize }, 12usize, concat!( "Offset of field: ", stringify!(pf_state_peer_export), "::", stringify!(seqhi) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).seqdiff) as usize - ptr as usize }, 16usize, concat!( "Offset of field: ", stringify!(pf_state_peer_export), "::", stringify!(seqdiff) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).max_win) as usize - ptr as usize }, 20usize, concat!( "Offset of field: ", stringify!(pf_state_peer_export), "::", stringify!(max_win) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).mss) as usize - ptr as usize }, 22usize, concat!( "Offset of field: ", stringify!(pf_state_peer_export), "::", stringify!(mss) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).state) as usize - ptr as usize }, 24usize, concat!( "Offset of field: ", stringify!(pf_state_peer_export), "::", stringify!(state) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).wscale) as usize - ptr as usize }, 25usize, concat!( "Offset of field: ", stringify!(pf_state_peer_export), "::", stringify!(wscale) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).dummy) as usize - ptr as usize }, 26usize, concat!( "Offset of field: ", stringify!(pf_state_peer_export), "::", stringify!(dummy) ) ); } #[repr(C)] #[derive(Copy, Clone)] pub struct pf_state_export { pub version: u64, pub id: u64, pub ifname: [::std::os::raw::c_char; 16usize], pub orig_ifname: [::std::os::raw::c_char; 16usize], pub key: [pf_state_key_export; 2usize], pub src: pf_state_peer_export, pub dst: pf_state_peer_export, pub rt_addr: pf_addr, pub rule: u32, pub anchor: u32, pub nat_rule: u32, pub creation: u32, pub expire: u32, pub spare0: u32, pub packets: [u64; 2usize], pub bytes: [u64; 2usize], pub creatorid: u32, pub spare1: u32, pub af: sa_family_t, pub proto: u8, pub direction: u8, pub log: u8, pub state_flags_compat: u8, pub timeout: u8, pub sync_flags: u8, pub updates: u8, pub state_flags: u16, pub qid: u16, pub pqid: u16, pub dnpipe: u16, pub dnrpipe: u16, pub rtableid: i32, pub min_ttl: u8, pub set_tos: u8, pub max_mss: u16, pub set_prio: [u8; 2usize], pub rt: u8, pub rt_ifname: [::std::os::raw::c_char; 16usize], pub spare: [u8; 72usize], } #[test] fn bindgen_test_layout_pf_state_export() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 384usize, concat!("Size of: ", stringify!(pf_state_export)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pf_state_export)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).version) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pf_state_export), "::", stringify!(version) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).id) as usize - ptr as usize }, 8usize, concat!("Offset of field: ", stringify!(pf_state_export), "::", stringify!(id)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifname) as usize - ptr as usize }, 16usize, concat!( "Offset of field: ", stringify!(pf_state_export), "::", stringify!(ifname) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).orig_ifname) as usize - ptr as usize }, 32usize, concat!( "Offset of field: ", stringify!(pf_state_export), "::", stringify!(orig_ifname) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).key) as usize - ptr as usize }, 48usize, concat!("Offset of field: ", stringify!(pf_state_export), "::", stringify!(key)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).src) as usize - ptr as usize }, 120usize, concat!("Offset of field: ", stringify!(pf_state_export), "::", stringify!(src)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).dst) as usize - ptr as usize }, 152usize, concat!("Offset of field: ", stringify!(pf_state_export), "::", stringify!(dst)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rt_addr) as usize - ptr as usize }, 184usize, concat!( "Offset of field: ", stringify!(pf_state_export), "::", stringify!(rt_addr) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rule) as usize - ptr as usize }, 200usize, concat!("Offset of field: ", stringify!(pf_state_export), "::", stringify!(rule)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).anchor) as usize - ptr as usize }, 204usize, concat!( "Offset of field: ", stringify!(pf_state_export), "::", stringify!(anchor) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).nat_rule) as usize - ptr as usize }, 208usize, concat!( "Offset of field: ", stringify!(pf_state_export), "::", stringify!(nat_rule) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).creation) as usize - ptr as usize }, 212usize, concat!( "Offset of field: ", stringify!(pf_state_export), "::", stringify!(creation) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).expire) as usize - ptr as usize }, 216usize, concat!( "Offset of field: ", stringify!(pf_state_export), "::", stringify!(expire) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).spare0) as usize - ptr as usize }, 220usize, concat!( "Offset of field: ", stringify!(pf_state_export), "::", stringify!(spare0) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).packets) as usize - ptr as usize }, 224usize, concat!( "Offset of field: ", stringify!(pf_state_export), "::", stringify!(packets) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).bytes) as usize - ptr as usize }, 240usize, concat!( "Offset of field: ", stringify!(pf_state_export), "::", stringify!(bytes) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).creatorid) as usize - ptr as usize }, 256usize, concat!( "Offset of field: ", stringify!(pf_state_export), "::", stringify!(creatorid) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).spare1) as usize - ptr as usize }, 260usize, concat!( "Offset of field: ", stringify!(pf_state_export), "::", stringify!(spare1) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).af) as usize - ptr as usize }, 264usize, concat!("Offset of field: ", stringify!(pf_state_export), "::", stringify!(af)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).proto) as usize - ptr as usize }, 265usize, concat!( "Offset of field: ", stringify!(pf_state_export), "::", stringify!(proto) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).direction) as usize - ptr as usize }, 266usize, concat!( "Offset of field: ", stringify!(pf_state_export), "::", stringify!(direction) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).log) as usize - ptr as usize }, 267usize, concat!("Offset of field: ", stringify!(pf_state_export), "::", stringify!(log)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).state_flags_compat) as usize - ptr as usize }, 268usize, concat!( "Offset of field: ", stringify!(pf_state_export), "::", stringify!(state_flags_compat) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).timeout) as usize - ptr as usize }, 269usize, concat!( "Offset of field: ", stringify!(pf_state_export), "::", stringify!(timeout) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).sync_flags) as usize - ptr as usize }, 270usize, concat!( "Offset of field: ", stringify!(pf_state_export), "::", stringify!(sync_flags) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).updates) as usize - ptr as usize }, 271usize, concat!( "Offset of field: ", stringify!(pf_state_export), "::", stringify!(updates) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).state_flags) as usize - ptr as usize }, 272usize, concat!( "Offset of field: ", stringify!(pf_state_export), "::", stringify!(state_flags) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).qid) as usize - ptr as usize }, 274usize, concat!("Offset of field: ", stringify!(pf_state_export), "::", stringify!(qid)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pqid) as usize - ptr as usize }, 276usize, concat!("Offset of field: ", stringify!(pf_state_export), "::", stringify!(pqid)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).dnpipe) as usize - ptr as usize }, 278usize, concat!( "Offset of field: ", stringify!(pf_state_export), "::", stringify!(dnpipe) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).dnrpipe) as usize - ptr as usize }, 280usize, concat!( "Offset of field: ", stringify!(pf_state_export), "::", stringify!(dnrpipe) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rtableid) as usize - ptr as usize }, 284usize, concat!( "Offset of field: ", stringify!(pf_state_export), "::", stringify!(rtableid) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).min_ttl) as usize - ptr as usize }, 288usize, concat!( "Offset of field: ", stringify!(pf_state_export), "::", stringify!(min_ttl) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).set_tos) as usize - ptr as usize }, 289usize, concat!( "Offset of field: ", stringify!(pf_state_export), "::", stringify!(set_tos) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).max_mss) as usize - ptr as usize }, 290usize, concat!( "Offset of field: ", stringify!(pf_state_export), "::", stringify!(max_mss) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).set_prio) as usize - ptr as usize }, 292usize, concat!( "Offset of field: ", stringify!(pf_state_export), "::", stringify!(set_prio) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rt) as usize - ptr as usize }, 294usize, concat!("Offset of field: ", stringify!(pf_state_export), "::", stringify!(rt)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rt_ifname) as usize - ptr as usize }, 295usize, concat!( "Offset of field: ", stringify!(pf_state_export), "::", stringify!(rt_ifname) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).spare) as usize - ptr as usize }, 311usize, concat!( "Offset of field: ", stringify!(pf_state_export), "::", stringify!(spare) ) ); } #[repr(C, packed)] #[derive(Debug, Copy, Clone)] pub struct pfsync_state_scrub { pub pfss_flags: u_int16_t, pub pfss_ttl: u_int8_t, pub scrub_flag: u_int8_t, pub pfss_ts_mod: u_int32_t, } #[test] fn bindgen_test_layout_pfsync_state_scrub() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 8usize, concat!("Size of: ", stringify!(pfsync_state_scrub)) ); assert_eq!( ::std::mem::align_of::(), 1usize, concat!("Alignment of ", stringify!(pfsync_state_scrub)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfss_flags) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pfsync_state_scrub), "::", stringify!(pfss_flags) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfss_ttl) as usize - ptr as usize }, 2usize, concat!( "Offset of field: ", stringify!(pfsync_state_scrub), "::", stringify!(pfss_ttl) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).scrub_flag) as usize - ptr as usize }, 3usize, concat!( "Offset of field: ", stringify!(pfsync_state_scrub), "::", stringify!(scrub_flag) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfss_ts_mod) as usize - ptr as usize }, 4usize, concat!( "Offset of field: ", stringify!(pfsync_state_scrub), "::", stringify!(pfss_ts_mod) ) ); } #[repr(C, packed)] #[derive(Debug, Copy, Clone)] pub struct pfsync_state_peer { pub scrub: pfsync_state_scrub, pub seqlo: u_int32_t, pub seqhi: u_int32_t, pub seqdiff: u_int32_t, pub max_win: u_int16_t, pub mss: u_int16_t, pub state: u_int8_t, pub wscale: u_int8_t, pub pad: [u_int8_t; 6usize], } #[test] fn bindgen_test_layout_pfsync_state_peer() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 32usize, concat!("Size of: ", stringify!(pfsync_state_peer)) ); assert_eq!( ::std::mem::align_of::(), 1usize, concat!("Alignment of ", stringify!(pfsync_state_peer)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).scrub) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pfsync_state_peer), "::", stringify!(scrub) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).seqlo) as usize - ptr as usize }, 8usize, concat!( "Offset of field: ", stringify!(pfsync_state_peer), "::", stringify!(seqlo) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).seqhi) as usize - ptr as usize }, 12usize, concat!( "Offset of field: ", stringify!(pfsync_state_peer), "::", stringify!(seqhi) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).seqdiff) as usize - ptr as usize }, 16usize, concat!( "Offset of field: ", stringify!(pfsync_state_peer), "::", stringify!(seqdiff) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).max_win) as usize - ptr as usize }, 20usize, concat!( "Offset of field: ", stringify!(pfsync_state_peer), "::", stringify!(max_win) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).mss) as usize - ptr as usize }, 22usize, concat!( "Offset of field: ", stringify!(pfsync_state_peer), "::", stringify!(mss) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).state) as usize - ptr as usize }, 24usize, concat!( "Offset of field: ", stringify!(pfsync_state_peer), "::", stringify!(state) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).wscale) as usize - ptr as usize }, 25usize, concat!( "Offset of field: ", stringify!(pfsync_state_peer), "::", stringify!(wscale) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pad) as usize - ptr as usize }, 26usize, concat!( "Offset of field: ", stringify!(pfsync_state_peer), "::", stringify!(pad) ) ); } #[repr(C)] #[derive(Copy, Clone)] pub struct pfsync_state_key { pub addr: [pf_addr; 2usize], pub port: [u_int16_t; 2usize], } #[test] fn bindgen_test_layout_pfsync_state_key() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 36usize, concat!("Size of: ", stringify!(pfsync_state_key)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(pfsync_state_key)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).addr) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pfsync_state_key), "::", stringify!(addr) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).port) as usize - ptr as usize }, 32usize, concat!( "Offset of field: ", stringify!(pfsync_state_key), "::", stringify!(port) ) ); } #[repr(C, packed)] #[derive(Copy, Clone)] pub struct pfsync_state_1301 { pub id: u_int64_t, pub ifname: [::std::os::raw::c_char; 16usize], pub key: [pfsync_state_key; 2usize], pub src: pfsync_state_peer, pub dst: pfsync_state_peer, pub rt_addr: pf_addr, pub rule: u_int32_t, pub anchor: u_int32_t, pub nat_rule: u_int32_t, pub creation: u_int32_t, pub expire: u_int32_t, pub packets: [[u_int32_t; 2usize]; 2usize], pub bytes: [[u_int32_t; 2usize]; 2usize], pub creatorid: u_int32_t, pub af: sa_family_t, pub proto: u_int8_t, pub direction: u_int8_t, pub __spare: [u_int8_t; 2usize], pub log: u_int8_t, pub state_flags: u_int8_t, pub timeout: u_int8_t, pub sync_flags: u_int8_t, pub updates: u_int8_t, } #[test] fn bindgen_test_layout_pfsync_state_1301() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 242usize, concat!("Size of: ", stringify!(pfsync_state_1301)) ); assert_eq!( ::std::mem::align_of::(), 1usize, concat!("Alignment of ", stringify!(pfsync_state_1301)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).id) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(pfsync_state_1301), "::", stringify!(id)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifname) as usize - ptr as usize }, 8usize, concat!( "Offset of field: ", stringify!(pfsync_state_1301), "::", stringify!(ifname) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).key) as usize - ptr as usize }, 24usize, concat!( "Offset of field: ", stringify!(pfsync_state_1301), "::", stringify!(key) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).src) as usize - ptr as usize }, 96usize, concat!( "Offset of field: ", stringify!(pfsync_state_1301), "::", stringify!(src) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).dst) as usize - ptr as usize }, 128usize, concat!( "Offset of field: ", stringify!(pfsync_state_1301), "::", stringify!(dst) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rt_addr) as usize - ptr as usize }, 160usize, concat!( "Offset of field: ", stringify!(pfsync_state_1301), "::", stringify!(rt_addr) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rule) as usize - ptr as usize }, 176usize, concat!( "Offset of field: ", stringify!(pfsync_state_1301), "::", stringify!(rule) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).anchor) as usize - ptr as usize }, 180usize, concat!( "Offset of field: ", stringify!(pfsync_state_1301), "::", stringify!(anchor) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).nat_rule) as usize - ptr as usize }, 184usize, concat!( "Offset of field: ", stringify!(pfsync_state_1301), "::", stringify!(nat_rule) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).creation) as usize - ptr as usize }, 188usize, concat!( "Offset of field: ", stringify!(pfsync_state_1301), "::", stringify!(creation) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).expire) as usize - ptr as usize }, 192usize, concat!( "Offset of field: ", stringify!(pfsync_state_1301), "::", stringify!(expire) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).packets) as usize - ptr as usize }, 196usize, concat!( "Offset of field: ", stringify!(pfsync_state_1301), "::", stringify!(packets) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).bytes) as usize - ptr as usize }, 212usize, concat!( "Offset of field: ", stringify!(pfsync_state_1301), "::", stringify!(bytes) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).creatorid) as usize - ptr as usize }, 228usize, concat!( "Offset of field: ", stringify!(pfsync_state_1301), "::", stringify!(creatorid) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).af) as usize - ptr as usize }, 232usize, concat!("Offset of field: ", stringify!(pfsync_state_1301), "::", stringify!(af)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).proto) as usize - ptr as usize }, 233usize, concat!( "Offset of field: ", stringify!(pfsync_state_1301), "::", stringify!(proto) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).direction) as usize - ptr as usize }, 234usize, concat!( "Offset of field: ", stringify!(pfsync_state_1301), "::", stringify!(direction) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__spare) as usize - ptr as usize }, 235usize, concat!( "Offset of field: ", stringify!(pfsync_state_1301), "::", stringify!(__spare) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).log) as usize - ptr as usize }, 237usize, concat!( "Offset of field: ", stringify!(pfsync_state_1301), "::", stringify!(log) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).state_flags) as usize - ptr as usize }, 238usize, concat!( "Offset of field: ", stringify!(pfsync_state_1301), "::", stringify!(state_flags) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).timeout) as usize - ptr as usize }, 239usize, concat!( "Offset of field: ", stringify!(pfsync_state_1301), "::", stringify!(timeout) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).sync_flags) as usize - ptr as usize }, 240usize, concat!( "Offset of field: ", stringify!(pfsync_state_1301), "::", stringify!(sync_flags) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).updates) as usize - ptr as usize }, 241usize, concat!( "Offset of field: ", stringify!(pfsync_state_1301), "::", stringify!(updates) ) ); } #[repr(C, packed)] #[derive(Copy, Clone)] pub struct pfsync_state_1400 { pub id: u_int64_t, pub ifname: [::std::os::raw::c_char; 16usize], pub key: [pfsync_state_key; 2usize], pub src: pfsync_state_peer, pub dst: pfsync_state_peer, pub rt_addr: pf_addr, pub rule: u_int32_t, pub anchor: u_int32_t, pub nat_rule: u_int32_t, pub creation: u_int32_t, pub expire: u_int32_t, pub packets: [[u_int32_t; 2usize]; 2usize], pub bytes: [[u_int32_t; 2usize]; 2usize], pub creatorid: u_int32_t, pub af: sa_family_t, pub proto: u_int8_t, pub direction: u_int8_t, pub state_flags: u_int16_t, pub log: u_int8_t, pub __spare: u_int8_t, pub timeout: u_int8_t, pub sync_flags: u_int8_t, pub updates: u_int8_t, pub qid: u_int16_t, pub pqid: u_int16_t, pub dnpipe: u_int16_t, pub dnrpipe: u_int16_t, pub rtableid: i32, pub min_ttl: u_int8_t, pub set_tos: u_int8_t, pub max_mss: u_int16_t, pub set_prio: [u_int8_t; 2usize], pub rt: u_int8_t, pub rt_ifname: [::std::os::raw::c_char; 16usize], } #[test] fn bindgen_test_layout_pfsync_state_1400() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 277usize, concat!("Size of: ", stringify!(pfsync_state_1400)) ); assert_eq!( ::std::mem::align_of::(), 1usize, concat!("Alignment of ", stringify!(pfsync_state_1400)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).id) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(pfsync_state_1400), "::", stringify!(id)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifname) as usize - ptr as usize }, 8usize, concat!( "Offset of field: ", stringify!(pfsync_state_1400), "::", stringify!(ifname) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).key) as usize - ptr as usize }, 24usize, concat!( "Offset of field: ", stringify!(pfsync_state_1400), "::", stringify!(key) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).src) as usize - ptr as usize }, 96usize, concat!( "Offset of field: ", stringify!(pfsync_state_1400), "::", stringify!(src) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).dst) as usize - ptr as usize }, 128usize, concat!( "Offset of field: ", stringify!(pfsync_state_1400), "::", stringify!(dst) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rt_addr) as usize - ptr as usize }, 160usize, concat!( "Offset of field: ", stringify!(pfsync_state_1400), "::", stringify!(rt_addr) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rule) as usize - ptr as usize }, 176usize, concat!( "Offset of field: ", stringify!(pfsync_state_1400), "::", stringify!(rule) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).anchor) as usize - ptr as usize }, 180usize, concat!( "Offset of field: ", stringify!(pfsync_state_1400), "::", stringify!(anchor) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).nat_rule) as usize - ptr as usize }, 184usize, concat!( "Offset of field: ", stringify!(pfsync_state_1400), "::", stringify!(nat_rule) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).creation) as usize - ptr as usize }, 188usize, concat!( "Offset of field: ", stringify!(pfsync_state_1400), "::", stringify!(creation) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).expire) as usize - ptr as usize }, 192usize, concat!( "Offset of field: ", stringify!(pfsync_state_1400), "::", stringify!(expire) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).packets) as usize - ptr as usize }, 196usize, concat!( "Offset of field: ", stringify!(pfsync_state_1400), "::", stringify!(packets) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).bytes) as usize - ptr as usize }, 212usize, concat!( "Offset of field: ", stringify!(pfsync_state_1400), "::", stringify!(bytes) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).creatorid) as usize - ptr as usize }, 228usize, concat!( "Offset of field: ", stringify!(pfsync_state_1400), "::", stringify!(creatorid) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).af) as usize - ptr as usize }, 232usize, concat!("Offset of field: ", stringify!(pfsync_state_1400), "::", stringify!(af)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).proto) as usize - ptr as usize }, 233usize, concat!( "Offset of field: ", stringify!(pfsync_state_1400), "::", stringify!(proto) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).direction) as usize - ptr as usize }, 234usize, concat!( "Offset of field: ", stringify!(pfsync_state_1400), "::", stringify!(direction) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).state_flags) as usize - ptr as usize }, 235usize, concat!( "Offset of field: ", stringify!(pfsync_state_1400), "::", stringify!(state_flags) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).log) as usize - ptr as usize }, 237usize, concat!( "Offset of field: ", stringify!(pfsync_state_1400), "::", stringify!(log) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__spare) as usize - ptr as usize }, 238usize, concat!( "Offset of field: ", stringify!(pfsync_state_1400), "::", stringify!(__spare) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).timeout) as usize - ptr as usize }, 239usize, concat!( "Offset of field: ", stringify!(pfsync_state_1400), "::", stringify!(timeout) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).sync_flags) as usize - ptr as usize }, 240usize, concat!( "Offset of field: ", stringify!(pfsync_state_1400), "::", stringify!(sync_flags) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).updates) as usize - ptr as usize }, 241usize, concat!( "Offset of field: ", stringify!(pfsync_state_1400), "::", stringify!(updates) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).qid) as usize - ptr as usize }, 242usize, concat!( "Offset of field: ", stringify!(pfsync_state_1400), "::", stringify!(qid) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pqid) as usize - ptr as usize }, 244usize, concat!( "Offset of field: ", stringify!(pfsync_state_1400), "::", stringify!(pqid) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).dnpipe) as usize - ptr as usize }, 246usize, concat!( "Offset of field: ", stringify!(pfsync_state_1400), "::", stringify!(dnpipe) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).dnrpipe) as usize - ptr as usize }, 248usize, concat!( "Offset of field: ", stringify!(pfsync_state_1400), "::", stringify!(dnrpipe) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rtableid) as usize - ptr as usize }, 250usize, concat!( "Offset of field: ", stringify!(pfsync_state_1400), "::", stringify!(rtableid) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).min_ttl) as usize - ptr as usize }, 254usize, concat!( "Offset of field: ", stringify!(pfsync_state_1400), "::", stringify!(min_ttl) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).set_tos) as usize - ptr as usize }, 255usize, concat!( "Offset of field: ", stringify!(pfsync_state_1400), "::", stringify!(set_tos) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).max_mss) as usize - ptr as usize }, 256usize, concat!( "Offset of field: ", stringify!(pfsync_state_1400), "::", stringify!(max_mss) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).set_prio) as usize - ptr as usize }, 258usize, concat!( "Offset of field: ", stringify!(pfsync_state_1400), "::", stringify!(set_prio) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rt) as usize - ptr as usize }, 260usize, concat!("Offset of field: ", stringify!(pfsync_state_1400), "::", stringify!(rt)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rt_ifname) as usize - ptr as usize }, 261usize, concat!( "Offset of field: ", stringify!(pfsync_state_1400), "::", stringify!(rt_ifname) ) ); } #[repr(C, packed)] #[derive(Copy, Clone)] pub union pfsync_state_union { pub pfs_1301: pfsync_state_1301, pub pfs_1400: pfsync_state_1400, } #[test] fn bindgen_test_layout_pfsync_state_union() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 277usize, concat!("Size of: ", stringify!(pfsync_state_union)) ); assert_eq!( ::std::mem::align_of::(), 1usize, concat!("Alignment of ", stringify!(pfsync_state_union)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfs_1301) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pfsync_state_union), "::", stringify!(pfs_1301) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfs_1400) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pfsync_state_union), "::", stringify!(pfs_1400) ) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pf_krulequeue { pub tqh_first: *mut pf_krule, pub tqh_last: *mut *mut pf_krule, } #[test] fn bindgen_test_layout_pf_krulequeue() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 16usize, concat!("Size of: ", stringify!(pf_krulequeue)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pf_krulequeue)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).tqh_first) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pf_krulequeue), "::", stringify!(tqh_first) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).tqh_last) as usize - ptr as usize }, 8usize, concat!( "Offset of field: ", stringify!(pf_krulequeue), "::", stringify!(tqh_last) ) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pf_kruleset { pub rules: [pf_kruleset__bindgen_ty_1; 5usize], pub anchor: *mut pf_kanchor, pub tticket: u_int32_t, pub tables: ::std::os::raw::c_int, pub topen: ::std::os::raw::c_int, } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pf_kruleset__bindgen_ty_1 { pub queues: [pf_krulequeue; 2usize], pub active: pf_kruleset__bindgen_ty_1__bindgen_ty_1, pub inactive: pf_kruleset__bindgen_ty_1__bindgen_ty_1, } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pf_kruleset__bindgen_ty_1__bindgen_ty_1 { pub ptr: *mut pf_krulequeue, pub ptr_array: *mut *mut pf_krule, pub rcount: u_int32_t, pub ticket: u_int32_t, pub open: ::std::os::raw::c_int, pub tree: *mut pf_krule_global, } #[test] fn bindgen_test_layout_pf_kruleset__bindgen_ty_1__bindgen_ty_1() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 40usize, concat!("Size of: ", stringify!(pf_kruleset__bindgen_ty_1__bindgen_ty_1)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pf_kruleset__bindgen_ty_1__bindgen_ty_1)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ptr) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pf_kruleset__bindgen_ty_1__bindgen_ty_1), "::", stringify!(ptr) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ptr_array) as usize - ptr as usize }, 8usize, concat!( "Offset of field: ", stringify!(pf_kruleset__bindgen_ty_1__bindgen_ty_1), "::", stringify!(ptr_array) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rcount) as usize - ptr as usize }, 16usize, concat!( "Offset of field: ", stringify!(pf_kruleset__bindgen_ty_1__bindgen_ty_1), "::", stringify!(rcount) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ticket) as usize - ptr as usize }, 20usize, concat!( "Offset of field: ", stringify!(pf_kruleset__bindgen_ty_1__bindgen_ty_1), "::", stringify!(ticket) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).open) as usize - ptr as usize }, 24usize, concat!( "Offset of field: ", stringify!(pf_kruleset__bindgen_ty_1__bindgen_ty_1), "::", stringify!(open) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).tree) as usize - ptr as usize }, 32usize, concat!( "Offset of field: ", stringify!(pf_kruleset__bindgen_ty_1__bindgen_ty_1), "::", stringify!(tree) ) ); } #[test] fn bindgen_test_layout_pf_kruleset__bindgen_ty_1() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 112usize, concat!("Size of: ", stringify!(pf_kruleset__bindgen_ty_1)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pf_kruleset__bindgen_ty_1)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).queues) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pf_kruleset__bindgen_ty_1), "::", stringify!(queues) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).active) as usize - ptr as usize }, 32usize, concat!( "Offset of field: ", stringify!(pf_kruleset__bindgen_ty_1), "::", stringify!(active) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).inactive) as usize - ptr as usize }, 72usize, concat!( "Offset of field: ", stringify!(pf_kruleset__bindgen_ty_1), "::", stringify!(inactive) ) ); } #[test] fn bindgen_test_layout_pf_kruleset() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 584usize, concat!("Size of: ", stringify!(pf_kruleset)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pf_kruleset)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rules) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(pf_kruleset), "::", stringify!(rules)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).anchor) as usize - ptr as usize }, 560usize, concat!("Offset of field: ", stringify!(pf_kruleset), "::", stringify!(anchor)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).tticket) as usize - ptr as usize }, 568usize, concat!("Offset of field: ", stringify!(pf_kruleset), "::", stringify!(tticket)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).tables) as usize - ptr as usize }, 572usize, concat!("Offset of field: ", stringify!(pf_kruleset), "::", stringify!(tables)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).topen) as usize - ptr as usize }, 576usize, concat!("Offset of field: ", stringify!(pf_kruleset), "::", stringify!(topen)) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pf_kanchor_global { pub rbh_root: *mut pf_kanchor, } #[test] fn bindgen_test_layout_pf_kanchor_global() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 8usize, concat!("Size of: ", stringify!(pf_kanchor_global)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pf_kanchor_global)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rbh_root) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pf_kanchor_global), "::", stringify!(rbh_root) ) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pf_kanchor_node { pub rbh_root: *mut pf_kanchor, } #[test] fn bindgen_test_layout_pf_kanchor_node() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 8usize, concat!("Size of: ", stringify!(pf_kanchor_node)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pf_kanchor_node)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rbh_root) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pf_kanchor_node), "::", stringify!(rbh_root) ) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pf_kanchor { pub entry_global: pf_kanchor__bindgen_ty_1, pub entry_node: pf_kanchor__bindgen_ty_2, pub parent: *mut pf_kanchor, pub children: pf_kanchor_node, pub name: [::std::os::raw::c_char; 64usize], pub path: [::std::os::raw::c_char; 1024usize], pub ruleset: pf_kruleset, pub refcnt: ::std::os::raw::c_int, } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pf_kanchor__bindgen_ty_1 { pub rbe_link: [*mut pf_kanchor; 3usize], } #[test] fn bindgen_test_layout_pf_kanchor__bindgen_ty_1() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 24usize, concat!("Size of: ", stringify!(pf_kanchor__bindgen_ty_1)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pf_kanchor__bindgen_ty_1)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rbe_link) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pf_kanchor__bindgen_ty_1), "::", stringify!(rbe_link) ) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pf_kanchor__bindgen_ty_2 { pub rbe_link: [*mut pf_kanchor; 3usize], } #[test] fn bindgen_test_layout_pf_kanchor__bindgen_ty_2() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 24usize, concat!("Size of: ", stringify!(pf_kanchor__bindgen_ty_2)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pf_kanchor__bindgen_ty_2)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rbe_link) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pf_kanchor__bindgen_ty_2), "::", stringify!(rbe_link) ) ); } #[test] fn bindgen_test_layout_pf_kanchor() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 1744usize, concat!("Size of: ", stringify!(pf_kanchor)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pf_kanchor)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).entry_global) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pf_kanchor), "::", stringify!(entry_global) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).entry_node) as usize - ptr as usize }, 24usize, concat!( "Offset of field: ", stringify!(pf_kanchor), "::", stringify!(entry_node) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).parent) as usize - ptr as usize }, 48usize, concat!("Offset of field: ", stringify!(pf_kanchor), "::", stringify!(parent)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).children) as usize - ptr as usize }, 56usize, concat!("Offset of field: ", stringify!(pf_kanchor), "::", stringify!(children)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).name) as usize - ptr as usize }, 64usize, concat!("Offset of field: ", stringify!(pf_kanchor), "::", stringify!(name)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).path) as usize - ptr as usize }, 128usize, concat!("Offset of field: ", stringify!(pf_kanchor), "::", stringify!(path)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ruleset) as usize - ptr as usize }, 1152usize, concat!("Offset of field: ", stringify!(pf_kanchor), "::", stringify!(ruleset)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).refcnt) as usize - ptr as usize }, 1736usize, concat!("Offset of field: ", stringify!(pf_kanchor), "::", stringify!(refcnt)) ); } unsafe extern "C" { pub fn pf_kanchor_global_RB_INSERT_COLOR( arg1: *mut pf_kanchor_global, arg2: *mut pf_kanchor, arg3: *mut pf_kanchor, ) -> *mut pf_kanchor; } unsafe extern "C" { pub fn pf_kanchor_global_RB_REMOVE_COLOR( arg1: *mut pf_kanchor_global, arg2: *mut pf_kanchor, arg3: *mut pf_kanchor, ) -> *mut pf_kanchor; } unsafe extern "C" { pub fn pf_kanchor_global_RB_INSERT_FINISH( arg1: *mut pf_kanchor_global, arg2: *mut pf_kanchor, arg3: *mut *mut pf_kanchor, arg4: *mut pf_kanchor, ) -> *mut pf_kanchor; } unsafe extern "C" { pub fn pf_kanchor_global_RB_INSERT(arg1: *mut pf_kanchor_global, arg2: *mut pf_kanchor) -> *mut pf_kanchor; } unsafe extern "C" { pub fn pf_kanchor_global_RB_REMOVE(arg1: *mut pf_kanchor_global, arg2: *mut pf_kanchor) -> *mut pf_kanchor; } unsafe extern "C" { pub fn pf_kanchor_global_RB_FIND(arg1: *mut pf_kanchor_global, arg2: *mut pf_kanchor) -> *mut pf_kanchor; } unsafe extern "C" { pub fn pf_kanchor_global_RB_NFIND(arg1: *mut pf_kanchor_global, arg2: *mut pf_kanchor) -> *mut pf_kanchor; } unsafe extern "C" { pub fn pf_kanchor_global_RB_NEXT(arg1: *mut pf_kanchor) -> *mut pf_kanchor; } unsafe extern "C" { pub fn pf_kanchor_global_RB_INSERT_NEXT( arg1: *mut pf_kanchor_global, arg2: *mut pf_kanchor, arg3: *mut pf_kanchor, ) -> *mut pf_kanchor; } unsafe extern "C" { pub fn pf_kanchor_global_RB_PREV(arg1: *mut pf_kanchor) -> *mut pf_kanchor; } unsafe extern "C" { pub fn pf_kanchor_global_RB_INSERT_PREV( arg1: *mut pf_kanchor_global, arg2: *mut pf_kanchor, arg3: *mut pf_kanchor, ) -> *mut pf_kanchor; } unsafe extern "C" { pub fn pf_kanchor_global_RB_MINMAX(arg1: *mut pf_kanchor_global, arg2: ::std::os::raw::c_int) -> *mut pf_kanchor; } unsafe extern "C" { pub fn pf_kanchor_global_RB_REINSERT(arg1: *mut pf_kanchor_global, arg2: *mut pf_kanchor) -> *mut pf_kanchor; } unsafe extern "C" { pub fn pf_kanchor_node_RB_INSERT_COLOR( arg1: *mut pf_kanchor_node, arg2: *mut pf_kanchor, arg3: *mut pf_kanchor, ) -> *mut pf_kanchor; } unsafe extern "C" { pub fn pf_kanchor_node_RB_REMOVE_COLOR( arg1: *mut pf_kanchor_node, arg2: *mut pf_kanchor, arg3: *mut pf_kanchor, ) -> *mut pf_kanchor; } unsafe extern "C" { pub fn pf_kanchor_node_RB_INSERT_FINISH( arg1: *mut pf_kanchor_node, arg2: *mut pf_kanchor, arg3: *mut *mut pf_kanchor, arg4: *mut pf_kanchor, ) -> *mut pf_kanchor; } unsafe extern "C" { pub fn pf_kanchor_node_RB_INSERT(arg1: *mut pf_kanchor_node, arg2: *mut pf_kanchor) -> *mut pf_kanchor; } unsafe extern "C" { pub fn pf_kanchor_node_RB_REMOVE(arg1: *mut pf_kanchor_node, arg2: *mut pf_kanchor) -> *mut pf_kanchor; } unsafe extern "C" { pub fn pf_kanchor_node_RB_FIND(arg1: *mut pf_kanchor_node, arg2: *mut pf_kanchor) -> *mut pf_kanchor; } unsafe extern "C" { pub fn pf_kanchor_node_RB_NFIND(arg1: *mut pf_kanchor_node, arg2: *mut pf_kanchor) -> *mut pf_kanchor; } unsafe extern "C" { pub fn pf_kanchor_node_RB_NEXT(arg1: *mut pf_kanchor) -> *mut pf_kanchor; } unsafe extern "C" { pub fn pf_kanchor_node_RB_INSERT_NEXT( arg1: *mut pf_kanchor_node, arg2: *mut pf_kanchor, arg3: *mut pf_kanchor, ) -> *mut pf_kanchor; } unsafe extern "C" { pub fn pf_kanchor_node_RB_PREV(arg1: *mut pf_kanchor) -> *mut pf_kanchor; } unsafe extern "C" { pub fn pf_kanchor_node_RB_INSERT_PREV( arg1: *mut pf_kanchor_node, arg2: *mut pf_kanchor, arg3: *mut pf_kanchor, ) -> *mut pf_kanchor; } unsafe extern "C" { pub fn pf_kanchor_node_RB_MINMAX(arg1: *mut pf_kanchor_node, arg2: ::std::os::raw::c_int) -> *mut pf_kanchor; } unsafe extern "C" { pub fn pf_kanchor_node_RB_REINSERT(arg1: *mut pf_kanchor_node, arg2: *mut pf_kanchor) -> *mut pf_kanchor; } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pf_kanchor_stackframe { _unused: [u8; 0], } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pf_keth_anchor_stackframe { _unused: [u8; 0], } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pfr_table { pub pfrt_anchor: [::std::os::raw::c_char; 1024usize], pub pfrt_name: [::std::os::raw::c_char; 32usize], pub pfrt_flags: u_int32_t, pub pfrt_fback: u_int8_t, } #[test] fn bindgen_test_layout_pfr_table() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 1064usize, concat!("Size of: ", stringify!(pfr_table)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(pfr_table)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfrt_anchor) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pfr_table), "::", stringify!(pfrt_anchor) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfrt_name) as usize - ptr as usize }, 1024usize, concat!("Offset of field: ", stringify!(pfr_table), "::", stringify!(pfrt_name)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfrt_flags) as usize - ptr as usize }, 1056usize, concat!("Offset of field: ", stringify!(pfr_table), "::", stringify!(pfrt_flags)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfrt_fback) as usize - ptr as usize }, 1060usize, concat!("Offset of field: ", stringify!(pfr_table), "::", stringify!(pfrt_fback)) ); } pub const PFR_FB_NONE: _bindgen_ty_15 = 0; pub const PFR_FB_MATCH: _bindgen_ty_15 = 1; pub const PFR_FB_ADDED: _bindgen_ty_15 = 2; pub const PFR_FB_DELETED: _bindgen_ty_15 = 3; pub const PFR_FB_CHANGED: _bindgen_ty_15 = 4; pub const PFR_FB_CLEARED: _bindgen_ty_15 = 5; pub const PFR_FB_DUPLICATE: _bindgen_ty_15 = 6; pub const PFR_FB_NOTMATCH: _bindgen_ty_15 = 7; pub const PFR_FB_CONFLICT: _bindgen_ty_15 = 8; pub const PFR_FB_NOCOUNT: _bindgen_ty_15 = 9; pub const PFR_FB_MAX: _bindgen_ty_15 = 10; pub type _bindgen_ty_15 = ::std::os::raw::c_uint; #[repr(C)] #[derive(Copy, Clone)] pub struct pfr_addr { pub pfra_u: pfr_addr__bindgen_ty_1, pub pfra_af: u_int8_t, pub pfra_net: u_int8_t, pub pfra_not: u_int8_t, pub pfra_fback: u_int8_t, } #[repr(C)] #[derive(Copy, Clone)] pub union pfr_addr__bindgen_ty_1 { pub _pfra_ip4addr: in_addr, pub _pfra_ip6addr: in6_addr, } #[test] fn bindgen_test_layout_pfr_addr__bindgen_ty_1() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 16usize, concat!("Size of: ", stringify!(pfr_addr__bindgen_ty_1)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(pfr_addr__bindgen_ty_1)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr)._pfra_ip4addr) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pfr_addr__bindgen_ty_1), "::", stringify!(_pfra_ip4addr) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr)._pfra_ip6addr) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pfr_addr__bindgen_ty_1), "::", stringify!(_pfra_ip6addr) ) ); } #[test] fn bindgen_test_layout_pfr_addr() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 20usize, concat!("Size of: ", stringify!(pfr_addr)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(pfr_addr)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfra_u) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(pfr_addr), "::", stringify!(pfra_u)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfra_af) as usize - ptr as usize }, 16usize, concat!("Offset of field: ", stringify!(pfr_addr), "::", stringify!(pfra_af)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfra_net) as usize - ptr as usize }, 17usize, concat!("Offset of field: ", stringify!(pfr_addr), "::", stringify!(pfra_net)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfra_not) as usize - ptr as usize }, 18usize, concat!("Offset of field: ", stringify!(pfr_addr), "::", stringify!(pfra_not)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfra_fback) as usize - ptr as usize }, 19usize, concat!("Offset of field: ", stringify!(pfr_addr), "::", stringify!(pfra_fback)) ); } pub const PFR_DIR_IN: _bindgen_ty_16 = 0; pub const PFR_DIR_OUT: _bindgen_ty_16 = 1; pub const PFR_DIR_MAX: _bindgen_ty_16 = 2; pub type _bindgen_ty_16 = ::std::os::raw::c_uint; pub const PFR_OP_BLOCK: _bindgen_ty_17 = 0; pub const PFR_OP_PASS: _bindgen_ty_17 = 1; pub const PFR_OP_ADDR_MAX: _bindgen_ty_17 = 2; pub const PFR_OP_TABLE_MAX: _bindgen_ty_17 = 3; pub type _bindgen_ty_17 = ::std::os::raw::c_uint; pub const PFR_TYPE_PACKETS: _bindgen_ty_18 = 0; pub const PFR_TYPE_BYTES: _bindgen_ty_18 = 1; pub const PFR_TYPE_MAX: _bindgen_ty_18 = 2; pub type _bindgen_ty_18 = ::std::os::raw::c_uint; #[repr(C)] #[derive(Copy, Clone)] pub struct pfr_astats { pub pfras_a: pfr_addr, pub pfras_packets: [[u_int64_t; 2usize]; 2usize], pub pfras_bytes: [[u_int64_t; 2usize]; 2usize], pub pfras_tzero: ::std::os::raw::c_long, } #[test] fn bindgen_test_layout_pfr_astats() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 96usize, concat!("Size of: ", stringify!(pfr_astats)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pfr_astats)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfras_a) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(pfr_astats), "::", stringify!(pfras_a)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfras_packets) as usize - ptr as usize }, 24usize, concat!( "Offset of field: ", stringify!(pfr_astats), "::", stringify!(pfras_packets) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfras_bytes) as usize - ptr as usize }, 56usize, concat!( "Offset of field: ", stringify!(pfr_astats), "::", stringify!(pfras_bytes) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfras_tzero) as usize - ptr as usize }, 88usize, concat!( "Offset of field: ", stringify!(pfr_astats), "::", stringify!(pfras_tzero) ) ); } pub const PFR_REFCNT_RULE: _bindgen_ty_19 = 0; pub const PFR_REFCNT_ANCHOR: _bindgen_ty_19 = 1; pub const PFR_REFCNT_MAX: _bindgen_ty_19 = 2; pub type _bindgen_ty_19 = ::std::os::raw::c_uint; #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pfr_tstats { pub pfrts_t: pfr_table, pub pfrts_packets: [[u_int64_t; 3usize]; 2usize], pub pfrts_bytes: [[u_int64_t; 3usize]; 2usize], pub pfrts_match: u_int64_t, pub pfrts_nomatch: u_int64_t, pub pfrts_tzero: ::std::os::raw::c_long, pub pfrts_cnt: ::std::os::raw::c_int, pub pfrts_refcnt: [::std::os::raw::c_int; 2usize], } #[test] fn bindgen_test_layout_pfr_tstats() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 1200usize, concat!("Size of: ", stringify!(pfr_tstats)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pfr_tstats)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfrts_t) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(pfr_tstats), "::", stringify!(pfrts_t)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfrts_packets) as usize - ptr as usize }, 1064usize, concat!( "Offset of field: ", stringify!(pfr_tstats), "::", stringify!(pfrts_packets) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfrts_bytes) as usize - ptr as usize }, 1112usize, concat!( "Offset of field: ", stringify!(pfr_tstats), "::", stringify!(pfrts_bytes) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfrts_match) as usize - ptr as usize }, 1160usize, concat!( "Offset of field: ", stringify!(pfr_tstats), "::", stringify!(pfrts_match) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfrts_nomatch) as usize - ptr as usize }, 1168usize, concat!( "Offset of field: ", stringify!(pfr_tstats), "::", stringify!(pfrts_nomatch) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfrts_tzero) as usize - ptr as usize }, 1176usize, concat!( "Offset of field: ", stringify!(pfr_tstats), "::", stringify!(pfrts_tzero) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfrts_cnt) as usize - ptr as usize }, 1184usize, concat!("Offset of field: ", stringify!(pfr_tstats), "::", stringify!(pfrts_cnt)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfrts_refcnt) as usize - ptr as usize }, 1188usize, concat!( "Offset of field: ", stringify!(pfr_tstats), "::", stringify!(pfrts_refcnt) ) ); } #[repr(C)] #[derive(Copy, Clone)] pub union sockaddr_union { pub sa: sockaddr, pub sin: sockaddr_in, pub sin6: sockaddr_in6, } #[test] fn bindgen_test_layout_sockaddr_union() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 28usize, concat!("Size of: ", stringify!(sockaddr_union)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(sockaddr_union)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).sa) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(sockaddr_union), "::", stringify!(sa)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).sin) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(sockaddr_union), "::", stringify!(sin)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).sin6) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(sockaddr_union), "::", stringify!(sin6)) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pfr_kcounters { pub pfrkc_counters: counter_u64_t, pub pfrkc_tzero: ::std::os::raw::c_long, } #[test] fn bindgen_test_layout_pfr_kcounters() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 16usize, concat!("Size of: ", stringify!(pfr_kcounters)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pfr_kcounters)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfrkc_counters) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pfr_kcounters), "::", stringify!(pfrkc_counters) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfrkc_tzero) as usize - ptr as usize }, 8usize, concat!( "Offset of field: ", stringify!(pfr_kcounters), "::", stringify!(pfrkc_tzero) ) ); } pub const pf_syncookies_mode_PF_SYNCOOKIES_NEVER: pf_syncookies_mode = 0; pub const pf_syncookies_mode_PF_SYNCOOKIES_ALWAYS: pf_syncookies_mode = 1; pub const pf_syncookies_mode_PF_SYNCOOKIES_ADAPTIVE: pf_syncookies_mode = 2; pub const pf_syncookies_mode_PF_SYNCOOKIES_MODE_MAX: pf_syncookies_mode = 2; pub type pf_syncookies_mode = ::std::os::raw::c_uint; #[repr(C)] #[derive(Copy, Clone)] pub struct pf_divert { pub addr: pf_divert__bindgen_ty_1, pub port: u_int16_t, } #[repr(C)] #[derive(Copy, Clone)] pub union pf_divert__bindgen_ty_1 { pub ipv4: in_addr, pub ipv6: in6_addr, } #[test] fn bindgen_test_layout_pf_divert__bindgen_ty_1() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 16usize, concat!("Size of: ", stringify!(pf_divert__bindgen_ty_1)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(pf_divert__bindgen_ty_1)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ipv4) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pf_divert__bindgen_ty_1), "::", stringify!(ipv4) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ipv6) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pf_divert__bindgen_ty_1), "::", stringify!(ipv6) ) ); } #[test] fn bindgen_test_layout_pf_divert() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 20usize, concat!("Size of: ", stringify!(pf_divert)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(pf_divert)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).addr) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(pf_divert), "::", stringify!(addr)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).port) as usize - ptr as usize }, 16usize, concat!("Offset of field: ", stringify!(pf_divert), "::", stringify!(port)) ); } #[repr(C)] #[derive(Copy, Clone)] pub struct pfioc_pooladdr { pub action: u_int32_t, pub ticket: u_int32_t, pub nr: u_int32_t, pub r_num: u_int32_t, pub r_action: u_int8_t, pub r_last: u_int8_t, pub af: u_int8_t, pub anchor: [::std::os::raw::c_char; 1024usize], pub addr: pf_pooladdr, } #[test] fn bindgen_test_layout_pfioc_pooladdr() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 1136usize, concat!("Size of: ", stringify!(pfioc_pooladdr)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pfioc_pooladdr)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).action) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pfioc_pooladdr), "::", stringify!(action) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ticket) as usize - ptr as usize }, 4usize, concat!( "Offset of field: ", stringify!(pfioc_pooladdr), "::", stringify!(ticket) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).nr) as usize - ptr as usize }, 8usize, concat!("Offset of field: ", stringify!(pfioc_pooladdr), "::", stringify!(nr)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).r_num) as usize - ptr as usize }, 12usize, concat!("Offset of field: ", stringify!(pfioc_pooladdr), "::", stringify!(r_num)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).r_action) as usize - ptr as usize }, 16usize, concat!( "Offset of field: ", stringify!(pfioc_pooladdr), "::", stringify!(r_action) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).r_last) as usize - ptr as usize }, 17usize, concat!( "Offset of field: ", stringify!(pfioc_pooladdr), "::", stringify!(r_last) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).af) as usize - ptr as usize }, 18usize, concat!("Offset of field: ", stringify!(pfioc_pooladdr), "::", stringify!(af)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).anchor) as usize - ptr as usize }, 19usize, concat!( "Offset of field: ", stringify!(pfioc_pooladdr), "::", stringify!(anchor) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).addr) as usize - ptr as usize }, 1048usize, concat!("Offset of field: ", stringify!(pfioc_pooladdr), "::", stringify!(addr)) ); } #[repr(C)] #[derive(Copy, Clone)] pub struct pfioc_rule { pub action: u_int32_t, pub ticket: u_int32_t, pub pool_ticket: u_int32_t, pub nr: u_int32_t, pub anchor: [::std::os::raw::c_char; 1024usize], pub anchor_call: [::std::os::raw::c_char; 1024usize], pub rule: pf_rule, } #[test] fn bindgen_test_layout_pfioc_rule() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 3040usize, concat!("Size of: ", stringify!(pfioc_rule)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pfioc_rule)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).action) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(pfioc_rule), "::", stringify!(action)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ticket) as usize - ptr as usize }, 4usize, concat!("Offset of field: ", stringify!(pfioc_rule), "::", stringify!(ticket)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pool_ticket) as usize - ptr as usize }, 8usize, concat!( "Offset of field: ", stringify!(pfioc_rule), "::", stringify!(pool_ticket) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).nr) as usize - ptr as usize }, 12usize, concat!("Offset of field: ", stringify!(pfioc_rule), "::", stringify!(nr)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).anchor) as usize - ptr as usize }, 16usize, concat!("Offset of field: ", stringify!(pfioc_rule), "::", stringify!(anchor)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).anchor_call) as usize - ptr as usize }, 1040usize, concat!( "Offset of field: ", stringify!(pfioc_rule), "::", stringify!(anchor_call) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rule) as usize - ptr as usize }, 2064usize, concat!("Offset of field: ", stringify!(pfioc_rule), "::", stringify!(rule)) ); } #[repr(C)] #[derive(Copy, Clone)] pub struct pfioc_natlook { pub saddr: pf_addr, pub daddr: pf_addr, pub rsaddr: pf_addr, pub rdaddr: pf_addr, pub sport: u_int16_t, pub dport: u_int16_t, pub rsport: u_int16_t, pub rdport: u_int16_t, pub af: sa_family_t, pub proto: u_int8_t, pub direction: u_int8_t, } #[test] fn bindgen_test_layout_pfioc_natlook() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 76usize, concat!("Size of: ", stringify!(pfioc_natlook)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(pfioc_natlook)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).saddr) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(pfioc_natlook), "::", stringify!(saddr)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).daddr) as usize - ptr as usize }, 16usize, concat!("Offset of field: ", stringify!(pfioc_natlook), "::", stringify!(daddr)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rsaddr) as usize - ptr as usize }, 32usize, concat!("Offset of field: ", stringify!(pfioc_natlook), "::", stringify!(rsaddr)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rdaddr) as usize - ptr as usize }, 48usize, concat!("Offset of field: ", stringify!(pfioc_natlook), "::", stringify!(rdaddr)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).sport) as usize - ptr as usize }, 64usize, concat!("Offset of field: ", stringify!(pfioc_natlook), "::", stringify!(sport)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).dport) as usize - ptr as usize }, 66usize, concat!("Offset of field: ", stringify!(pfioc_natlook), "::", stringify!(dport)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rsport) as usize - ptr as usize }, 68usize, concat!("Offset of field: ", stringify!(pfioc_natlook), "::", stringify!(rsport)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rdport) as usize - ptr as usize }, 70usize, concat!("Offset of field: ", stringify!(pfioc_natlook), "::", stringify!(rdport)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).af) as usize - ptr as usize }, 72usize, concat!("Offset of field: ", stringify!(pfioc_natlook), "::", stringify!(af)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).proto) as usize - ptr as usize }, 73usize, concat!("Offset of field: ", stringify!(pfioc_natlook), "::", stringify!(proto)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).direction) as usize - ptr as usize }, 74usize, concat!( "Offset of field: ", stringify!(pfioc_natlook), "::", stringify!(direction) ) ); } #[repr(C)] #[derive(Copy, Clone)] pub struct pfioc_state { pub state: pfsync_state_1301, } #[test] fn bindgen_test_layout_pfioc_state() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 242usize, concat!("Size of: ", stringify!(pfioc_state)) ); assert_eq!( ::std::mem::align_of::(), 1usize, concat!("Alignment of ", stringify!(pfioc_state)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).state) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(pfioc_state), "::", stringify!(state)) ); } #[repr(C)] #[derive(Copy, Clone)] pub struct pfioc_src_node_kill { pub psnk_af: sa_family_t, pub psnk_src: pf_rule_addr, pub psnk_dst: pf_rule_addr, pub psnk_killed: u_int, } #[test] fn bindgen_test_layout_pfioc_src_node_kill() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 128usize, concat!("Size of: ", stringify!(pfioc_src_node_kill)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pfioc_src_node_kill)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).psnk_af) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pfioc_src_node_kill), "::", stringify!(psnk_af) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).psnk_src) as usize - ptr as usize }, 8usize, concat!( "Offset of field: ", stringify!(pfioc_src_node_kill), "::", stringify!(psnk_src) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).psnk_dst) as usize - ptr as usize }, 64usize, concat!( "Offset of field: ", stringify!(pfioc_src_node_kill), "::", stringify!(psnk_dst) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).psnk_killed) as usize - ptr as usize }, 120usize, concat!( "Offset of field: ", stringify!(pfioc_src_node_kill), "::", stringify!(psnk_killed) ) ); } #[repr(C)] #[derive(Copy, Clone)] pub struct pfioc_state_kill { pub psk_pfcmp: pf_state_cmp, pub psk_af: sa_family_t, pub psk_proto: ::std::os::raw::c_int, pub psk_src: pf_rule_addr, pub psk_dst: pf_rule_addr, pub psk_ifname: [::std::os::raw::c_char; 16usize], pub psk_label: [::std::os::raw::c_char; 64usize], pub psk_killed: u_int, } #[test] fn bindgen_test_layout_pfioc_state_kill() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 224usize, concat!("Size of: ", stringify!(pfioc_state_kill)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pfioc_state_kill)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).psk_pfcmp) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pfioc_state_kill), "::", stringify!(psk_pfcmp) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).psk_af) as usize - ptr as usize }, 16usize, concat!( "Offset of field: ", stringify!(pfioc_state_kill), "::", stringify!(psk_af) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).psk_proto) as usize - ptr as usize }, 20usize, concat!( "Offset of field: ", stringify!(pfioc_state_kill), "::", stringify!(psk_proto) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).psk_src) as usize - ptr as usize }, 24usize, concat!( "Offset of field: ", stringify!(pfioc_state_kill), "::", stringify!(psk_src) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).psk_dst) as usize - ptr as usize }, 80usize, concat!( "Offset of field: ", stringify!(pfioc_state_kill), "::", stringify!(psk_dst) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).psk_ifname) as usize - ptr as usize }, 136usize, concat!( "Offset of field: ", stringify!(pfioc_state_kill), "::", stringify!(psk_ifname) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).psk_label) as usize - ptr as usize }, 152usize, concat!( "Offset of field: ", stringify!(pfioc_state_kill), "::", stringify!(psk_label) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).psk_killed) as usize - ptr as usize }, 216usize, concat!( "Offset of field: ", stringify!(pfioc_state_kill), "::", stringify!(psk_killed) ) ); } #[repr(C)] #[derive(Copy, Clone)] pub struct pfioc_states { pub ps_len: ::std::os::raw::c_int, pub __bindgen_anon_1: pfioc_states__bindgen_ty_1, } #[repr(C)] #[derive(Copy, Clone)] pub union pfioc_states__bindgen_ty_1 { pub ps_buf: *mut ::std::os::raw::c_void, pub ps_states: *mut pfsync_state_1301, } #[test] fn bindgen_test_layout_pfioc_states__bindgen_ty_1() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 8usize, concat!("Size of: ", stringify!(pfioc_states__bindgen_ty_1)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pfioc_states__bindgen_ty_1)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ps_buf) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pfioc_states__bindgen_ty_1), "::", stringify!(ps_buf) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ps_states) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pfioc_states__bindgen_ty_1), "::", stringify!(ps_states) ) ); } #[test] fn bindgen_test_layout_pfioc_states() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 16usize, concat!("Size of: ", stringify!(pfioc_states)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pfioc_states)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ps_len) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(pfioc_states), "::", stringify!(ps_len)) ); } #[repr(C)] #[derive(Copy, Clone)] pub struct pfioc_states_v2 { pub ps_len: ::std::os::raw::c_int, pub ps_req_version: u64, pub __bindgen_anon_1: pfioc_states_v2__bindgen_ty_1, } #[repr(C)] #[derive(Copy, Clone)] pub union pfioc_states_v2__bindgen_ty_1 { pub ps_buf: *mut ::std::os::raw::c_void, pub ps_states: *mut pf_state_export, } #[test] fn bindgen_test_layout_pfioc_states_v2__bindgen_ty_1() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 8usize, concat!("Size of: ", stringify!(pfioc_states_v2__bindgen_ty_1)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pfioc_states_v2__bindgen_ty_1)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ps_buf) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pfioc_states_v2__bindgen_ty_1), "::", stringify!(ps_buf) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ps_states) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pfioc_states_v2__bindgen_ty_1), "::", stringify!(ps_states) ) ); } #[test] fn bindgen_test_layout_pfioc_states_v2() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 24usize, concat!("Size of: ", stringify!(pfioc_states_v2)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pfioc_states_v2)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ps_len) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pfioc_states_v2), "::", stringify!(ps_len) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ps_req_version) as usize - ptr as usize }, 8usize, concat!( "Offset of field: ", stringify!(pfioc_states_v2), "::", stringify!(ps_req_version) ) ); } #[repr(C)] #[derive(Copy, Clone)] pub struct pfioc_src_nodes { pub psn_len: ::std::os::raw::c_int, pub __bindgen_anon_1: pfioc_src_nodes__bindgen_ty_1, } #[repr(C)] #[derive(Copy, Clone)] pub union pfioc_src_nodes__bindgen_ty_1 { pub psn_buf: *mut ::std::os::raw::c_void, pub psn_src_nodes: *mut pf_src_node, } #[test] fn bindgen_test_layout_pfioc_src_nodes__bindgen_ty_1() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 8usize, concat!("Size of: ", stringify!(pfioc_src_nodes__bindgen_ty_1)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pfioc_src_nodes__bindgen_ty_1)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).psn_buf) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pfioc_src_nodes__bindgen_ty_1), "::", stringify!(psn_buf) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).psn_src_nodes) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pfioc_src_nodes__bindgen_ty_1), "::", stringify!(psn_src_nodes) ) ); } #[test] fn bindgen_test_layout_pfioc_src_nodes() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 16usize, concat!("Size of: ", stringify!(pfioc_src_nodes)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pfioc_src_nodes)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).psn_len) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pfioc_src_nodes), "::", stringify!(psn_len) ) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pfioc_if { pub ifname: [::std::os::raw::c_char; 16usize], } #[test] fn bindgen_test_layout_pfioc_if() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 16usize, concat!("Size of: ", stringify!(pfioc_if)) ); assert_eq!( ::std::mem::align_of::(), 1usize, concat!("Alignment of ", stringify!(pfioc_if)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifname) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(pfioc_if), "::", stringify!(ifname)) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pfioc_tm { pub timeout: ::std::os::raw::c_int, pub seconds: ::std::os::raw::c_int, } #[test] fn bindgen_test_layout_pfioc_tm() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 8usize, concat!("Size of: ", stringify!(pfioc_tm)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(pfioc_tm)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).timeout) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(pfioc_tm), "::", stringify!(timeout)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).seconds) as usize - ptr as usize }, 4usize, concat!("Offset of field: ", stringify!(pfioc_tm), "::", stringify!(seconds)) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pfioc_limit { pub index: ::std::os::raw::c_int, pub limit: ::std::os::raw::c_uint, } #[test] fn bindgen_test_layout_pfioc_limit() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 8usize, concat!("Size of: ", stringify!(pfioc_limit)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(pfioc_limit)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).index) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(pfioc_limit), "::", stringify!(index)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).limit) as usize - ptr as usize }, 4usize, concat!("Offset of field: ", stringify!(pfioc_limit), "::", stringify!(limit)) ); } #[repr(C)] #[derive(Copy, Clone)] pub struct pfioc_altq_v0 { pub action: u_int32_t, pub ticket: u_int32_t, pub nr: u_int32_t, pub altq: pf_altq_v0, } #[test] fn bindgen_test_layout_pfioc_altq_v0() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 256usize, concat!("Size of: ", stringify!(pfioc_altq_v0)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pfioc_altq_v0)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).action) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(pfioc_altq_v0), "::", stringify!(action)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ticket) as usize - ptr as usize }, 4usize, concat!("Offset of field: ", stringify!(pfioc_altq_v0), "::", stringify!(ticket)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).nr) as usize - ptr as usize }, 8usize, concat!("Offset of field: ", stringify!(pfioc_altq_v0), "::", stringify!(nr)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).altq) as usize - ptr as usize }, 16usize, concat!("Offset of field: ", stringify!(pfioc_altq_v0), "::", stringify!(altq)) ); } #[repr(C)] #[derive(Copy, Clone)] pub struct pfioc_altq_v1 { pub action: u_int32_t, pub ticket: u_int32_t, pub nr: u_int32_t, pub version: u_int32_t, pub altq: pf_altq_v1, } #[test] fn bindgen_test_layout_pfioc_altq_v1() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 304usize, concat!("Size of: ", stringify!(pfioc_altq_v1)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pfioc_altq_v1)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).action) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(pfioc_altq_v1), "::", stringify!(action)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ticket) as usize - ptr as usize }, 4usize, concat!("Offset of field: ", stringify!(pfioc_altq_v1), "::", stringify!(ticket)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).nr) as usize - ptr as usize }, 8usize, concat!("Offset of field: ", stringify!(pfioc_altq_v1), "::", stringify!(nr)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).version) as usize - ptr as usize }, 12usize, concat!( "Offset of field: ", stringify!(pfioc_altq_v1), "::", stringify!(version) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).altq) as usize - ptr as usize }, 16usize, concat!("Offset of field: ", stringify!(pfioc_altq_v1), "::", stringify!(altq)) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pfioc_qstats_v0 { pub ticket: u_int32_t, pub nr: u_int32_t, pub buf: *mut ::std::os::raw::c_void, pub nbytes: ::std::os::raw::c_int, pub scheduler: u_int8_t, } #[test] fn bindgen_test_layout_pfioc_qstats_v0() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 24usize, concat!("Size of: ", stringify!(pfioc_qstats_v0)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pfioc_qstats_v0)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ticket) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pfioc_qstats_v0), "::", stringify!(ticket) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).nr) as usize - ptr as usize }, 4usize, concat!("Offset of field: ", stringify!(pfioc_qstats_v0), "::", stringify!(nr)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).buf) as usize - ptr as usize }, 8usize, concat!("Offset of field: ", stringify!(pfioc_qstats_v0), "::", stringify!(buf)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).nbytes) as usize - ptr as usize }, 16usize, concat!( "Offset of field: ", stringify!(pfioc_qstats_v0), "::", stringify!(nbytes) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).scheduler) as usize - ptr as usize }, 20usize, concat!( "Offset of field: ", stringify!(pfioc_qstats_v0), "::", stringify!(scheduler) ) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pfioc_qstats_v1 { pub ticket: u_int32_t, pub nr: u_int32_t, pub buf: *mut ::std::os::raw::c_void, pub nbytes: ::std::os::raw::c_int, pub scheduler: u_int8_t, pub version: u_int32_t, } #[test] fn bindgen_test_layout_pfioc_qstats_v1() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 32usize, concat!("Size of: ", stringify!(pfioc_qstats_v1)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pfioc_qstats_v1)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ticket) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pfioc_qstats_v1), "::", stringify!(ticket) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).nr) as usize - ptr as usize }, 4usize, concat!("Offset of field: ", stringify!(pfioc_qstats_v1), "::", stringify!(nr)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).buf) as usize - ptr as usize }, 8usize, concat!("Offset of field: ", stringify!(pfioc_qstats_v1), "::", stringify!(buf)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).nbytes) as usize - ptr as usize }, 16usize, concat!( "Offset of field: ", stringify!(pfioc_qstats_v1), "::", stringify!(nbytes) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).scheduler) as usize - ptr as usize }, 20usize, concat!( "Offset of field: ", stringify!(pfioc_qstats_v1), "::", stringify!(scheduler) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).version) as usize - ptr as usize }, 24usize, concat!( "Offset of field: ", stringify!(pfioc_qstats_v1), "::", stringify!(version) ) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pfioc_ruleset { pub nr: u_int32_t, pub path: [::std::os::raw::c_char; 1024usize], pub name: [::std::os::raw::c_char; 64usize], } #[test] fn bindgen_test_layout_pfioc_ruleset() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 1092usize, concat!("Size of: ", stringify!(pfioc_ruleset)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(pfioc_ruleset)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).nr) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(pfioc_ruleset), "::", stringify!(nr)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).path) as usize - ptr as usize }, 4usize, concat!("Offset of field: ", stringify!(pfioc_ruleset), "::", stringify!(path)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).name) as usize - ptr as usize }, 1028usize, concat!("Offset of field: ", stringify!(pfioc_ruleset), "::", stringify!(name)) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pfioc_trans { pub size: ::std::os::raw::c_int, pub esize: ::std::os::raw::c_int, pub array: *mut pfioc_trans_pfioc_trans_e, } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pfioc_trans_pfioc_trans_e { pub rs_num: ::std::os::raw::c_int, pub anchor: [::std::os::raw::c_char; 1024usize], pub ticket: u_int32_t, } #[test] fn bindgen_test_layout_pfioc_trans_pfioc_trans_e() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 1032usize, concat!("Size of: ", stringify!(pfioc_trans_pfioc_trans_e)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(pfioc_trans_pfioc_trans_e)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rs_num) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pfioc_trans_pfioc_trans_e), "::", stringify!(rs_num) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).anchor) as usize - ptr as usize }, 4usize, concat!( "Offset of field: ", stringify!(pfioc_trans_pfioc_trans_e), "::", stringify!(anchor) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ticket) as usize - ptr as usize }, 1028usize, concat!( "Offset of field: ", stringify!(pfioc_trans_pfioc_trans_e), "::", stringify!(ticket) ) ); } #[test] fn bindgen_test_layout_pfioc_trans() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 16usize, concat!("Size of: ", stringify!(pfioc_trans)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pfioc_trans)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).size) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(pfioc_trans), "::", stringify!(size)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).esize) as usize - ptr as usize }, 4usize, concat!("Offset of field: ", stringify!(pfioc_trans), "::", stringify!(esize)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).array) as usize - ptr as usize }, 8usize, concat!("Offset of field: ", stringify!(pfioc_trans), "::", stringify!(array)) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pfioc_table { pub pfrio_table: pfr_table, pub pfrio_buffer: *mut ::std::os::raw::c_void, pub pfrio_esize: ::std::os::raw::c_int, pub pfrio_size: ::std::os::raw::c_int, pub pfrio_size2: ::std::os::raw::c_int, pub pfrio_nadd: ::std::os::raw::c_int, pub pfrio_ndel: ::std::os::raw::c_int, pub pfrio_nchange: ::std::os::raw::c_int, pub pfrio_flags: ::std::os::raw::c_int, pub pfrio_ticket: u_int32_t, } #[test] fn bindgen_test_layout_pfioc_table() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 1104usize, concat!("Size of: ", stringify!(pfioc_table)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pfioc_table)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfrio_table) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pfioc_table), "::", stringify!(pfrio_table) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfrio_buffer) as usize - ptr as usize }, 1064usize, concat!( "Offset of field: ", stringify!(pfioc_table), "::", stringify!(pfrio_buffer) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfrio_esize) as usize - ptr as usize }, 1072usize, concat!( "Offset of field: ", stringify!(pfioc_table), "::", stringify!(pfrio_esize) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfrio_size) as usize - ptr as usize }, 1076usize, concat!( "Offset of field: ", stringify!(pfioc_table), "::", stringify!(pfrio_size) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfrio_size2) as usize - ptr as usize }, 1080usize, concat!( "Offset of field: ", stringify!(pfioc_table), "::", stringify!(pfrio_size2) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfrio_nadd) as usize - ptr as usize }, 1084usize, concat!( "Offset of field: ", stringify!(pfioc_table), "::", stringify!(pfrio_nadd) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfrio_ndel) as usize - ptr as usize }, 1088usize, concat!( "Offset of field: ", stringify!(pfioc_table), "::", stringify!(pfrio_ndel) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfrio_nchange) as usize - ptr as usize }, 1092usize, concat!( "Offset of field: ", stringify!(pfioc_table), "::", stringify!(pfrio_nchange) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfrio_flags) as usize - ptr as usize }, 1096usize, concat!( "Offset of field: ", stringify!(pfioc_table), "::", stringify!(pfrio_flags) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfrio_ticket) as usize - ptr as usize }, 1100usize, concat!( "Offset of field: ", stringify!(pfioc_table), "::", stringify!(pfrio_ticket) ) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pfioc_iface { pub pfiio_name: [::std::os::raw::c_char; 16usize], pub pfiio_buffer: *mut ::std::os::raw::c_void, pub pfiio_esize: ::std::os::raw::c_int, pub pfiio_size: ::std::os::raw::c_int, pub pfiio_nzero: ::std::os::raw::c_int, pub pfiio_flags: ::std::os::raw::c_int, } #[test] fn bindgen_test_layout_pfioc_iface() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 40usize, concat!("Size of: ", stringify!(pfioc_iface)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pfioc_iface)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfiio_name) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pfioc_iface), "::", stringify!(pfiio_name) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfiio_buffer) as usize - ptr as usize }, 16usize, concat!( "Offset of field: ", stringify!(pfioc_iface), "::", stringify!(pfiio_buffer) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfiio_esize) as usize - ptr as usize }, 24usize, concat!( "Offset of field: ", stringify!(pfioc_iface), "::", stringify!(pfiio_esize) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfiio_size) as usize - ptr as usize }, 28usize, concat!( "Offset of field: ", stringify!(pfioc_iface), "::", stringify!(pfiio_size) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfiio_nzero) as usize - ptr as usize }, 32usize, concat!( "Offset of field: ", stringify!(pfioc_iface), "::", stringify!(pfiio_nzero) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfiio_flags) as usize - ptr as usize }, 36usize, concat!( "Offset of field: ", stringify!(pfioc_iface), "::", stringify!(pfiio_flags) ) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pf_ifspeed_v0 { pub ifname: [::std::os::raw::c_char; 16usize], pub baudrate: u_int32_t, } #[test] fn bindgen_test_layout_pf_ifspeed_v0() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 20usize, concat!("Size of: ", stringify!(pf_ifspeed_v0)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(pf_ifspeed_v0)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifname) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(pf_ifspeed_v0), "::", stringify!(ifname)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).baudrate) as usize - ptr as usize }, 16usize, concat!( "Offset of field: ", stringify!(pf_ifspeed_v0), "::", stringify!(baudrate) ) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pf_ifspeed_v1 { pub ifname: [::std::os::raw::c_char; 16usize], pub baudrate32: u_int32_t, pub baudrate: u_int64_t, } #[test] fn bindgen_test_layout_pf_ifspeed_v1() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 32usize, concat!("Size of: ", stringify!(pf_ifspeed_v1)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pf_ifspeed_v1)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifname) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(pf_ifspeed_v1), "::", stringify!(ifname)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).baudrate32) as usize - ptr as usize }, 16usize, concat!( "Offset of field: ", stringify!(pf_ifspeed_v1), "::", stringify!(baudrate32) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).baudrate) as usize - ptr as usize }, 24usize, concat!( "Offset of field: ", stringify!(pf_ifspeed_v1), "::", stringify!(baudrate) ) ); } unsafe extern "C" { pub fn pf_osfp_add(arg1: *mut pf_osfp_ioctl) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn pf_osfp_flush(); } unsafe extern "C" { pub fn pf_osfp_get(arg1: *mut pf_osfp_ioctl) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn pf_osfp_match(arg1: *mut pf_os_fingerprint_pf_osfp_enlist, arg2: pf_osfp_t) -> ::std::os::raw::c_int; } pub type __builtin_va_list = [__va_list_tag; 1usize]; #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct __va_list_tag { pub gp_offset: ::std::os::raw::c_uint, pub fp_offset: ::std::os::raw::c_uint, pub overflow_arg_area: *mut ::std::os::raw::c_void, pub reg_save_area: *mut ::std::os::raw::c_void, } #[test] fn bindgen_test_layout___va_list_tag() { const UNINIT: ::std::mem::MaybeUninit<__va_list_tag> = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::<__va_list_tag>(), 24usize, concat!("Size of: ", stringify!(__va_list_tag)) ); assert_eq!( ::std::mem::align_of::<__va_list_tag>(), 8usize, concat!("Alignment of ", stringify!(__va_list_tag)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).gp_offset) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(__va_list_tag), "::", stringify!(gp_offset) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).fp_offset) as usize - ptr as usize }, 4usize, concat!( "Offset of field: ", stringify!(__va_list_tag), "::", stringify!(fp_offset) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).overflow_arg_area) as usize - ptr as usize }, 8usize, concat!( "Offset of field: ", stringify!(__va_list_tag), "::", stringify!(overflow_arg_area) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).reg_save_area) as usize - ptr as usize }, 16usize, concat!( "Offset of field: ", stringify!(__va_list_tag), "::", stringify!(reg_save_area) ) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct witness { pub _address: u8, } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct llentry { pub _address: u8, } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct ifg_group { pub _address: u8, } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pfi_dynaddr { pub _address: u8, } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pfr_ktable { pub _address: u8, } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pf_kstate { pub _address: u8, } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pf_krule { pub _address: u8, } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pf_krule_global { pub _address: u8, } ================================================ FILE: crates/shadowsocks-service/src/local/redir/sys/unix/pfvar_bindgen_macos.rs ================================================ // automatically generated by rust-bindgen 0.69.2 #[repr(C)] #[derive(Copy, Clone, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)] pub struct __BindgenBitfieldUnit { storage: Storage, } impl __BindgenBitfieldUnit { #[inline] pub const fn new(storage: Storage) -> Self { Self { storage } } } impl __BindgenBitfieldUnit where Storage: AsRef<[u8]> + AsMut<[u8]>, { #[inline] pub fn get_bit(&self, index: usize) -> bool { debug_assert!(index / 8 < self.storage.as_ref().len()); let byte_index = index / 8; let byte = self.storage.as_ref()[byte_index]; let bit_index = if cfg!(target_endian = "big") { 7 - (index % 8) } else { index % 8 }; let mask = 1 << bit_index; byte & mask == mask } #[inline] pub fn set_bit(&mut self, index: usize, val: bool) { debug_assert!(index / 8 < self.storage.as_ref().len()); let byte_index = index / 8; let byte = &mut self.storage.as_mut()[byte_index]; let bit_index = if cfg!(target_endian = "big") { 7 - (index % 8) } else { index % 8 }; let mask = 1 << bit_index; if val { *byte |= mask; } else { *byte &= !mask; } } #[inline] pub fn get(&self, bit_offset: usize, bit_width: u8) -> u64 { debug_assert!(bit_width <= 64); debug_assert!(bit_offset / 8 < self.storage.as_ref().len()); debug_assert!((bit_offset + (bit_width as usize)) / 8 <= self.storage.as_ref().len()); let mut val = 0; for i in 0..(bit_width as usize) { if self.get_bit(i + bit_offset) { let index = if cfg!(target_endian = "big") { bit_width as usize - 1 - i } else { i }; val |= 1 << index; } } val } #[inline] pub fn set(&mut self, bit_offset: usize, bit_width: u8, val: u64) { debug_assert!(bit_width <= 64); debug_assert!(bit_offset / 8 < self.storage.as_ref().len()); debug_assert!((bit_offset + (bit_width as usize)) / 8 <= self.storage.as_ref().len()); for i in 0..(bit_width as usize) { let mask = 1 << i; let val_bit_is_set = val & mask == mask; let index = if cfg!(target_endian = "big") { bit_width as usize - 1 - i } else { i }; self.set_bit(index + bit_offset, val_bit_is_set); } } } pub const __bool_true_false_are_defined: u32 = 1; pub const true_: u32 = 1; pub const false_: u32 = 0; pub const BSD: u32 = 199506; pub const BSD4_3: u32 = 1; pub const BSD4_4: u32 = 1; pub const NeXTBSD: u32 = 1995064; pub const NeXTBSD4_0: u32 = 0; pub const __DARWIN_UNIX03: u32 = 1; pub const __DARWIN_64_BIT_INO_T: u32 = 1; pub const __DARWIN_VERS_1050: u32 = 1; pub const __DARWIN_NON_CANCELABLE: u32 = 0; pub const __DARWIN_SUF_UNIX03: &[u8; 10] = b"$UNIX2003\0"; pub const __DARWIN_SUF_64_BIT_INO_T: &[u8; 9] = b"$INODE64\0"; pub const __DARWIN_SUF_1050: &[u8; 6] = b"$1050\0"; pub const __DARWIN_SUF_EXTSN: &[u8; 14] = b"$DARWIN_EXTSN\0"; pub const __DARWIN_C_ANSI: u32 = 4096; pub const __DARWIN_C_FULL: u32 = 900000; pub const __DARWIN_C_LEVEL: u32 = 900000; pub const __STDC_WANT_LIB_EXT1__: u32 = 1; pub const __DARWIN_NO_LONG_LONG: u32 = 0; pub const _DARWIN_FEATURE_64_BIT_INODE: u32 = 1; pub const _DARWIN_FEATURE_UNIX_CONFORMANCE: u32 = 3; pub const __PTHREAD_SIZE__: u32 = 8176; pub const __PTHREAD_ATTR_SIZE__: u32 = 56; pub const __PTHREAD_MUTEXATTR_SIZE__: u32 = 8; pub const __PTHREAD_MUTEX_SIZE__: u32 = 56; pub const __PTHREAD_CONDATTR_SIZE__: u32 = 8; pub const __PTHREAD_COND_SIZE__: u32 = 40; pub const __PTHREAD_ONCE_SIZE__: u32 = 8; pub const __PTHREAD_RWLOCK_SIZE__: u32 = 192; pub const __PTHREAD_RWLOCKATTR_SIZE__: u32 = 16; pub const _QUAD_HIGHWORD: u32 = 1; pub const _QUAD_LOWWORD: u32 = 0; pub const __DARWIN_LITTLE_ENDIAN: u32 = 1234; pub const __DARWIN_BIG_ENDIAN: u32 = 4321; pub const __DARWIN_PDP_ENDIAN: u32 = 3412; pub const __DARWIN_BYTE_ORDER: u32 = 1234; pub const LITTLE_ENDIAN: u32 = 1234; pub const BIG_ENDIAN: u32 = 4321; pub const PDP_ENDIAN: u32 = 3412; pub const BYTE_ORDER: u32 = 1234; pub const __API_TO_BE_DEPRECATED: u32 = 100000; pub const __API_TO_BE_DEPRECATED_MACOS: u32 = 100000; pub const __API_TO_BE_DEPRECATED_IOS: u32 = 100000; pub const __API_TO_BE_DEPRECATED_MACCATALYST: u32 = 100000; pub const __API_TO_BE_DEPRECATED_WATCHOS: u32 = 100000; pub const __API_TO_BE_DEPRECATED_TVOS: u32 = 100000; pub const __API_TO_BE_DEPRECATED_DRIVERKIT: u32 = 100000; pub const __API_TO_BE_DEPRECATED_VISIONOS: u32 = 100000; pub const __MAC_10_0: u32 = 1000; pub const __MAC_10_1: u32 = 1010; pub const __MAC_10_2: u32 = 1020; pub const __MAC_10_3: u32 = 1030; pub const __MAC_10_4: u32 = 1040; pub const __MAC_10_5: u32 = 1050; pub const __MAC_10_6: u32 = 1060; pub const __MAC_10_7: u32 = 1070; pub const __MAC_10_8: u32 = 1080; pub const __MAC_10_9: u32 = 1090; pub const __MAC_10_10: u32 = 101000; pub const __MAC_10_10_2: u32 = 101002; pub const __MAC_10_10_3: u32 = 101003; pub const __MAC_10_11: u32 = 101100; pub const __MAC_10_11_2: u32 = 101102; pub const __MAC_10_11_3: u32 = 101103; pub const __MAC_10_11_4: u32 = 101104; pub const __MAC_10_12: u32 = 101200; pub const __MAC_10_12_1: u32 = 101201; pub const __MAC_10_12_2: u32 = 101202; pub const __MAC_10_12_4: u32 = 101204; pub const __MAC_10_13: u32 = 101300; pub const __MAC_10_13_1: u32 = 101301; pub const __MAC_10_13_2: u32 = 101302; pub const __MAC_10_13_4: u32 = 101304; pub const __MAC_10_14: u32 = 101400; pub const __MAC_10_14_1: u32 = 101401; pub const __MAC_10_14_4: u32 = 101404; pub const __MAC_10_14_5: u32 = 101405; pub const __MAC_10_14_6: u32 = 101406; pub const __MAC_10_15: u32 = 101500; pub const __MAC_10_15_1: u32 = 101501; pub const __MAC_10_15_4: u32 = 101504; pub const __MAC_10_16: u32 = 101600; pub const __MAC_11_0: u32 = 110000; pub const __MAC_11_1: u32 = 110100; pub const __MAC_11_3: u32 = 110300; pub const __MAC_11_4: u32 = 110400; pub const __MAC_11_5: u32 = 110500; pub const __MAC_11_6: u32 = 110600; pub const __MAC_12_0: u32 = 120000; pub const __MAC_12_1: u32 = 120100; pub const __MAC_12_2: u32 = 120200; pub const __MAC_12_3: u32 = 120300; pub const __MAC_12_4: u32 = 120400; pub const __MAC_12_5: u32 = 120500; pub const __MAC_12_6: u32 = 120600; pub const __MAC_12_7: u32 = 120700; pub const __MAC_13_0: u32 = 130000; pub const __MAC_13_1: u32 = 130100; pub const __MAC_13_2: u32 = 130200; pub const __MAC_13_3: u32 = 130300; pub const __MAC_13_4: u32 = 130400; pub const __MAC_13_5: u32 = 130500; pub const __MAC_13_6: u32 = 130600; pub const __MAC_14_0: u32 = 140000; pub const __MAC_14_1: u32 = 140100; pub const __MAC_14_2: u32 = 140200; pub const __IPHONE_2_0: u32 = 20000; pub const __IPHONE_2_1: u32 = 20100; pub const __IPHONE_2_2: u32 = 20200; pub const __IPHONE_3_0: u32 = 30000; pub const __IPHONE_3_1: u32 = 30100; pub const __IPHONE_3_2: u32 = 30200; pub const __IPHONE_4_0: u32 = 40000; pub const __IPHONE_4_1: u32 = 40100; pub const __IPHONE_4_2: u32 = 40200; pub const __IPHONE_4_3: u32 = 40300; pub const __IPHONE_5_0: u32 = 50000; pub const __IPHONE_5_1: u32 = 50100; pub const __IPHONE_6_0: u32 = 60000; pub const __IPHONE_6_1: u32 = 60100; pub const __IPHONE_7_0: u32 = 70000; pub const __IPHONE_7_1: u32 = 70100; pub const __IPHONE_8_0: u32 = 80000; pub const __IPHONE_8_1: u32 = 80100; pub const __IPHONE_8_2: u32 = 80200; pub const __IPHONE_8_3: u32 = 80300; pub const __IPHONE_8_4: u32 = 80400; pub const __IPHONE_9_0: u32 = 90000; pub const __IPHONE_9_1: u32 = 90100; pub const __IPHONE_9_2: u32 = 90200; pub const __IPHONE_9_3: u32 = 90300; pub const __IPHONE_10_0: u32 = 100000; pub const __IPHONE_10_1: u32 = 100100; pub const __IPHONE_10_2: u32 = 100200; pub const __IPHONE_10_3: u32 = 100300; pub const __IPHONE_11_0: u32 = 110000; pub const __IPHONE_11_1: u32 = 110100; pub const __IPHONE_11_2: u32 = 110200; pub const __IPHONE_11_3: u32 = 110300; pub const __IPHONE_11_4: u32 = 110400; pub const __IPHONE_12_0: u32 = 120000; pub const __IPHONE_12_1: u32 = 120100; pub const __IPHONE_12_2: u32 = 120200; pub const __IPHONE_12_3: u32 = 120300; pub const __IPHONE_12_4: u32 = 120400; pub const __IPHONE_13_0: u32 = 130000; pub const __IPHONE_13_1: u32 = 130100; pub const __IPHONE_13_2: u32 = 130200; pub const __IPHONE_13_3: u32 = 130300; pub const __IPHONE_13_4: u32 = 130400; pub const __IPHONE_13_5: u32 = 130500; pub const __IPHONE_13_6: u32 = 130600; pub const __IPHONE_13_7: u32 = 130700; pub const __IPHONE_14_0: u32 = 140000; pub const __IPHONE_14_1: u32 = 140100; pub const __IPHONE_14_2: u32 = 140200; pub const __IPHONE_14_3: u32 = 140300; pub const __IPHONE_14_5: u32 = 140500; pub const __IPHONE_14_4: u32 = 140400; pub const __IPHONE_14_6: u32 = 140600; pub const __IPHONE_14_7: u32 = 140700; pub const __IPHONE_14_8: u32 = 140800; pub const __IPHONE_15_0: u32 = 150000; pub const __IPHONE_15_1: u32 = 150100; pub const __IPHONE_15_2: u32 = 150200; pub const __IPHONE_15_3: u32 = 150300; pub const __IPHONE_15_4: u32 = 150400; pub const __IPHONE_15_5: u32 = 150500; pub const __IPHONE_15_6: u32 = 150600; pub const __IPHONE_16_0: u32 = 160000; pub const __IPHONE_16_1: u32 = 160100; pub const __IPHONE_16_2: u32 = 160200; pub const __IPHONE_16_3: u32 = 160300; pub const __IPHONE_16_4: u32 = 160400; pub const __IPHONE_16_5: u32 = 160500; pub const __IPHONE_16_6: u32 = 160600; pub const __IPHONE_16_7: u32 = 160700; pub const __IPHONE_17_0: u32 = 170000; pub const __IPHONE_17_1: u32 = 170100; pub const __IPHONE_17_2: u32 = 170200; pub const __WATCHOS_1_0: u32 = 10000; pub const __WATCHOS_2_0: u32 = 20000; pub const __WATCHOS_2_1: u32 = 20100; pub const __WATCHOS_2_2: u32 = 20200; pub const __WATCHOS_3_0: u32 = 30000; pub const __WATCHOS_3_1: u32 = 30100; pub const __WATCHOS_3_1_1: u32 = 30101; pub const __WATCHOS_3_2: u32 = 30200; pub const __WATCHOS_4_0: u32 = 40000; pub const __WATCHOS_4_1: u32 = 40100; pub const __WATCHOS_4_2: u32 = 40200; pub const __WATCHOS_4_3: u32 = 40300; pub const __WATCHOS_5_0: u32 = 50000; pub const __WATCHOS_5_1: u32 = 50100; pub const __WATCHOS_5_2: u32 = 50200; pub const __WATCHOS_5_3: u32 = 50300; pub const __WATCHOS_6_0: u32 = 60000; pub const __WATCHOS_6_1: u32 = 60100; pub const __WATCHOS_6_2: u32 = 60200; pub const __WATCHOS_7_0: u32 = 70000; pub const __WATCHOS_7_1: u32 = 70100; pub const __WATCHOS_7_2: u32 = 70200; pub const __WATCHOS_7_3: u32 = 70300; pub const __WATCHOS_7_4: u32 = 70400; pub const __WATCHOS_7_5: u32 = 70500; pub const __WATCHOS_7_6: u32 = 70600; pub const __WATCHOS_8_0: u32 = 80000; pub const __WATCHOS_8_1: u32 = 80100; pub const __WATCHOS_8_3: u32 = 80300; pub const __WATCHOS_8_4: u32 = 80400; pub const __WATCHOS_8_5: u32 = 80500; pub const __WATCHOS_8_6: u32 = 80600; pub const __WATCHOS_8_7: u32 = 80700; pub const __WATCHOS_9_0: u32 = 90000; pub const __WATCHOS_9_1: u32 = 90100; pub const __WATCHOS_9_2: u32 = 90200; pub const __WATCHOS_9_3: u32 = 90300; pub const __WATCHOS_9_4: u32 = 90400; pub const __WATCHOS_9_5: u32 = 90500; pub const __WATCHOS_9_6: u32 = 90600; pub const __WATCHOS_10_0: u32 = 100000; pub const __WATCHOS_10_1: u32 = 100100; pub const __WATCHOS_10_2: u32 = 100200; pub const __TVOS_9_0: u32 = 90000; pub const __TVOS_9_1: u32 = 90100; pub const __TVOS_9_2: u32 = 90200; pub const __TVOS_10_0: u32 = 100000; pub const __TVOS_10_0_1: u32 = 100001; pub const __TVOS_10_1: u32 = 100100; pub const __TVOS_10_2: u32 = 100200; pub const __TVOS_11_0: u32 = 110000; pub const __TVOS_11_1: u32 = 110100; pub const __TVOS_11_2: u32 = 110200; pub const __TVOS_11_3: u32 = 110300; pub const __TVOS_11_4: u32 = 110400; pub const __TVOS_12_0: u32 = 120000; pub const __TVOS_12_1: u32 = 120100; pub const __TVOS_12_2: u32 = 120200; pub const __TVOS_12_3: u32 = 120300; pub const __TVOS_12_4: u32 = 120400; pub const __TVOS_13_0: u32 = 130000; pub const __TVOS_13_2: u32 = 130200; pub const __TVOS_13_3: u32 = 130300; pub const __TVOS_13_4: u32 = 130400; pub const __TVOS_14_0: u32 = 140000; pub const __TVOS_14_1: u32 = 140100; pub const __TVOS_14_2: u32 = 140200; pub const __TVOS_14_3: u32 = 140300; pub const __TVOS_14_5: u32 = 140500; pub const __TVOS_14_6: u32 = 140600; pub const __TVOS_14_7: u32 = 140700; pub const __TVOS_15_0: u32 = 150000; pub const __TVOS_15_1: u32 = 150100; pub const __TVOS_15_2: u32 = 150200; pub const __TVOS_15_3: u32 = 150300; pub const __TVOS_15_4: u32 = 150400; pub const __TVOS_15_5: u32 = 150500; pub const __TVOS_15_6: u32 = 150600; pub const __TVOS_16_0: u32 = 160000; pub const __TVOS_16_1: u32 = 160100; pub const __TVOS_16_2: u32 = 160200; pub const __TVOS_16_3: u32 = 160300; pub const __TVOS_16_4: u32 = 160400; pub const __TVOS_16_5: u32 = 160500; pub const __TVOS_16_6: u32 = 160600; pub const __TVOS_17_0: u32 = 170000; pub const __TVOS_17_1: u32 = 170100; pub const __TVOS_17_2: u32 = 170200; pub const __BRIDGEOS_2_0: u32 = 20000; pub const __BRIDGEOS_3_0: u32 = 30000; pub const __BRIDGEOS_3_1: u32 = 30100; pub const __BRIDGEOS_3_4: u32 = 30400; pub const __BRIDGEOS_4_0: u32 = 40000; pub const __BRIDGEOS_4_1: u32 = 40100; pub const __BRIDGEOS_5_0: u32 = 50000; pub const __BRIDGEOS_5_1: u32 = 50100; pub const __BRIDGEOS_5_3: u32 = 50300; pub const __BRIDGEOS_6_0: u32 = 60000; pub const __BRIDGEOS_6_2: u32 = 60200; pub const __BRIDGEOS_6_4: u32 = 60400; pub const __BRIDGEOS_6_5: u32 = 60500; pub const __BRIDGEOS_6_6: u32 = 60600; pub const __BRIDGEOS_7_0: u32 = 70000; pub const __BRIDGEOS_7_1: u32 = 70100; pub const __BRIDGEOS_7_2: u32 = 70200; pub const __BRIDGEOS_7_3: u32 = 70300; pub const __BRIDGEOS_7_4: u32 = 70400; pub const __BRIDGEOS_7_6: u32 = 70600; pub const __BRIDGEOS_8_0: u32 = 80000; pub const __BRIDGEOS_8_1: u32 = 80100; pub const __BRIDGEOS_8_2: u32 = 80200; pub const __DRIVERKIT_19_0: u32 = 190000; pub const __DRIVERKIT_20_0: u32 = 200000; pub const __DRIVERKIT_21_0: u32 = 210000; pub const __DRIVERKIT_22_0: u32 = 220000; pub const __DRIVERKIT_22_4: u32 = 220400; pub const __DRIVERKIT_22_5: u32 = 220500; pub const __DRIVERKIT_22_6: u32 = 220600; pub const __DRIVERKIT_23_0: u32 = 230000; pub const __DRIVERKIT_23_1: u32 = 230100; pub const __DRIVERKIT_23_2: u32 = 230200; pub const __VISIONOS_1_0: u32 = 10000; pub const MAC_OS_X_VERSION_10_0: u32 = 1000; pub const MAC_OS_X_VERSION_10_1: u32 = 1010; pub const MAC_OS_X_VERSION_10_2: u32 = 1020; pub const MAC_OS_X_VERSION_10_3: u32 = 1030; pub const MAC_OS_X_VERSION_10_4: u32 = 1040; pub const MAC_OS_X_VERSION_10_5: u32 = 1050; pub const MAC_OS_X_VERSION_10_6: u32 = 1060; pub const MAC_OS_X_VERSION_10_7: u32 = 1070; pub const MAC_OS_X_VERSION_10_8: u32 = 1080; pub const MAC_OS_X_VERSION_10_9: u32 = 1090; pub const MAC_OS_X_VERSION_10_10: u32 = 101000; pub const MAC_OS_X_VERSION_10_10_2: u32 = 101002; pub const MAC_OS_X_VERSION_10_10_3: u32 = 101003; pub const MAC_OS_X_VERSION_10_11: u32 = 101100; pub const MAC_OS_X_VERSION_10_11_2: u32 = 101102; pub const MAC_OS_X_VERSION_10_11_3: u32 = 101103; pub const MAC_OS_X_VERSION_10_11_4: u32 = 101104; pub const MAC_OS_X_VERSION_10_12: u32 = 101200; pub const MAC_OS_X_VERSION_10_12_1: u32 = 101201; pub const MAC_OS_X_VERSION_10_12_2: u32 = 101202; pub const MAC_OS_X_VERSION_10_12_4: u32 = 101204; pub const MAC_OS_X_VERSION_10_13: u32 = 101300; pub const MAC_OS_X_VERSION_10_13_1: u32 = 101301; pub const MAC_OS_X_VERSION_10_13_2: u32 = 101302; pub const MAC_OS_X_VERSION_10_13_4: u32 = 101304; pub const MAC_OS_X_VERSION_10_14: u32 = 101400; pub const MAC_OS_X_VERSION_10_14_1: u32 = 101401; pub const MAC_OS_X_VERSION_10_14_4: u32 = 101404; pub const MAC_OS_X_VERSION_10_14_5: u32 = 101405; pub const MAC_OS_X_VERSION_10_14_6: u32 = 101406; pub const MAC_OS_X_VERSION_10_15: u32 = 101500; pub const MAC_OS_X_VERSION_10_15_1: u32 = 101501; pub const MAC_OS_X_VERSION_10_15_4: u32 = 101504; pub const MAC_OS_X_VERSION_10_16: u32 = 101600; pub const MAC_OS_VERSION_11_0: u32 = 110000; pub const MAC_OS_VERSION_11_1: u32 = 110100; pub const MAC_OS_VERSION_11_3: u32 = 110300; pub const MAC_OS_VERSION_11_4: u32 = 110400; pub const MAC_OS_VERSION_11_5: u32 = 110500; pub const MAC_OS_VERSION_11_6: u32 = 110600; pub const MAC_OS_VERSION_12_0: u32 = 120000; pub const MAC_OS_VERSION_12_1: u32 = 120100; pub const MAC_OS_VERSION_12_2: u32 = 120200; pub const MAC_OS_VERSION_12_3: u32 = 120300; pub const MAC_OS_VERSION_12_4: u32 = 120400; pub const MAC_OS_VERSION_12_5: u32 = 120500; pub const MAC_OS_VERSION_12_6: u32 = 120600; pub const MAC_OS_VERSION_12_7: u32 = 120700; pub const MAC_OS_VERSION_13_0: u32 = 130000; pub const MAC_OS_VERSION_13_1: u32 = 130100; pub const MAC_OS_VERSION_13_2: u32 = 130200; pub const MAC_OS_VERSION_13_3: u32 = 130300; pub const MAC_OS_VERSION_13_4: u32 = 130400; pub const MAC_OS_VERSION_13_5: u32 = 130500; pub const MAC_OS_VERSION_13_6: u32 = 130600; pub const MAC_OS_VERSION_14_0: u32 = 140000; pub const MAC_OS_VERSION_14_1: u32 = 140100; pub const MAC_OS_VERSION_14_2: u32 = 140200; pub const __MAC_OS_X_VERSION_MAX_ALLOWED: u32 = 140200; pub const __ENABLE_LEGACY_MAC_AVAILABILITY: u32 = 1; pub const __DARWIN_FD_SETSIZE: u32 = 1024; pub const __DARWIN_NBBY: u32 = 8; pub const NBBY: u32 = 8; pub const FD_SETSIZE: u32 = 1024; pub const ARG_MAX: u32 = 1048576; pub const CHILD_MAX: u32 = 266; pub const GID_MAX: u32 = 2147483647; pub const LINK_MAX: u32 = 32767; pub const MAX_CANON: u32 = 1024; pub const MAX_INPUT: u32 = 1024; pub const NAME_MAX: u32 = 255; pub const NGROUPS_MAX: u32 = 16; pub const UID_MAX: u32 = 2147483647; pub const OPEN_MAX: u32 = 10240; pub const PATH_MAX: u32 = 1024; pub const PIPE_BUF: u32 = 512; pub const BC_BASE_MAX: u32 = 99; pub const BC_DIM_MAX: u32 = 2048; pub const BC_SCALE_MAX: u32 = 99; pub const BC_STRING_MAX: u32 = 1000; pub const CHARCLASS_NAME_MAX: u32 = 14; pub const COLL_WEIGHTS_MAX: u32 = 2; pub const EQUIV_CLASS_MAX: u32 = 2; pub const EXPR_NEST_MAX: u32 = 32; pub const LINE_MAX: u32 = 2048; pub const RE_DUP_MAX: u32 = 255; pub const NZERO: u32 = 20; pub const MAXCOMLEN: u32 = 16; pub const MAXINTERP: u32 = 64; pub const MAXLOGNAME: u32 = 255; pub const MAXUPRC: u32 = 266; pub const NCARGS: u32 = 1048576; pub const NGROUPS: u32 = 16; pub const NOFILE: u32 = 256; pub const NOGROUP: u32 = 65535; pub const MAXHOSTNAMELEN: u32 = 256; pub const MAXDOMNAMELEN: u32 = 256; pub const NBPG: u32 = 4096; pub const PGOFSET: u32 = 4095; pub const PGSHIFT: u32 = 12; pub const DEV_BSIZE: u32 = 512; pub const DEV_BSHIFT: u32 = 9; pub const BLKDEV_IOSIZE: u32 = 2048; pub const MAXPHYS: u32 = 131072; pub const CLSIZE: u32 = 1; pub const CLSIZELOG2: u32 = 0; pub const MSIZESHIFT: u32 = 8; pub const MSIZE: u32 = 256; pub const MCLSHIFT: u32 = 11; pub const MCLBYTES: u32 = 2048; pub const MBIGCLSHIFT: u32 = 12; pub const MBIGCLBYTES: u32 = 4096; pub const M16KCLSHIFT: u32 = 14; pub const M16KCLBYTES: u32 = 16384; pub const MCLOFSET: u32 = 2047; pub const NMBCLUSTERS: u32 = 512; pub const __DARWIN_CLK_TCK: u32 = 100; pub const CHAR_BIT: u32 = 8; pub const MB_LEN_MAX: u32 = 6; pub const CLK_TCK: u32 = 100; pub const SCHAR_MAX: u32 = 127; pub const SCHAR_MIN: i32 = -128; pub const UCHAR_MAX: u32 = 255; pub const CHAR_MAX: u32 = 127; pub const CHAR_MIN: i32 = -128; pub const USHRT_MAX: u32 = 65535; pub const SHRT_MAX: u32 = 32767; pub const SHRT_MIN: i32 = -32768; pub const UINT_MAX: u32 = 4294967295; pub const INT_MAX: u32 = 2147483647; pub const INT_MIN: i32 = -2147483648; pub const ULONG_MAX: i32 = -1; pub const LONG_MAX: u64 = 9223372036854775807; pub const LONG_MIN: i64 = -9223372036854775808; pub const ULLONG_MAX: i32 = -1; pub const LLONG_MAX: u64 = 9223372036854775807; pub const LLONG_MIN: i64 = -9223372036854775808; pub const LONG_BIT: u32 = 64; pub const SSIZE_MAX: u64 = 9223372036854775807; pub const WORD_BIT: u32 = 32; pub const SIZE_T_MAX: i32 = -1; pub const UQUAD_MAX: i32 = -1; pub const QUAD_MAX: u64 = 9223372036854775807; pub const QUAD_MIN: i64 = -9223372036854775808; pub const _POSIX_ARG_MAX: u32 = 4096; pub const _POSIX_CHILD_MAX: u32 = 25; pub const _POSIX_LINK_MAX: u32 = 8; pub const _POSIX_MAX_CANON: u32 = 255; pub const _POSIX_MAX_INPUT: u32 = 255; pub const _POSIX_NAME_MAX: u32 = 14; pub const _POSIX_NGROUPS_MAX: u32 = 8; pub const _POSIX_OPEN_MAX: u32 = 20; pub const _POSIX_PATH_MAX: u32 = 256; pub const _POSIX_PIPE_BUF: u32 = 512; pub const _POSIX_SSIZE_MAX: u32 = 32767; pub const _POSIX_STREAM_MAX: u32 = 8; pub const _POSIX_TZNAME_MAX: u32 = 6; pub const _POSIX2_BC_BASE_MAX: u32 = 99; pub const _POSIX2_BC_DIM_MAX: u32 = 2048; pub const _POSIX2_BC_SCALE_MAX: u32 = 99; pub const _POSIX2_BC_STRING_MAX: u32 = 1000; pub const _POSIX2_EQUIV_CLASS_MAX: u32 = 2; pub const _POSIX2_EXPR_NEST_MAX: u32 = 32; pub const _POSIX2_LINE_MAX: u32 = 2048; pub const _POSIX2_RE_DUP_MAX: u32 = 255; pub const _POSIX_AIO_LISTIO_MAX: u32 = 2; pub const _POSIX_AIO_MAX: u32 = 1; pub const _POSIX_DELAYTIMER_MAX: u32 = 32; pub const _POSIX_MQ_OPEN_MAX: u32 = 8; pub const _POSIX_MQ_PRIO_MAX: u32 = 32; pub const _POSIX_RTSIG_MAX: u32 = 8; pub const _POSIX_SEM_NSEMS_MAX: u32 = 256; pub const _POSIX_SEM_VALUE_MAX: u32 = 32767; pub const _POSIX_SIGQUEUE_MAX: u32 = 32; pub const _POSIX_TIMER_MAX: u32 = 32; pub const _POSIX_CLOCKRES_MIN: u32 = 20000000; pub const _POSIX_THREAD_DESTRUCTOR_ITERATIONS: u32 = 4; pub const _POSIX_THREAD_KEYS_MAX: u32 = 128; pub const _POSIX_THREAD_THREADS_MAX: u32 = 64; pub const PTHREAD_DESTRUCTOR_ITERATIONS: u32 = 4; pub const PTHREAD_KEYS_MAX: u32 = 512; pub const PTHREAD_STACK_MIN: u32 = 8192; pub const _POSIX_HOST_NAME_MAX: u32 = 255; pub const _POSIX_LOGIN_NAME_MAX: u32 = 9; pub const _POSIX_SS_REPL_MAX: u32 = 4; pub const _POSIX_SYMLINK_MAX: u32 = 255; pub const _POSIX_SYMLOOP_MAX: u32 = 8; pub const _POSIX_TRACE_EVENT_NAME_MAX: u32 = 30; pub const _POSIX_TRACE_NAME_MAX: u32 = 8; pub const _POSIX_TRACE_SYS_MAX: u32 = 8; pub const _POSIX_TRACE_USER_EVENT_MAX: u32 = 32; pub const _POSIX_TTY_NAME_MAX: u32 = 9; pub const _POSIX2_CHARCLASS_NAME_MAX: u32 = 14; pub const _POSIX2_COLL_WEIGHTS_MAX: u32 = 2; pub const _POSIX_RE_DUP_MAX: u32 = 255; pub const OFF_MIN: i64 = -9223372036854775808; pub const OFF_MAX: u64 = 9223372036854775807; pub const PASS_MAX: u32 = 128; pub const NL_ARGMAX: u32 = 9; pub const NL_LANGMAX: u32 = 14; pub const NL_MSGMAX: u32 = 32767; pub const NL_NMAX: u32 = 1; pub const NL_SETMAX: u32 = 255; pub const NL_TEXTMAX: u32 = 2048; pub const _XOPEN_IOV_MAX: u32 = 16; pub const IOV_MAX: u32 = 1024; pub const _XOPEN_NAME_MAX: u32 = 255; pub const _XOPEN_PATH_MAX: u32 = 1024; pub const __DARWIN_NSIG: u32 = 32; pub const NSIG: u32 = 32; pub const _I386_SIGNAL_H_: u32 = 1; pub const SIGHUP: u32 = 1; pub const SIGINT: u32 = 2; pub const SIGQUIT: u32 = 3; pub const SIGILL: u32 = 4; pub const SIGTRAP: u32 = 5; pub const SIGABRT: u32 = 6; pub const SIGIOT: u32 = 6; pub const SIGEMT: u32 = 7; pub const SIGFPE: u32 = 8; pub const SIGKILL: u32 = 9; pub const SIGBUS: u32 = 10; pub const SIGSEGV: u32 = 11; pub const SIGSYS: u32 = 12; pub const SIGPIPE: u32 = 13; pub const SIGALRM: u32 = 14; pub const SIGTERM: u32 = 15; pub const SIGURG: u32 = 16; pub const SIGSTOP: u32 = 17; pub const SIGTSTP: u32 = 18; pub const SIGCONT: u32 = 19; pub const SIGCHLD: u32 = 20; pub const SIGTTIN: u32 = 21; pub const SIGTTOU: u32 = 22; pub const SIGIO: u32 = 23; pub const SIGXCPU: u32 = 24; pub const SIGXFSZ: u32 = 25; pub const SIGVTALRM: u32 = 26; pub const SIGPROF: u32 = 27; pub const SIGWINCH: u32 = 28; pub const SIGINFO: u32 = 29; pub const SIGUSR1: u32 = 30; pub const SIGUSR2: u32 = 31; pub const FP_PREC_24B: u32 = 0; pub const FP_PREC_53B: u32 = 2; pub const FP_PREC_64B: u32 = 3; pub const FP_RND_NEAR: u32 = 0; pub const FP_RND_DOWN: u32 = 1; pub const FP_RND_UP: u32 = 2; pub const FP_CHOP: u32 = 3; pub const FP_STATE_BYTES: u32 = 512; pub const _X86_INSTRUCTION_STATE_MAX_INSN_BYTES: u32 = 2380; pub const _X86_INSTRUCTION_STATE_CACHELINE_SIZE: u32 = 64; pub const __LASTBRANCH_MAX: u32 = 32; pub const SIGEV_NONE: u32 = 0; pub const SIGEV_SIGNAL: u32 = 1; pub const SIGEV_THREAD: u32 = 3; pub const ILL_NOOP: u32 = 0; pub const ILL_ILLOPC: u32 = 1; pub const ILL_ILLTRP: u32 = 2; pub const ILL_PRVOPC: u32 = 3; pub const ILL_ILLOPN: u32 = 4; pub const ILL_ILLADR: u32 = 5; pub const ILL_PRVREG: u32 = 6; pub const ILL_COPROC: u32 = 7; pub const ILL_BADSTK: u32 = 8; pub const FPE_NOOP: u32 = 0; pub const FPE_FLTDIV: u32 = 1; pub const FPE_FLTOVF: u32 = 2; pub const FPE_FLTUND: u32 = 3; pub const FPE_FLTRES: u32 = 4; pub const FPE_FLTINV: u32 = 5; pub const FPE_FLTSUB: u32 = 6; pub const FPE_INTDIV: u32 = 7; pub const FPE_INTOVF: u32 = 8; pub const SEGV_NOOP: u32 = 0; pub const SEGV_MAPERR: u32 = 1; pub const SEGV_ACCERR: u32 = 2; pub const BUS_NOOP: u32 = 0; pub const BUS_ADRALN: u32 = 1; pub const BUS_ADRERR: u32 = 2; pub const BUS_OBJERR: u32 = 3; pub const TRAP_BRKPT: u32 = 1; pub const TRAP_TRACE: u32 = 2; pub const CLD_NOOP: u32 = 0; pub const CLD_EXITED: u32 = 1; pub const CLD_KILLED: u32 = 2; pub const CLD_DUMPED: u32 = 3; pub const CLD_TRAPPED: u32 = 4; pub const CLD_STOPPED: u32 = 5; pub const CLD_CONTINUED: u32 = 6; pub const POLL_IN: u32 = 1; pub const POLL_OUT: u32 = 2; pub const POLL_MSG: u32 = 3; pub const POLL_ERR: u32 = 4; pub const POLL_PRI: u32 = 5; pub const POLL_HUP: u32 = 6; pub const SA_ONSTACK: u32 = 1; pub const SA_RESTART: u32 = 2; pub const SA_RESETHAND: u32 = 4; pub const SA_NOCLDSTOP: u32 = 8; pub const SA_NODEFER: u32 = 16; pub const SA_NOCLDWAIT: u32 = 32; pub const SA_SIGINFO: u32 = 64; pub const SA_USERTRAMP: u32 = 256; pub const SA_64REGSET: u32 = 512; pub const SA_USERSPACE_MASK: u32 = 127; pub const SIG_BLOCK: u32 = 1; pub const SIG_UNBLOCK: u32 = 2; pub const SIG_SETMASK: u32 = 3; pub const SI_USER: u32 = 65537; pub const SI_QUEUE: u32 = 65538; pub const SI_TIMER: u32 = 65539; pub const SI_ASYNCIO: u32 = 65540; pub const SI_MESGQ: u32 = 65541; pub const SS_ONSTACK: u32 = 1; pub const SS_DISABLE: u32 = 4; pub const MINSIGSTKSZ: u32 = 32768; pub const SIGSTKSZ: u32 = 131072; pub const SV_ONSTACK: u32 = 1; pub const SV_INTERRUPT: u32 = 2; pub const SV_RESETHAND: u32 = 4; pub const SV_NODEFER: u32 = 16; pub const SV_NOCLDSTOP: u32 = 8; pub const SV_SIGINFO: u32 = 64; pub const PSWP: u32 = 0; pub const PVM: u32 = 4; pub const PINOD: u32 = 8; pub const PRIBIO: u32 = 16; pub const PVFS: u32 = 20; pub const PZERO: u32 = 22; pub const PSOCK: u32 = 24; pub const PWAIT: u32 = 32; pub const PLOCK: u32 = 36; pub const PPAUSE: u32 = 40; pub const PUSER: u32 = 50; pub const MAXPRI: u32 = 127; pub const PRIMASK: u32 = 255; pub const PCATCH: u32 = 256; pub const PTTYBLOCK: u32 = 512; pub const PDROP: u32 = 1024; pub const PSPIN: u32 = 2048; pub const CMASK: u32 = 18; pub const CLBYTES: u32 = 4096; pub const CLOFSET: u32 = 4095; pub const CLOFF: u32 = 4095; pub const CLSHIFT: u32 = 12; pub const CBLOCK: u32 = 64; pub const CBQSIZE: u32 = 8; pub const CROUND: u32 = 63; pub const MAXBSIZE: u32 = 1048576; pub const MAXPHYSIO: u32 = 131072; pub const MAXFRAG: u32 = 8; pub const MAXPHYSIO_WIRED: u32 = 16777216; pub const MAXPATHLEN: u32 = 1024; pub const MAXSYMLINKS: u32 = 32; pub const FSHIFT: u32 = 11; pub const FSCALE: u32 = 2048; pub const SPLAY_NEGINF: i32 = -1; pub const SPLAY_INF: u32 = 1; pub const RB_BLACK: u32 = 0; pub const RB_RED: u32 = 1; pub const RB_NEGINF: i32 = -1; pub const RB_INF: u32 = 1; pub const RNF_NORMAL: u32 = 1; pub const RNF_ROOT: u32 = 2; pub const RNF_ACTIVE: u32 = 4; pub const __WORDSIZE: u32 = 64; pub const INT8_MAX: u32 = 127; pub const INT16_MAX: u32 = 32767; pub const INT32_MAX: u32 = 2147483647; pub const INT64_MAX: u64 = 9223372036854775807; pub const INT8_MIN: i32 = -128; pub const INT16_MIN: i32 = -32768; pub const INT32_MIN: i32 = -2147483648; pub const INT64_MIN: i64 = -9223372036854775808; pub const UINT8_MAX: u32 = 255; pub const UINT16_MAX: u32 = 65535; pub const UINT32_MAX: u32 = 4294967295; pub const UINT64_MAX: i32 = -1; pub const INT_LEAST8_MIN: i32 = -128; pub const INT_LEAST16_MIN: i32 = -32768; pub const INT_LEAST32_MIN: i32 = -2147483648; pub const INT_LEAST64_MIN: i64 = -9223372036854775808; pub const INT_LEAST8_MAX: u32 = 127; pub const INT_LEAST16_MAX: u32 = 32767; pub const INT_LEAST32_MAX: u32 = 2147483647; pub const INT_LEAST64_MAX: u64 = 9223372036854775807; pub const UINT_LEAST8_MAX: u32 = 255; pub const UINT_LEAST16_MAX: u32 = 65535; pub const UINT_LEAST32_MAX: u32 = 4294967295; pub const UINT_LEAST64_MAX: i32 = -1; pub const INT_FAST8_MIN: i32 = -128; pub const INT_FAST16_MIN: i32 = -32768; pub const INT_FAST32_MIN: i32 = -2147483648; pub const INT_FAST64_MIN: i64 = -9223372036854775808; pub const INT_FAST8_MAX: u32 = 127; pub const INT_FAST16_MAX: u32 = 32767; pub const INT_FAST32_MAX: u32 = 2147483647; pub const INT_FAST64_MAX: u64 = 9223372036854775807; pub const UINT_FAST8_MAX: u32 = 255; pub const UINT_FAST16_MAX: u32 = 65535; pub const UINT_FAST32_MAX: u32 = 4294967295; pub const UINT_FAST64_MAX: i32 = -1; pub const INTPTR_MAX: u64 = 9223372036854775807; pub const INTPTR_MIN: i64 = -9223372036854775808; pub const UINTPTR_MAX: i32 = -1; pub const SIZE_MAX: i32 = -1; pub const RSIZE_MAX: i32 = -1; pub const WINT_MIN: i32 = -2147483648; pub const WINT_MAX: u32 = 2147483647; pub const SIG_ATOMIC_MIN: i32 = -2147483648; pub const SIG_ATOMIC_MAX: u32 = 2147483647; pub const KEV_INET_SUBCLASS: u32 = 1; pub const KEV_INET_NEW_ADDR: u32 = 1; pub const KEV_INET_CHANGED_ADDR: u32 = 2; pub const KEV_INET_ADDR_DELETED: u32 = 3; pub const KEV_INET_SIFDSTADDR: u32 = 4; pub const KEV_INET_SIFBRDADDR: u32 = 5; pub const KEV_INET_SIFNETMASK: u32 = 6; pub const KEV_INET_ARPCOLLISION: u32 = 7; pub const KEV_INET_PORTINUSE: u32 = 8; pub const KEV_INET_ARPRTRFAILURE: u32 = 9; pub const KEV_INET_ARPRTRALIVE: u32 = 10; pub const KEV_DL_SUBCLASS: u32 = 2; pub const KEV_DL_SIFFLAGS: u32 = 1; pub const KEV_DL_SIFMETRICS: u32 = 2; pub const KEV_DL_SIFMTU: u32 = 3; pub const KEV_DL_SIFPHYS: u32 = 4; pub const KEV_DL_SIFMEDIA: u32 = 5; pub const KEV_DL_SIFGENERIC: u32 = 6; pub const KEV_DL_ADDMULTI: u32 = 7; pub const KEV_DL_DELMULTI: u32 = 8; pub const KEV_DL_IF_ATTACHED: u32 = 9; pub const KEV_DL_IF_DETACHING: u32 = 10; pub const KEV_DL_IF_DETACHED: u32 = 11; pub const KEV_DL_LINK_OFF: u32 = 12; pub const KEV_DL_LINK_ON: u32 = 13; pub const KEV_DL_PROTO_ATTACHED: u32 = 14; pub const KEV_DL_PROTO_DETACHED: u32 = 15; pub const KEV_DL_LINK_ADDRESS_CHANGED: u32 = 16; pub const KEV_DL_WAKEFLAGS_CHANGED: u32 = 17; pub const KEV_DL_IF_IDLE_ROUTE_REFCNT: u32 = 18; pub const KEV_DL_IFCAP_CHANGED: u32 = 19; pub const KEV_DL_LINK_QUALITY_METRIC_CHANGED: u32 = 20; pub const KEV_DL_NODE_PRESENCE: u32 = 21; pub const KEV_DL_NODE_ABSENCE: u32 = 22; pub const KEV_DL_MASTER_ELECTED: u32 = 23; pub const KEV_DL_ISSUES: u32 = 24; pub const KEV_DL_IFDELEGATE_CHANGED: u32 = 25; pub const KEV_DL_AWDL_RESTRICTED: u32 = 26; pub const KEV_DL_AWDL_UNRESTRICTED: u32 = 27; pub const KEV_DL_RRC_STATE_CHANGED: u32 = 28; pub const KEV_DL_QOS_MODE_CHANGED: u32 = 29; pub const KEV_DL_LOW_POWER_MODE_CHANGED: u32 = 30; pub const KEV_NETPOLICY_SUBCLASS: u32 = 3; pub const KEV_NETPOLICY_IFDENIED: u32 = 1; pub const KEV_NETPOLICY_IFFAILED: u32 = 2; pub const KEV_NETPOLICY_NETDENIED: u32 = 3; pub const NETPOLICY_NETWORKTYPE_LOCAL: u32 = 1; pub const KEV_SOCKET_SUBCLASS: u32 = 4; pub const KEV_SOCKET_CLOSED: u32 = 1; pub const KEV_INET6_SUBCLASS: u32 = 6; pub const KEV_INET6_NEW_USER_ADDR: u32 = 1; pub const KEV_INET6_CHANGED_ADDR: u32 = 2; pub const KEV_INET6_ADDR_DELETED: u32 = 3; pub const KEV_INET6_NEW_LL_ADDR: u32 = 4; pub const KEV_INET6_NEW_RTADV_ADDR: u32 = 5; pub const KEV_INET6_DEFROUTER: u32 = 6; pub const KEV_INET6_REQUEST_NAT64_PREFIX: u32 = 7; pub const KEV_ND6_SUBCLASS: u32 = 7; pub const KEV_ND6_RA: u32 = 1; pub const KEV_ND6_NDFAILURE: u32 = 2; pub const KEV_ND6_NDALIVE: u32 = 3; pub const KEV_ND6_DAD_FAILURE: u32 = 4; pub const KEV_ND6_DAD_SUCCESS: u32 = 5; pub const KEV_ND6_ADDR_DETACHED: u32 = 6; pub const KEV_ND6_ADDR_DEPRECATED: u32 = 7; pub const KEV_ND6_ADDR_EXPIRED: u32 = 8; pub const KEV_ND6_RTR_EXPIRED: u32 = 9; pub const KEV_ND6_PFX_EXPIRED: u32 = 10; pub const KEV_NECP_SUBCLASS: u32 = 8; pub const KEV_NECP_POLICIES_CHANGED: u32 = 1; pub const KEV_NETAGENT_SUBCLASS: u32 = 9; pub const KEV_NETAGENT_REGISTERED: u32 = 1; pub const KEV_NETAGENT_UNREGISTERED: u32 = 2; pub const KEV_NETAGENT_UPDATED: u32 = 3; pub const KEV_NETAGENT_UPDATED_INTERFACES: u32 = 4; pub const KEV_LOG_SUBCLASS: u32 = 10; pub const IPFWLOGEVENT: u32 = 0; pub const KEV_NETEVENT_SUBCLASS: u32 = 11; pub const KEV_NETEVENT_APNFALLBACK: u32 = 1; pub const KEV_NETEVENT_CLAT46_EVENT: u32 = 2; pub const KEV_MPTCP_SUBCLASS: u32 = 12; pub const KEV_MPTCP_CELLUSE: u32 = 1; pub const KEV_IPSEC_SUBCLASS: u32 = 13; pub const KEV_IPSEC_WAKE_PACKET: u32 = 1; pub const SOCK_STREAM: u32 = 1; pub const SOCK_DGRAM: u32 = 2; pub const SOCK_RAW: u32 = 3; pub const SOCK_RDM: u32 = 4; pub const SOCK_SEQPACKET: u32 = 5; pub const SO_DEBUG: u32 = 1; pub const SO_ACCEPTCONN: u32 = 2; pub const SO_REUSEADDR: u32 = 4; pub const SO_KEEPALIVE: u32 = 8; pub const SO_DONTROUTE: u32 = 16; pub const SO_BROADCAST: u32 = 32; pub const SO_USELOOPBACK: u32 = 64; pub const SO_LINGER: u32 = 128; pub const SO_OOBINLINE: u32 = 256; pub const SO_REUSEPORT: u32 = 512; pub const SO_TIMESTAMP: u32 = 1024; pub const SO_TIMESTAMP_MONOTONIC: u32 = 2048; pub const SO_DONTTRUNC: u32 = 8192; pub const SO_WANTMORE: u32 = 16384; pub const SO_WANTOOBFLAG: u32 = 32768; pub const SO_NOWAKEFROMSLEEP: u32 = 65536; pub const SO_NOAPNFALLBK: u32 = 131072; pub const SO_TIMESTAMP_CONTINUOUS: u32 = 262144; pub const SO_SNDBUF: u32 = 4097; pub const SO_RCVBUF: u32 = 4098; pub const SO_SNDLOWAT: u32 = 4099; pub const SO_RCVLOWAT: u32 = 4100; pub const SO_SNDTIMEO: u32 = 4101; pub const SO_RCVTIMEO: u32 = 4102; pub const SO_ERROR: u32 = 4103; pub const SO_TYPE: u32 = 4104; pub const SO_LABEL: u32 = 4112; pub const SO_PEERLABEL: u32 = 4113; pub const SO_NREAD: u32 = 4128; pub const SO_NKE: u32 = 4129; pub const SO_NOSIGPIPE: u32 = 4130; pub const SO_NOADDRERR: u32 = 4131; pub const SO_NWRITE: u32 = 4132; pub const SO_REUSESHAREUID: u32 = 4133; pub const SO_NOTIFYCONFLICT: u32 = 4134; pub const SO_UPCALLCLOSEWAIT: u32 = 4135; pub const SO_LINGER_SEC: u32 = 4224; pub const SO_RESTRICTIONS: u32 = 4225; pub const SO_RESTRICT_DENY_IN: u32 = 1; pub const SO_RESTRICT_DENY_OUT: u32 = 2; pub const SO_RESTRICT_DENY_CELLULAR: u32 = 4; pub const SO_RESTRICT_DENY_EXPENSIVE: u32 = 8; pub const SO_RESTRICT_DENY_CONSTRAINED: u32 = 16; pub const SO_RANDOMPORT: u32 = 4226; pub const SO_NP_EXTENSIONS: u32 = 4227; pub const SO_EXECPATH: u32 = 4229; pub const SO_TRAFFIC_CLASS: u32 = 4230; pub const SO_TC_BK_SYS: u32 = 100; pub const SO_TC_BK: u32 = 200; pub const SO_TC_BE: u32 = 0; pub const SO_TC_RD: u32 = 300; pub const SO_TC_OAM: u32 = 400; pub const SO_TC_AV: u32 = 500; pub const SO_TC_RV: u32 = 600; pub const SO_TC_VI: u32 = 700; pub const SO_TC_VO: u32 = 800; pub const SO_TC_CTL: u32 = 900; pub const SO_TC_MAX: u32 = 10; pub const TRAFFIC_MGT_SO_BACKGROUND: u32 = 1; pub const TRAFFIC_MGT_TCP_RECVBG: u32 = 2; pub const SO_RECV_TRAFFIC_CLASS: u32 = 4231; pub const SO_TRAFFIC_CLASS_DBG: u32 = 4232; pub const SO_OPTION_UNUSED_0: u32 = 4233; pub const SO_PRIVILEGED_TRAFFIC_CLASS: u32 = 4240; pub const SO_DEFUNCTIT: u32 = 4241; pub const SO_DEFUNCTOK: u32 = 4352; pub const SO_ISDEFUNCT: u32 = 4353; pub const SO_OPPORTUNISTIC: u32 = 4354; pub const SO_FLUSH: u32 = 4355; pub const SO_TC_ALL: i32 = -1; pub const SO_RECV_ANYIF: u32 = 4356; pub const SO_TRAFFIC_MGT_BACKGROUND: u32 = 4357; pub const SO_FLOW_DIVERT_TOKEN: u32 = 4358; pub const SO_DELEGATED: u32 = 4359; pub const SO_DELEGATED_UUID: u32 = 4360; pub const SO_NECP_ATTRIBUTES: u32 = 4361; pub const SO_CFIL_SOCK_ID: u32 = 4368; pub const SO_NECP_CLIENTUUID: u32 = 4369; pub const SO_NUMRCVPKT: u32 = 4370; pub const SO_AWDL_UNRESTRICTED: u32 = 4371; pub const SO_EXTENDED_BK_IDLE: u32 = 4372; pub const SO_MARK_CELLFALLBACK: u32 = 4373; pub const SO_NET_SERVICE_TYPE: u32 = 4374; pub const SO_QOSMARKING_POLICY_OVERRIDE: u32 = 4375; pub const SO_INTCOPROC_ALLOW: u32 = 4376; pub const SO_NETSVC_MARKING_LEVEL: u32 = 4377; pub const SO_NECP_LISTENUUID: u32 = 4384; pub const SO_MPKL_SEND_INFO: u32 = 4386; pub const SO_STATISTICS_EVENT: u32 = 4387; pub const SO_WANT_KEV_SOCKET_CLOSED: u32 = 4388; pub const NET_SERVICE_TYPE_BE: u32 = 0; pub const NET_SERVICE_TYPE_BK: u32 = 1; pub const NET_SERVICE_TYPE_SIG: u32 = 2; pub const NET_SERVICE_TYPE_VI: u32 = 3; pub const NET_SERVICE_TYPE_VO: u32 = 4; pub const NET_SERVICE_TYPE_RV: u32 = 5; pub const NET_SERVICE_TYPE_AV: u32 = 6; pub const NET_SERVICE_TYPE_OAM: u32 = 7; pub const NET_SERVICE_TYPE_RD: u32 = 8; pub const _NET_SERVICE_TYPE_COUNT: u32 = 9; pub const SO_TC_NET_SERVICE_OFFSET: u32 = 10000; pub const SO_TC_NETSVC_SIG: u32 = 10002; pub const NETSVC_MRKNG_UNKNOWN: u32 = 0; pub const NETSVC_MRKNG_LVL_L2: u32 = 1; pub const NETSVC_MRKNG_LVL_L3L2_ALL: u32 = 2; pub const NETSVC_MRKNG_LVL_L3L2_BK: u32 = 3; pub const SAE_ASSOCID_ANY: u32 = 0; pub const SAE_CONNID_ANY: u32 = 0; pub const CONNECT_RESUME_ON_READ_WRITE: u32 = 1; pub const CONNECT_DATA_IDEMPOTENT: u32 = 2; pub const CONNECT_DATA_AUTHENTICATED: u32 = 4; pub const SONPX_SETOPTSHUT: u32 = 1; pub const SOL_SOCKET: u32 = 65535; pub const AF_UNSPEC: u32 = 0; pub const AF_UNIX: u32 = 1; pub const AF_LOCAL: u32 = 1; pub const AF_INET: u32 = 2; pub const AF_IMPLINK: u32 = 3; pub const AF_PUP: u32 = 4; pub const AF_CHAOS: u32 = 5; pub const AF_NS: u32 = 6; pub const AF_ISO: u32 = 7; pub const AF_OSI: u32 = 7; pub const AF_ECMA: u32 = 8; pub const AF_DATAKIT: u32 = 9; pub const AF_CCITT: u32 = 10; pub const AF_SNA: u32 = 11; pub const AF_DECnet: u32 = 12; pub const AF_DLI: u32 = 13; pub const AF_LAT: u32 = 14; pub const AF_HYLINK: u32 = 15; pub const AF_APPLETALK: u32 = 16; pub const AF_ROUTE: u32 = 17; pub const AF_LINK: u32 = 18; pub const pseudo_AF_XTP: u32 = 19; pub const AF_COIP: u32 = 20; pub const AF_CNT: u32 = 21; pub const pseudo_AF_RTIP: u32 = 22; pub const AF_IPX: u32 = 23; pub const AF_SIP: u32 = 24; pub const pseudo_AF_PIP: u32 = 25; pub const AF_NDRV: u32 = 27; pub const AF_ISDN: u32 = 28; pub const AF_E164: u32 = 28; pub const pseudo_AF_KEY: u32 = 29; pub const AF_INET6: u32 = 30; pub const AF_NATM: u32 = 31; pub const AF_SYSTEM: u32 = 32; pub const AF_NETBIOS: u32 = 33; pub const AF_PPP: u32 = 34; pub const pseudo_AF_HDRCMPLT: u32 = 35; pub const AF_AFP: u32 = 36; pub const AF_IEEE80211: u32 = 37; pub const AF_UTUN: u32 = 38; pub const AF_MULTIPATH: u32 = 39; pub const AF_VSOCK: u32 = 40; pub const AF_MAX: u32 = 41; pub const SOCK_MAXADDRLEN: u32 = 255; pub const _SS_MAXSIZE: u32 = 128; pub const PF_UNSPEC: u32 = 0; pub const PF_LOCAL: u32 = 1; pub const PF_UNIX: u32 = 1; pub const PF_INET: u32 = 2; pub const PF_IMPLINK: u32 = 3; pub const PF_PUP: u32 = 4; pub const PF_CHAOS: u32 = 5; pub const PF_NS: u32 = 6; pub const PF_ISO: u32 = 7; pub const PF_OSI: u32 = 7; pub const PF_ECMA: u32 = 8; pub const PF_DATAKIT: u32 = 9; pub const PF_CCITT: u32 = 10; pub const PF_SNA: u32 = 11; pub const PF_DECnet: u32 = 12; pub const PF_DLI: u32 = 13; pub const PF_LAT: u32 = 14; pub const PF_HYLINK: u32 = 15; pub const PF_APPLETALK: u32 = 16; pub const PF_ROUTE: u32 = 17; pub const PF_LINK: u32 = 18; pub const PF_XTP: u32 = 19; pub const PF_COIP: u32 = 20; pub const PF_CNT: u32 = 21; pub const PF_SIP: u32 = 24; pub const PF_IPX: u32 = 23; pub const PF_RTIP: u32 = 22; pub const PF_PIP: u32 = 25; pub const PF_NDRV: u32 = 27; pub const PF_ISDN: u32 = 28; pub const PF_KEY: u32 = 29; pub const PF_INET6: u32 = 30; pub const PF_NATM: u32 = 31; pub const PF_SYSTEM: u32 = 32; pub const PF_NETBIOS: u32 = 33; pub const PF_PPP: u32 = 34; pub const PF_AFP: u32 = 36; pub const PF_UTUN: u32 = 38; pub const PF_MULTIPATH: u32 = 39; pub const PF_VSOCK: u32 = 40; pub const PF_MAX: u32 = 41; pub const NET_MAXID: u32 = 41; pub const NET_RT_DUMP: u32 = 1; pub const NET_RT_FLAGS: u32 = 2; pub const NET_RT_IFLIST: u32 = 3; pub const NET_RT_STAT: u32 = 4; pub const NET_RT_TRASH: u32 = 5; pub const NET_RT_IFLIST2: u32 = 6; pub const NET_RT_DUMP2: u32 = 7; pub const NET_RT_DUMPX: u32 = 8; pub const NET_RT_DUMPX_FLAGS: u32 = 9; pub const NET_RT_FLAGS_PRIV: u32 = 10; pub const NET_RT_MAXID: u32 = 11; pub const SO_STATISTICS_EVENT_ENTER_CELLFALLBACK: u32 = 1; pub const SO_STATISTICS_EVENT_EXIT_CELLFALLBACK: u32 = 2; pub const SO_STATISTICS_EVENT_RESERVED_1: u32 = 4; pub const SO_STATISTICS_EVENT_RESERVED_2: u32 = 8; pub const SOMAXCONN: u32 = 128; pub const MSG_OOB: u32 = 1; pub const MSG_PEEK: u32 = 2; pub const MSG_DONTROUTE: u32 = 4; pub const MSG_EOR: u32 = 8; pub const MSG_TRUNC: u32 = 16; pub const MSG_CTRUNC: u32 = 32; pub const MSG_WAITALL: u32 = 64; pub const MSG_DONTWAIT: u32 = 128; pub const MSG_EOF: u32 = 256; pub const MSG_WAITSTREAM: u32 = 512; pub const MSG_FLUSH: u32 = 1024; pub const MSG_HOLD: u32 = 2048; pub const MSG_SEND: u32 = 4096; pub const MSG_HAVEMORE: u32 = 8192; pub const MSG_RCVMORE: u32 = 16384; pub const MSG_NEEDSA: u32 = 65536; pub const MSG_NOSIGNAL: u32 = 524288; pub const SCM_RIGHTS: u32 = 1; pub const SCM_TIMESTAMP: u32 = 2; pub const SCM_CREDS: u32 = 3; pub const SCM_TIMESTAMP_MONOTONIC: u32 = 4; pub const SCM_TIMESTAMP_CONTINUOUS: u32 = 7; pub const SCM_MPKL_SEND_INFO: u32 = 8; pub const SCM_MPKL_RECV_INFO: u32 = 9; pub const SHUT_RD: u32 = 0; pub const SHUT_WR: u32 = 1; pub const SHUT_RDWR: u32 = 2; pub const CIF_CONNECTING: u32 = 1; pub const CIF_CONNECTED: u32 = 2; pub const CIF_DISCONNECTING: u32 = 4; pub const CIF_DISCONNECTED: u32 = 8; pub const CIF_BOUND_IF: u32 = 16; pub const CIF_BOUND_IP: u32 = 32; pub const CIF_BOUND_PORT: u32 = 64; pub const CIF_PREFERRED: u32 = 128; pub const CIF_MP_CAPABLE: u32 = 256; pub const CIF_MP_READY: u32 = 512; pub const CIF_MP_DEGRADED: u32 = 1024; pub const CIF_MP_ACTIVE: u32 = 2048; pub const CIAUX_TCP: u32 = 1; pub const CIAUX_MPTCP: u32 = 2; pub const IPPROTO_IP: u32 = 0; pub const IPPROTO_HOPOPTS: u32 = 0; pub const IPPROTO_ICMP: u32 = 1; pub const IPPROTO_IGMP: u32 = 2; pub const IPPROTO_GGP: u32 = 3; pub const IPPROTO_IPV4: u32 = 4; pub const IPPROTO_IPIP: u32 = 4; pub const IPPROTO_TCP: u32 = 6; pub const IPPROTO_ST: u32 = 7; pub const IPPROTO_EGP: u32 = 8; pub const IPPROTO_PIGP: u32 = 9; pub const IPPROTO_RCCMON: u32 = 10; pub const IPPROTO_NVPII: u32 = 11; pub const IPPROTO_PUP: u32 = 12; pub const IPPROTO_ARGUS: u32 = 13; pub const IPPROTO_EMCON: u32 = 14; pub const IPPROTO_XNET: u32 = 15; pub const IPPROTO_CHAOS: u32 = 16; pub const IPPROTO_UDP: u32 = 17; pub const IPPROTO_MUX: u32 = 18; pub const IPPROTO_MEAS: u32 = 19; pub const IPPROTO_HMP: u32 = 20; pub const IPPROTO_PRM: u32 = 21; pub const IPPROTO_IDP: u32 = 22; pub const IPPROTO_TRUNK1: u32 = 23; pub const IPPROTO_TRUNK2: u32 = 24; pub const IPPROTO_LEAF1: u32 = 25; pub const IPPROTO_LEAF2: u32 = 26; pub const IPPROTO_RDP: u32 = 27; pub const IPPROTO_IRTP: u32 = 28; pub const IPPROTO_TP: u32 = 29; pub const IPPROTO_BLT: u32 = 30; pub const IPPROTO_NSP: u32 = 31; pub const IPPROTO_INP: u32 = 32; pub const IPPROTO_SEP: u32 = 33; pub const IPPROTO_3PC: u32 = 34; pub const IPPROTO_IDPR: u32 = 35; pub const IPPROTO_XTP: u32 = 36; pub const IPPROTO_DDP: u32 = 37; pub const IPPROTO_CMTP: u32 = 38; pub const IPPROTO_TPXX: u32 = 39; pub const IPPROTO_IL: u32 = 40; pub const IPPROTO_IPV6: u32 = 41; pub const IPPROTO_SDRP: u32 = 42; pub const IPPROTO_ROUTING: u32 = 43; pub const IPPROTO_FRAGMENT: u32 = 44; pub const IPPROTO_IDRP: u32 = 45; pub const IPPROTO_RSVP: u32 = 46; pub const IPPROTO_GRE: u32 = 47; pub const IPPROTO_MHRP: u32 = 48; pub const IPPROTO_BHA: u32 = 49; pub const IPPROTO_ESP: u32 = 50; pub const IPPROTO_AH: u32 = 51; pub const IPPROTO_INLSP: u32 = 52; pub const IPPROTO_SWIPE: u32 = 53; pub const IPPROTO_NHRP: u32 = 54; pub const IPPROTO_ICMPV6: u32 = 58; pub const IPPROTO_NONE: u32 = 59; pub const IPPROTO_DSTOPTS: u32 = 60; pub const IPPROTO_AHIP: u32 = 61; pub const IPPROTO_CFTP: u32 = 62; pub const IPPROTO_HELLO: u32 = 63; pub const IPPROTO_SATEXPAK: u32 = 64; pub const IPPROTO_KRYPTOLAN: u32 = 65; pub const IPPROTO_RVD: u32 = 66; pub const IPPROTO_IPPC: u32 = 67; pub const IPPROTO_ADFS: u32 = 68; pub const IPPROTO_SATMON: u32 = 69; pub const IPPROTO_VISA: u32 = 70; pub const IPPROTO_IPCV: u32 = 71; pub const IPPROTO_CPNX: u32 = 72; pub const IPPROTO_CPHB: u32 = 73; pub const IPPROTO_WSN: u32 = 74; pub const IPPROTO_PVP: u32 = 75; pub const IPPROTO_BRSATMON: u32 = 76; pub const IPPROTO_ND: u32 = 77; pub const IPPROTO_WBMON: u32 = 78; pub const IPPROTO_WBEXPAK: u32 = 79; pub const IPPROTO_EON: u32 = 80; pub const IPPROTO_VMTP: u32 = 81; pub const IPPROTO_SVMTP: u32 = 82; pub const IPPROTO_VINES: u32 = 83; pub const IPPROTO_TTP: u32 = 84; pub const IPPROTO_IGP: u32 = 85; pub const IPPROTO_DGP: u32 = 86; pub const IPPROTO_TCF: u32 = 87; pub const IPPROTO_IGRP: u32 = 88; pub const IPPROTO_OSPFIGP: u32 = 89; pub const IPPROTO_SRPC: u32 = 90; pub const IPPROTO_LARP: u32 = 91; pub const IPPROTO_MTP: u32 = 92; pub const IPPROTO_AX25: u32 = 93; pub const IPPROTO_IPEIP: u32 = 94; pub const IPPROTO_MICP: u32 = 95; pub const IPPROTO_SCCSP: u32 = 96; pub const IPPROTO_ETHERIP: u32 = 97; pub const IPPROTO_ENCAP: u32 = 98; pub const IPPROTO_APES: u32 = 99; pub const IPPROTO_GMTP: u32 = 100; pub const IPPROTO_PIM: u32 = 103; pub const IPPROTO_IPCOMP: u32 = 108; pub const IPPROTO_PGM: u32 = 113; pub const IPPROTO_SCTP: u32 = 132; pub const IPPROTO_QUIC: u32 = 253; pub const IPPROTO_DIVERT: u32 = 254; pub const IPPROTO_RAW: u32 = 255; pub const IPPROTO_MAX: u32 = 256; pub const IPPROTO_DONE: u32 = 257; pub const __DARWIN_IPPORT_RESERVED: u32 = 1024; pub const IPPORT_RESERVED: u32 = 1024; pub const IPPORT_USERRESERVED: u32 = 5000; pub const IPPORT_HIFIRSTAUTO: u32 = 49152; pub const IPPORT_HILASTAUTO: u32 = 65535; pub const IPPORT_RESERVEDSTART: u32 = 600; pub const IN_CLASSA_NET: u32 = 4278190080; pub const IN_CLASSA_NSHIFT: u32 = 24; pub const IN_CLASSA_HOST: u32 = 16777215; pub const IN_CLASSA_MAX: u32 = 128; pub const IN_CLASSB_NET: u32 = 4294901760; pub const IN_CLASSB_NSHIFT: u32 = 16; pub const IN_CLASSB_HOST: u32 = 65535; pub const IN_CLASSB_MAX: u32 = 65536; pub const IN_CLASSC_NET: u32 = 4294967040; pub const IN_CLASSC_NSHIFT: u32 = 8; pub const IN_CLASSC_HOST: u32 = 255; pub const IN_CLASSD_NET: u32 = 4026531840; pub const IN_CLASSD_NSHIFT: u32 = 28; pub const IN_CLASSD_HOST: u32 = 268435455; pub const INADDR_NONE: u32 = 4294967295; pub const IN_LOOPBACKNET: u32 = 127; pub const INET_ADDRSTRLEN: u32 = 16; pub const IP_OPTIONS: u32 = 1; pub const IP_HDRINCL: u32 = 2; pub const IP_TOS: u32 = 3; pub const IP_TTL: u32 = 4; pub const IP_RECVOPTS: u32 = 5; pub const IP_RECVRETOPTS: u32 = 6; pub const IP_RECVDSTADDR: u32 = 7; pub const IP_RETOPTS: u32 = 8; pub const IP_MULTICAST_IF: u32 = 9; pub const IP_MULTICAST_TTL: u32 = 10; pub const IP_MULTICAST_LOOP: u32 = 11; pub const IP_ADD_MEMBERSHIP: u32 = 12; pub const IP_DROP_MEMBERSHIP: u32 = 13; pub const IP_MULTICAST_VIF: u32 = 14; pub const IP_RSVP_ON: u32 = 15; pub const IP_RSVP_OFF: u32 = 16; pub const IP_RSVP_VIF_ON: u32 = 17; pub const IP_RSVP_VIF_OFF: u32 = 18; pub const IP_PORTRANGE: u32 = 19; pub const IP_RECVIF: u32 = 20; pub const IP_IPSEC_POLICY: u32 = 21; pub const IP_FAITH: u32 = 22; pub const IP_STRIPHDR: u32 = 23; pub const IP_RECVTTL: u32 = 24; pub const IP_BOUND_IF: u32 = 25; pub const IP_PKTINFO: u32 = 26; pub const IP_RECVPKTINFO: u32 = 26; pub const IP_RECVTOS: u32 = 27; pub const IP_DONTFRAG: u32 = 28; pub const IP_FW_ADD: u32 = 40; pub const IP_FW_DEL: u32 = 41; pub const IP_FW_FLUSH: u32 = 42; pub const IP_FW_ZERO: u32 = 43; pub const IP_FW_GET: u32 = 44; pub const IP_FW_RESETLOG: u32 = 45; pub const IP_OLD_FW_ADD: u32 = 50; pub const IP_OLD_FW_DEL: u32 = 51; pub const IP_OLD_FW_FLUSH: u32 = 52; pub const IP_OLD_FW_ZERO: u32 = 53; pub const IP_OLD_FW_GET: u32 = 54; pub const IP_NAT__XXX: u32 = 55; pub const IP_OLD_FW_RESETLOG: u32 = 56; pub const IP_DUMMYNET_CONFIGURE: u32 = 60; pub const IP_DUMMYNET_DEL: u32 = 61; pub const IP_DUMMYNET_FLUSH: u32 = 62; pub const IP_DUMMYNET_GET: u32 = 64; pub const IP_TRAFFIC_MGT_BACKGROUND: u32 = 65; pub const IP_MULTICAST_IFINDEX: u32 = 66; pub const IP_ADD_SOURCE_MEMBERSHIP: u32 = 70; pub const IP_DROP_SOURCE_MEMBERSHIP: u32 = 71; pub const IP_BLOCK_SOURCE: u32 = 72; pub const IP_UNBLOCK_SOURCE: u32 = 73; pub const IP_MSFILTER: u32 = 74; pub const MCAST_JOIN_GROUP: u32 = 80; pub const MCAST_LEAVE_GROUP: u32 = 81; pub const MCAST_JOIN_SOURCE_GROUP: u32 = 82; pub const MCAST_LEAVE_SOURCE_GROUP: u32 = 83; pub const MCAST_BLOCK_SOURCE: u32 = 84; pub const MCAST_UNBLOCK_SOURCE: u32 = 85; pub const IP_NO_IFT_CELLULAR: u32 = 6969; pub const IP_NO_IFT_PDP: u32 = 6969; pub const IP_OUT_IF: u32 = 9696; pub const IP_DEFAULT_MULTICAST_TTL: u32 = 1; pub const IP_DEFAULT_MULTICAST_LOOP: u32 = 1; pub const IP_MIN_MEMBERSHIPS: u32 = 31; pub const IP_MAX_MEMBERSHIPS: u32 = 4095; pub const IP_MAX_GROUP_SRC_FILTER: u32 = 512; pub const IP_MAX_SOCK_SRC_FILTER: u32 = 128; pub const IP_MAX_SOCK_MUTE_FILTER: u32 = 128; pub const MCAST_UNDEFINED: u32 = 0; pub const MCAST_INCLUDE: u32 = 1; pub const MCAST_EXCLUDE: u32 = 2; pub const IP_PORTRANGE_DEFAULT: u32 = 0; pub const IP_PORTRANGE_HIGH: u32 = 1; pub const IP_PORTRANGE_LOW: u32 = 2; pub const IPPROTO_MAXID: u32 = 52; pub const IPCTL_FORWARDING: u32 = 1; pub const IPCTL_SENDREDIRECTS: u32 = 2; pub const IPCTL_DEFTTL: u32 = 3; pub const IPCTL_RTEXPIRE: u32 = 5; pub const IPCTL_RTMINEXPIRE: u32 = 6; pub const IPCTL_RTMAXCACHE: u32 = 7; pub const IPCTL_SOURCEROUTE: u32 = 8; pub const IPCTL_DIRECTEDBROADCAST: u32 = 9; pub const IPCTL_INTRQMAXLEN: u32 = 10; pub const IPCTL_INTRQDROPS: u32 = 11; pub const IPCTL_STATS: u32 = 12; pub const IPCTL_ACCEPTSOURCEROUTE: u32 = 13; pub const IPCTL_FASTFORWARDING: u32 = 14; pub const IPCTL_KEEPFAITH: u32 = 15; pub const IPCTL_GIF_TTL: u32 = 16; pub const IPCTL_MAXID: u32 = 17; pub const __KAME_VERSION: &[u8; 18] = b"2009/apple-darwin\0"; pub const IPV6PORT_RESERVED: u32 = 1024; pub const IPV6PORT_ANONMIN: u32 = 49152; pub const IPV6PORT_ANONMAX: u32 = 65535; pub const IPV6PORT_RESERVEDMIN: u32 = 600; pub const IPV6PORT_RESERVEDMAX: u32 = 1023; pub const INET6_ADDRSTRLEN: u32 = 46; pub const __IPV6_ADDR_SCOPE_NODELOCAL: u32 = 1; pub const __IPV6_ADDR_SCOPE_INTFACELOCAL: u32 = 1; pub const __IPV6_ADDR_SCOPE_LINKLOCAL: u32 = 2; pub const __IPV6_ADDR_SCOPE_SITELOCAL: u32 = 5; pub const __IPV6_ADDR_SCOPE_ORGLOCAL: u32 = 8; pub const __IPV6_ADDR_SCOPE_GLOBAL: u32 = 14; pub const IPV6_ADDR_MC_FLAGS_TRANSIENT: u32 = 16; pub const IPV6_ADDR_MC_FLAGS_PREFIX: u32 = 32; pub const IPV6_ADDR_MC_FLAGS_UNICAST_BASED: u32 = 48; pub const IPV6_SOCKOPT_RESERVED1: u32 = 3; pub const IPV6_UNICAST_HOPS: u32 = 4; pub const IPV6_MULTICAST_IF: u32 = 9; pub const IPV6_MULTICAST_HOPS: u32 = 10; pub const IPV6_MULTICAST_LOOP: u32 = 11; pub const IPV6_JOIN_GROUP: u32 = 12; pub const IPV6_LEAVE_GROUP: u32 = 13; pub const IPV6_PORTRANGE: u32 = 14; pub const ICMP6_FILTER: u32 = 18; pub const IPV6_2292PKTINFO: u32 = 19; pub const IPV6_2292HOPLIMIT: u32 = 20; pub const IPV6_2292NEXTHOP: u32 = 21; pub const IPV6_2292HOPOPTS: u32 = 22; pub const IPV6_2292DSTOPTS: u32 = 23; pub const IPV6_2292RTHDR: u32 = 24; pub const IPV6_2292PKTOPTIONS: u32 = 25; pub const IPV6_CHECKSUM: u32 = 26; pub const IPV6_V6ONLY: u32 = 27; pub const IPV6_BINDV6ONLY: u32 = 27; pub const IPV6_IPSEC_POLICY: u32 = 28; pub const IPV6_FAITH: u32 = 29; pub const IPV6_FW_ADD: u32 = 30; pub const IPV6_FW_DEL: u32 = 31; pub const IPV6_FW_FLUSH: u32 = 32; pub const IPV6_FW_ZERO: u32 = 33; pub const IPV6_FW_GET: u32 = 34; pub const IPV6_RECVTCLASS: u32 = 35; pub const IPV6_TCLASS: u32 = 36; pub const IPV6_BOUND_IF: u32 = 125; pub const IPV6_NO_IFT_CELLULAR: u32 = 6969; pub const IPV6_OUT_IF: u32 = 9696; pub const IPV6_RTHDR_LOOSE: u32 = 0; pub const IPV6_RTHDR_STRICT: u32 = 1; pub const IPV6_RTHDR_TYPE_0: u32 = 0; pub const IPV6_DEFAULT_MULTICAST_HOPS: u32 = 1; pub const IPV6_DEFAULT_MULTICAST_LOOP: u32 = 1; pub const IPV6_MIN_MEMBERSHIPS: u32 = 31; pub const IPV6_MAX_MEMBERSHIPS: u32 = 4095; pub const IPV6_MAX_GROUP_SRC_FILTER: u32 = 512; pub const IPV6_MAX_SOCK_SRC_FILTER: u32 = 128; pub const IPV6_PORTRANGE_DEFAULT: u32 = 0; pub const IPV6_PORTRANGE_HIGH: u32 = 1; pub const IPV6_PORTRANGE_LOW: u32 = 2; pub const IPV6PROTO_MAXID: u32 = 104; pub const IPV6CTL_FORWARDING: u32 = 1; pub const IPV6CTL_SENDREDIRECTS: u32 = 2; pub const IPV6CTL_DEFHLIM: u32 = 3; pub const IPV6CTL_FORWSRCRT: u32 = 5; pub const IPV6CTL_STATS: u32 = 6; pub const IPV6CTL_MRTSTATS: u32 = 7; pub const IPV6CTL_MRTPROTO: u32 = 8; pub const IPV6CTL_MAXFRAGPACKETS: u32 = 9; pub const IPV6CTL_SOURCECHECK: u32 = 10; pub const IPV6CTL_SOURCECHECK_LOGINT: u32 = 11; pub const IPV6CTL_ACCEPT_RTADV: u32 = 12; pub const IPV6CTL_KEEPFAITH: u32 = 13; pub const IPV6CTL_LOG_INTERVAL: u32 = 14; pub const IPV6CTL_HDRNESTLIMIT: u32 = 15; pub const IPV6CTL_DAD_COUNT: u32 = 16; pub const IPV6CTL_AUTO_FLOWLABEL: u32 = 17; pub const IPV6CTL_DEFMCASTHLIM: u32 = 18; pub const IPV6CTL_GIF_HLIM: u32 = 19; pub const IPV6CTL_KAME_VERSION: u32 = 20; pub const IPV6CTL_USE_DEPRECATED: u32 = 21; pub const IPV6CTL_RR_PRUNE: u32 = 22; pub const IPV6CTL_V6ONLY: u32 = 24; pub const IPV6CTL_RTEXPIRE: u32 = 25; pub const IPV6CTL_RTMINEXPIRE: u32 = 26; pub const IPV6CTL_RTMAXCACHE: u32 = 27; pub const IPV6CTL_USETEMPADDR: u32 = 32; pub const IPV6CTL_TEMPPLTIME: u32 = 33; pub const IPV6CTL_TEMPVLTIME: u32 = 34; pub const IPV6CTL_AUTO_LINKLOCAL: u32 = 35; pub const IPV6CTL_RIP6STATS: u32 = 36; pub const IPV6CTL_PREFER_TEMPADDR: u32 = 37; pub const IPV6CTL_ADDRCTLPOLICY: u32 = 38; pub const IPV6CTL_USE_DEFAULTZONE: u32 = 39; pub const IPV6CTL_MAXFRAGS: u32 = 41; pub const IPV6CTL_MCAST_PMTU: u32 = 44; pub const IPV6CTL_NEIGHBORGCTHRESH: u32 = 46; pub const IPV6CTL_MAXIFPREFIXES: u32 = 47; pub const IPV6CTL_MAXIFDEFROUTERS: u32 = 48; pub const IPV6CTL_MAXDYNROUTES: u32 = 49; pub const ICMPV6CTL_ND6_ONLINKNSRFC4861: u32 = 50; pub const IPV6CTL_ULA_USETEMPADDR: u32 = 51; pub const IPV6CTL_MAXID: u32 = 51; pub const _DSCP_DF: u32 = 0; pub const _DSCP_CS0: u32 = 0; pub const _DSCP_CS1: u32 = 8; pub const _DSCP_CS2: u32 = 16; pub const _DSCP_CS3: u32 = 24; pub const _DSCP_CS4: u32 = 32; pub const _DSCP_CS5: u32 = 40; pub const _DSCP_CS6: u32 = 48; pub const _DSCP_CS7: u32 = 56; pub const _DSCP_EF: u32 = 46; pub const _DSCP_VA: u32 = 44; pub const _DSCP_AF11: u32 = 10; pub const _DSCP_AF12: u32 = 12; pub const _DSCP_AF13: u32 = 14; pub const _DSCP_AF21: u32 = 18; pub const _DSCP_AF22: u32 = 20; pub const _DSCP_AF23: u32 = 22; pub const _DSCP_AF31: u32 = 26; pub const _DSCP_AF32: u32 = 28; pub const _DSCP_AF33: u32 = 30; pub const _DSCP_AF41: u32 = 34; pub const _DSCP_AF42: u32 = 36; pub const _DSCP_AF43: u32 = 38; pub const _DSCP_52: u32 = 52; pub const _MAX_DSCP: u32 = 63; pub const ITIMER_REAL: u32 = 0; pub const ITIMER_VIRTUAL: u32 = 1; pub const ITIMER_PROF: u32 = 2; pub const DST_NONE: u32 = 0; pub const DST_USA: u32 = 1; pub const DST_AUST: u32 = 2; pub const DST_WET: u32 = 3; pub const DST_MET: u32 = 4; pub const DST_EET: u32 = 5; pub const DST_CAN: u32 = 6; pub const __DARWIN_WCHAR_MIN: i32 = -2147483648; pub const _FORTIFY_SOURCE: u32 = 2; pub const TIME_UTC: u32 = 1; pub const RTM_RTTUNIT: u32 = 1000000; pub const RTF_UP: u32 = 1; pub const RTF_GATEWAY: u32 = 2; pub const RTF_HOST: u32 = 4; pub const RTF_REJECT: u32 = 8; pub const RTF_DYNAMIC: u32 = 16; pub const RTF_MODIFIED: u32 = 32; pub const RTF_DONE: u32 = 64; pub const RTF_DELCLONE: u32 = 128; pub const RTF_CLONING: u32 = 256; pub const RTF_XRESOLVE: u32 = 512; pub const RTF_LLINFO: u32 = 1024; pub const RTF_LLDATA: u32 = 1024; pub const RTF_STATIC: u32 = 2048; pub const RTF_BLACKHOLE: u32 = 4096; pub const RTF_NOIFREF: u32 = 8192; pub const RTF_PROTO2: u32 = 16384; pub const RTF_PROTO1: u32 = 32768; pub const RTF_PRCLONING: u32 = 65536; pub const RTF_WASCLONED: u32 = 131072; pub const RTF_PROTO3: u32 = 262144; pub const RTF_PINNED: u32 = 1048576; pub const RTF_LOCAL: u32 = 2097152; pub const RTF_BROADCAST: u32 = 4194304; pub const RTF_MULTICAST: u32 = 8388608; pub const RTF_IFSCOPE: u32 = 16777216; pub const RTF_CONDEMNED: u32 = 33554432; pub const RTF_IFREF: u32 = 67108864; pub const RTF_PROXY: u32 = 134217728; pub const RTF_ROUTER: u32 = 268435456; pub const RTF_DEAD: u32 = 536870912; pub const RTF_GLOBAL: u32 = 1073741824; pub const RTPRF_OURS: u32 = 262144; pub const RTF_BITS : & [u8 ; 223] = b"\x10\x01UP\x02GATEWAY\x03HOST\x04REJECT\x05DYNAMIC\x06MODIFIED\x07DONE\x08DELCLONE\tCLONING\nXRESOLVE\x0BLLINFO\x0CSTATIC\rBLACKHOLE\x0ENOIFREF\x0FPROTO2\x10PROTO1\x11PRCLONING\x12WASCLONED\x13PROTO3\x15PINNED\x16LOCAL\x17BROADCAST\x18MULTICAST\x19IFSCOPE\x1ACONDEMNED\x1BIFREF\x1CPROXY\x1DROUTER\x1FGLOBAL\0" ; pub const RTM_VERSION: u32 = 5; pub const RTM_ADD: u32 = 1; pub const RTM_DELETE: u32 = 2; pub const RTM_CHANGE: u32 = 3; pub const RTM_GET: u32 = 4; pub const RTM_LOSING: u32 = 5; pub const RTM_REDIRECT: u32 = 6; pub const RTM_MISS: u32 = 7; pub const RTM_LOCK: u32 = 8; pub const RTM_OLDADD: u32 = 9; pub const RTM_OLDDEL: u32 = 10; pub const RTM_RESOLVE: u32 = 11; pub const RTM_NEWADDR: u32 = 12; pub const RTM_DELADDR: u32 = 13; pub const RTM_IFINFO: u32 = 14; pub const RTM_NEWMADDR: u32 = 15; pub const RTM_DELMADDR: u32 = 16; pub const RTM_GET_SILENT: u32 = 17; pub const RTM_IFINFO2: u32 = 18; pub const RTM_NEWMADDR2: u32 = 19; pub const RTM_GET2: u32 = 20; pub const RTM_GET_EXT: u32 = 21; pub const RTV_MTU: u32 = 1; pub const RTV_HOPCOUNT: u32 = 2; pub const RTV_EXPIRE: u32 = 4; pub const RTV_RPIPE: u32 = 8; pub const RTV_SPIPE: u32 = 16; pub const RTV_SSTHRESH: u32 = 32; pub const RTV_RTT: u32 = 64; pub const RTV_RTTVAR: u32 = 128; pub const RTV_REFRESH_HOST: u32 = 256; pub const RTA_DST: u32 = 1; pub const RTA_GATEWAY: u32 = 2; pub const RTA_NETMASK: u32 = 4; pub const RTA_GENMASK: u32 = 8; pub const RTA_IFP: u32 = 16; pub const RTA_IFA: u32 = 32; pub const RTA_AUTHOR: u32 = 64; pub const RTA_BRD: u32 = 128; pub const RTAX_DST: u32 = 0; pub const RTAX_GATEWAY: u32 = 1; pub const RTAX_NETMASK: u32 = 2; pub const RTAX_GENMASK: u32 = 3; pub const RTAX_IFP: u32 = 4; pub const RTAX_IFA: u32 = 5; pub const RTAX_AUTHOR: u32 = 6; pub const RTAX_BRD: u32 = 7; pub const RTAX_MAX: u32 = 8; pub const IFSCOPE_NONE: u32 = 0; pub const APPLE_IF_FAM_LOOPBACK: u32 = 1; pub const APPLE_IF_FAM_ETHERNET: u32 = 2; pub const APPLE_IF_FAM_SLIP: u32 = 3; pub const APPLE_IF_FAM_TUN: u32 = 4; pub const APPLE_IF_FAM_VLAN: u32 = 5; pub const APPLE_IF_FAM_PPP: u32 = 6; pub const APPLE_IF_FAM_PVC: u32 = 7; pub const APPLE_IF_FAM_DISC: u32 = 8; pub const APPLE_IF_FAM_MDECAP: u32 = 9; pub const APPLE_IF_FAM_GIF: u32 = 10; pub const APPLE_IF_FAM_FAITH: u32 = 11; pub const APPLE_IF_FAM_STF: u32 = 12; pub const APPLE_IF_FAM_FIREWIRE: u32 = 13; pub const APPLE_IF_FAM_BOND: u32 = 14; pub const APPLE_IF_FAM_CELLULAR: u32 = 15; pub const APPLE_IF_FAM_6LOWPAN: u32 = 16; pub const APPLE_IF_FAM_UTUN: u32 = 17; pub const APPLE_IF_FAM_IPSEC: u32 = 18; pub const IF_MINMTU: u32 = 72; pub const IF_MAXMTU: u32 = 65535; pub const IFNAMSIZ: u32 = 16; pub const IF_NETEM_PARAMS_PSCALE: u32 = 100000; pub const IF_VAR_H_HAS_IFNET_STATS_PER_FLOW: u32 = 1; pub const IF_CELLULAR_STATUS_REPORT_VERSION_1: u32 = 1; pub const IF_WIFI_STATUS_REPORT_VERSION_1: u32 = 1; pub const IF_CELLULAR_STATUS_REPORT_CURRENT_VERSION: u32 = 1; pub const IF_WIFI_STATUS_REPORT_CURRENT_VERSION: u32 = 1; pub const IF_CELL_LINK_QUALITY_METRIC_VALID: u32 = 1; pub const IF_CELL_UL_EFFECTIVE_BANDWIDTH_VALID: u32 = 2; pub const IF_CELL_UL_MAX_BANDWIDTH_VALID: u32 = 4; pub const IF_CELL_UL_MIN_LATENCY_VALID: u32 = 8; pub const IF_CELL_UL_EFFECTIVE_LATENCY_VALID: u32 = 16; pub const IF_CELL_UL_MAX_LATENCY_VALID: u32 = 32; pub const IF_CELL_UL_RETXT_LEVEL_VALID: u32 = 64; pub const IF_CELL_UL_BYTES_LOST_VALID: u32 = 128; pub const IF_CELL_UL_MIN_QUEUE_SIZE_VALID: u32 = 256; pub const IF_CELL_UL_AVG_QUEUE_SIZE_VALID: u32 = 512; pub const IF_CELL_UL_MAX_QUEUE_SIZE_VALID: u32 = 1024; pub const IF_CELL_DL_EFFECTIVE_BANDWIDTH_VALID: u32 = 2048; pub const IF_CELL_DL_MAX_BANDWIDTH_VALID: u32 = 4096; pub const IF_CELL_CONFIG_INACTIVITY_TIME_VALID: u32 = 8192; pub const IF_CELL_CONFIG_BACKOFF_TIME_VALID: u32 = 16384; pub const IF_CELL_UL_MSS_RECOMMENDED_VALID: u32 = 32768; pub const IF_CELL_UL_RETXT_LEVEL_NONE: u32 = 1; pub const IF_CELL_UL_RETXT_LEVEL_LOW: u32 = 2; pub const IF_CELL_UL_RETXT_LEVEL_MEDIUM: u32 = 3; pub const IF_CELL_UL_RETXT_LEVEL_HIGH: u32 = 4; pub const IF_CELL_UL_MSS_RECOMMENDED_NONE: u32 = 0; pub const IF_CELL_UL_MSS_RECOMMENDED_MEDIUM: u32 = 1; pub const IF_CELL_UL_MSS_RECOMMENDED_LOW: u32 = 2; pub const IF_WIFI_LINK_QUALITY_METRIC_VALID: u32 = 1; pub const IF_WIFI_UL_EFFECTIVE_BANDWIDTH_VALID: u32 = 2; pub const IF_WIFI_UL_MAX_BANDWIDTH_VALID: u32 = 4; pub const IF_WIFI_UL_MIN_LATENCY_VALID: u32 = 8; pub const IF_WIFI_UL_EFFECTIVE_LATENCY_VALID: u32 = 16; pub const IF_WIFI_UL_MAX_LATENCY_VALID: u32 = 32; pub const IF_WIFI_UL_RETXT_LEVEL_VALID: u32 = 64; pub const IF_WIFI_UL_ERROR_RATE_VALID: u32 = 128; pub const IF_WIFI_UL_BYTES_LOST_VALID: u32 = 256; pub const IF_WIFI_DL_EFFECTIVE_BANDWIDTH_VALID: u32 = 512; pub const IF_WIFI_DL_MAX_BANDWIDTH_VALID: u32 = 1024; pub const IF_WIFI_DL_MIN_LATENCY_VALID: u32 = 2048; pub const IF_WIFI_DL_EFFECTIVE_LATENCY_VALID: u32 = 4096; pub const IF_WIFI_DL_MAX_LATENCY_VALID: u32 = 8192; pub const IF_WIFI_DL_ERROR_RATE_VALID: u32 = 16384; pub const IF_WIFI_CONFIG_FREQUENCY_VALID: u32 = 32768; pub const IF_WIFI_CONFIG_MULTICAST_RATE_VALID: u32 = 65536; pub const IF_WIFI_CONFIG_SCAN_COUNT_VALID: u32 = 131072; pub const IF_WIFI_CONFIG_SCAN_DURATION_VALID: u32 = 262144; pub const IF_WIFI_UL_RETXT_LEVEL_NONE: u32 = 1; pub const IF_WIFI_UL_RETXT_LEVEL_LOW: u32 = 2; pub const IF_WIFI_UL_RETXT_LEVEL_MEDIUM: u32 = 3; pub const IF_WIFI_UL_RETXT_LEVEL_HIGH: u32 = 4; pub const IF_WIFI_CONFIG_FREQUENCY_2_4_GHZ: u32 = 1; pub const IF_WIFI_CONFIG_FREQUENCY_5_0_GHZ: u32 = 2; pub const IF_INTERFACE_STATE_RRC_STATE_VALID: u32 = 1; pub const IF_INTERFACE_STATE_LQM_STATE_VALID: u32 = 2; pub const IF_INTERFACE_STATE_INTERFACE_AVAILABILITY_VALID: u32 = 4; pub const IF_INTERFACE_STATE_RRC_STATE_IDLE: u32 = 0; pub const IF_INTERFACE_STATE_RRC_STATE_CONNECTED: u32 = 1; pub const IF_INTERFACE_STATE_INTERFACE_AVAILABLE: u32 = 0; pub const IF_INTERFACE_STATE_INTERFACE_UNAVAILABLE: u32 = 1; pub const IF_INTERFACE_ADVISORY_VERSION_1: u32 = 1; pub const IF_INTERFACE_ADVISORY_VERSION_CURRENT: u32 = 1; pub const IF_INTERFACE_ADVISORY_DIRECTION_TX: u32 = 1; pub const IF_INTERFACE_ADVISORY_DIRECTION_RX: u32 = 2; pub const IF_INTERFACE_ADVISORY_RATE_SUGGESTION_RAMP_UP: u32 = 2147483647; pub const IF_INTERFACE_ADVISORY_RATE_SUGGESTION_RAMP_DOWN: i32 = -2147483648; pub const IF_INTERFACE_ADVISORY_RATE_SUGGESTION_RAMP_NEUTRAL: u32 = 0; pub const IF_HWASSIST_CSUM_IP: u32 = 1; pub const IF_HWASSIST_CSUM_TCP: u32 = 2; pub const IF_HWASSIST_CSUM_UDP: u32 = 4; pub const IF_HWASSIST_CSUM_IP_FRAGS: u32 = 8; pub const IF_HWASSIST_CSUM_FRAGMENT: u32 = 16; pub const IF_HWASSIST_CSUM_TCPIPV6: u32 = 32; pub const IF_HWASSIST_CSUM_UDPIPV6: u32 = 64; pub const IF_HWASSIST_CSUM_FRAGMENT_IPV6: u32 = 128; pub const IF_HWASSIST_CSUM_PARTIAL: u32 = 4096; pub const IF_HWASSIST_CSUM_ZERO_INVERT: u32 = 8192; pub const IF_HWASSIST_CSUM_MASK: u32 = 65535; pub const IF_HWASSIST_VLAN_TAGGING: u32 = 65536; pub const IF_HWASSIST_VLAN_MTU: u32 = 131072; pub const IF_HWASSIST_TSO_V4: u32 = 2097152; pub const IF_HWASSIST_TSO_V6: u32 = 4194304; pub const IFXNAMSIZ: u32 = 24; pub const IFNET_NETWORK_ID_LEN: u32 = 32; pub const PF_MD5_DIGEST_LENGTH: u32 = 16; pub const PF_GRE_PPTP_VARIANT: u32 = 1; pub const PFTM_TCP_FIRST_PACKET_VAL: u32 = 120; pub const PFTM_TCP_OPENING_VAL: u32 = 30; pub const PFTM_TCP_ESTABLISHED_VAL: u32 = 86400; pub const PFTM_TCP_CLOSING_VAL: u32 = 900; pub const PFTM_TCP_FIN_WAIT_VAL: u32 = 45; pub const PFTM_TCP_CLOSED_VAL: u32 = 90; pub const PFTM_UDP_FIRST_PACKET_VAL: u32 = 60; pub const PFTM_UDP_SINGLE_VAL: u32 = 30; pub const PFTM_UDP_MULTIPLE_VAL: u32 = 60; pub const PFTM_ICMP_FIRST_PACKET_VAL: u32 = 20; pub const PFTM_ICMP_ERROR_REPLY_VAL: u32 = 10; pub const PFTM_GREv1_FIRST_PACKET_VAL: u32 = 120; pub const PFTM_GREv1_INITIATING_VAL: u32 = 30; pub const PFTM_GREv1_ESTABLISHED_VAL: u32 = 1800; pub const PFTM_ESP_FIRST_PACKET_VAL: u32 = 120; pub const PFTM_ESP_INITIATING_VAL: u32 = 30; pub const PFTM_ESP_ESTABLISHED_VAL: u32 = 900; pub const PFTM_OTHER_FIRST_PACKET_VAL: u32 = 60; pub const PFTM_OTHER_SINGLE_VAL: u32 = 30; pub const PFTM_OTHER_MULTIPLE_VAL: u32 = 60; pub const PFTM_FRAG_VAL: u32 = 30; pub const PFTM_INTERVAL_VAL: u32 = 10; pub const PFTM_SRC_NODE_VAL: u32 = 0; pub const PFTM_TS_DIFF_VAL: u32 = 30; pub const PF_POOL_IDMASK: u32 = 15; pub const PF_POOL_TYPEMASK: u32 = 15; pub const PF_POOL_STICKYADDR: u32 = 32; pub const PF_WSCALE_FLAG: u32 = 128; pub const PF_WSCALE_MASK: u32 = 15; pub const PF_LOG: u32 = 1; pub const PF_LOG_ALL: u32 = 2; pub const PF_LOG_SOCKET_LOOKUP: u32 = 4; pub const PF_TABLE_NAME_SIZE: u32 = 32; pub const PFI_AFLAG_NETWORK: u32 = 1; pub const PFI_AFLAG_BROADCAST: u32 = 2; pub const PFI_AFLAG_PEER: u32 = 4; pub const PFI_AFLAG_MODEMASK: u32 = 7; pub const PFI_AFLAG_NOALIAS: u32 = 8; pub const RTLABEL_LEN: u32 = 32; pub const PF_OSFP_EXPANDED: u32 = 1; pub const PF_OSFP_GENERIC: u32 = 2; pub const PF_OSFP_NODETAIL: u32 = 4; pub const PF_OSFP_LEN: u32 = 32; pub const _FP_RESERVED_BIT: u32 = 1; pub const _FP_UNUSED_BITS: u32 = 1; pub const _FP_CLASS_BITS: u32 = 10; pub const _FP_VERSION_BITS: u32 = 10; pub const _FP_SUBTYPE_BITS: u32 = 10; pub const PF_OSFP_WSIZE_MOD: u32 = 1; pub const PF_OSFP_WSIZE_DC: u32 = 2; pub const PF_OSFP_WSIZE_MSS: u32 = 4; pub const PF_OSFP_WSIZE_MTU: u32 = 8; pub const PF_OSFP_PSIZE_MOD: u32 = 16; pub const PF_OSFP_PSIZE_DC: u32 = 32; pub const PF_OSFP_WSCALE: u32 = 64; pub const PF_OSFP_WSCALE_MOD: u32 = 128; pub const PF_OSFP_WSCALE_DC: u32 = 256; pub const PF_OSFP_MSS: u32 = 512; pub const PF_OSFP_MSS_MOD: u32 = 1024; pub const PF_OSFP_MSS_DC: u32 = 2048; pub const PF_OSFP_DF: u32 = 4096; pub const PF_OSFP_TS0: u32 = 8192; pub const PF_OSFP_INET6: u32 = 16384; pub const PF_OSFP_MAXTTL_OFFSET: u32 = 40; pub const PF_OSFP_TCPOPT_NOP: u32 = 0; pub const PF_OSFP_TCPOPT_WSCALE: u32 = 1; pub const PF_OSFP_TCPOPT_MSS: u32 = 2; pub const PF_OSFP_TCPOPT_SACK: u32 = 3; pub const PF_OSFP_TCPOPT_TS: u32 = 4; pub const PF_OSFP_TCPOPT_BITS: u32 = 3; pub const PF_ANCHOR_NAME_SIZE: u32 = 64; pub const PF_SKIP_IFP: u32 = 0; pub const PF_SKIP_DIR: u32 = 1; pub const PF_SKIP_AF: u32 = 2; pub const PF_SKIP_PROTO: u32 = 3; pub const PF_SKIP_SRC_ADDR: u32 = 4; pub const PF_SKIP_SRC_PORT: u32 = 5; pub const PF_SKIP_DST_ADDR: u32 = 6; pub const PF_SKIP_DST_PORT: u32 = 7; pub const PF_SKIP_COUNT: u32 = 8; pub const PF_RULE_LABEL_SIZE: u32 = 64; pub const PF_QNAME_SIZE: u32 = 64; pub const PF_TAG_NAME_SIZE: u32 = 64; pub const PF_OWNER_NAME_SIZE: u32 = 64; pub const PF_STATE_NORMAL: u32 = 1; pub const PF_STATE_MODULATE: u32 = 2; pub const PF_STATE_SYNPROXY: u32 = 3; pub const SCIDX_MASK: u32 = 15; pub const SC_BE: u32 = 16; pub const SC_BK_SYS: u32 = 17; pub const SC_BK: u32 = 18; pub const SC_RD: u32 = 19; pub const SC_OAM: u32 = 20; pub const SC_AV: u32 = 21; pub const SC_RV: u32 = 22; pub const SC_VI: u32 = 23; pub const SC_SIG: u32 = 23; pub const SC_VO: u32 = 24; pub const SC_CTL: u32 = 25; pub const DSCP_MASK: u32 = 252; pub const DSCP_CUMASK: u32 = 3; pub const DSCP_EF: u32 = 184; pub const DSCP_AF11: u32 = 40; pub const DSCP_AF12: u32 = 48; pub const DSCP_AF13: u32 = 56; pub const DSCP_AF21: u32 = 72; pub const DSCP_AF22: u32 = 80; pub const DSCP_AF23: u32 = 88; pub const DSCP_AF31: u32 = 104; pub const DSCP_AF32: u32 = 112; pub const DSCP_AF33: u32 = 120; pub const DSCP_AF41: u32 = 136; pub const DSCP_AF42: u32 = 144; pub const DSCP_AF43: u32 = 152; pub const AF_CLASSMASK: u32 = 224; pub const AF_DROPPRECMASK: u32 = 24; pub const PF_FLUSH: u32 = 1; pub const PF_FLUSH_GLOBAL: u32 = 2; pub const PFDEV_PF: u32 = 0; pub const PFDEV_PFM: u32 = 1; pub const PFDEV_MAX: u32 = 2; pub const PFRULE_DROP: u32 = 0; pub const PFRULE_RETURNRST: u32 = 1; pub const PFRULE_FRAGMENT: u32 = 2; pub const PFRULE_RETURNICMP: u32 = 4; pub const PFRULE_RETURN: u32 = 8; pub const PFRULE_NOSYNC: u32 = 16; pub const PFRULE_SRCTRACK: u32 = 32; pub const PFRULE_RULESRCTRACK: u32 = 64; pub const PFRULE_NODF: u32 = 256; pub const PFRULE_FRAGCROP: u32 = 512; pub const PFRULE_FRAGDROP: u32 = 1024; pub const PFRULE_RANDOMID: u32 = 2048; pub const PFRULE_REASSEMBLE_TCP: u32 = 4096; pub const PFRULE_TOS: u32 = 8192; pub const PFRULE_DSCP: u32 = 16384; pub const PFRULE_SC: u32 = 32768; pub const PFRULE_IFBOUND: u32 = 65536; pub const PFRULE_PFM: u32 = 131072; pub const PFSTATE_HIWAT: u32 = 10000; pub const PFSTATE_ADAPT_START: u32 = 6000; pub const PFSTATE_ADAPT_END: u32 = 12000; pub const PFAPPSTATE_HIWAT: u32 = 10000; pub const PF_TAG_NAME_SYSTEM_SERVICE: &[u8; 32] = b"com.apple.pf.system_service_tag\0"; pub const PF_TAG_NAME_STACK_DROP: &[u8; 28] = b"com.apple.pf.stack_drop_tag\0"; pub const PF_THRESHOLD_MULT: u32 = 1000; pub const PF_THRESHOLD_MAX: u32 = 4294967; pub const PFSNODE_HIWAT: u32 = 10000; pub const PFSTATE_NOSYNC: u32 = 1; pub const PFSTATE_FROMSYNC: u32 = 2; pub const PFSTATE_STALE: u32 = 4; pub const PFSYNC_SCRUB_FLAG_VALID: u32 = 1; pub const PFSYNC_FLAG_COMPRESS: u32 = 1; pub const PFSYNC_FLAG_STALE: u32 = 2; pub const PFSYNC_FLAG_SRCNODE: u32 = 4; pub const PFSYNC_FLAG_NATSRCNODE: u32 = 8; pub const PF_RESERVED_ANCHOR: &[u8; 4] = b"_pf\0"; pub const PFR_TFLAG_PERSIST: u32 = 1; pub const PFR_TFLAG_CONST: u32 = 2; pub const PFR_TFLAG_ACTIVE: u32 = 4; pub const PFR_TFLAG_INACTIVE: u32 = 8; pub const PFR_TFLAG_REFERENCED: u32 = 16; pub const PFR_TFLAG_REFDANCHOR: u32 = 32; pub const PFR_TFLAG_USRMASK: u32 = 3; pub const PFR_TFLAG_SETMASK: u32 = 60; pub const PFR_TFLAG_ALLMASK: u32 = 63; pub const PFI_IFLAG_SKIP: u32 = 256; pub const PF_DPORT_RANGE: u32 = 1; pub const PF_RPORT_RANGE: u32 = 2; pub const PFRES_MATCH: u32 = 0; pub const PFRES_BADOFF: u32 = 1; pub const PFRES_FRAG: u32 = 2; pub const PFRES_SHORT: u32 = 3; pub const PFRES_NORM: u32 = 4; pub const PFRES_MEMORY: u32 = 5; pub const PFRES_TS: u32 = 6; pub const PFRES_CONGEST: u32 = 7; pub const PFRES_IPOPTIONS: u32 = 8; pub const PFRES_PROTCKSUM: u32 = 9; pub const PFRES_BADSTATE: u32 = 10; pub const PFRES_STATEINS: u32 = 11; pub const PFRES_MAXSTATES: u32 = 12; pub const PFRES_SRCLIMIT: u32 = 13; pub const PFRES_SYNPROXY: u32 = 14; pub const PFRES_DUMMYNET: u32 = 15; pub const PFRES_MAX: u32 = 16; pub const LCNT_STATES: u32 = 0; pub const LCNT_SRCSTATES: u32 = 1; pub const LCNT_SRCNODES: u32 = 2; pub const LCNT_SRCCONN: u32 = 3; pub const LCNT_SRCCONNRATE: u32 = 4; pub const LCNT_OVERLOAD_TABLE: u32 = 5; pub const LCNT_OVERLOAD_FLUSH: u32 = 6; pub const LCNT_MAX: u32 = 7; pub const PFUDPS_NO_TRAFFIC: u32 = 0; pub const PFUDPS_SINGLE: u32 = 1; pub const PFUDPS_MULTIPLE: u32 = 2; pub const PFUDPS_NSTATES: u32 = 3; pub const PFGRE1S_NO_TRAFFIC: u32 = 0; pub const PFGRE1S_INITIATING: u32 = 1; pub const PFGRE1S_ESTABLISHED: u32 = 2; pub const PFGRE1S_NSTATES: u32 = 3; pub const PFESPS_NO_TRAFFIC: u32 = 0; pub const PFESPS_INITIATING: u32 = 1; pub const PFESPS_ESTABLISHED: u32 = 2; pub const PFESPS_NSTATES: u32 = 3; pub const PFOTHERS_NO_TRAFFIC: u32 = 0; pub const PFOTHERS_SINGLE: u32 = 1; pub const PFOTHERS_MULTIPLE: u32 = 2; pub const PFOTHERS_NSTATES: u32 = 3; pub const FCNT_STATE_SEARCH: u32 = 0; pub const FCNT_STATE_INSERT: u32 = 1; pub const FCNT_STATE_REMOVALS: u32 = 2; pub const FCNT_MAX: u32 = 3; pub const SCNT_SRC_NODE_SEARCH: u32 = 0; pub const SCNT_SRC_NODE_INSERT: u32 = 1; pub const SCNT_SRC_NODE_REMOVALS: u32 = 2; pub const SCNT_MAX: u32 = 3; pub const PF_ALTQ_BW_ABSOLUTE: u32 = 1; pub const PF_ALTQ_BW_PERCENT: u32 = 2; pub const PF_ALTQF_TBR: u32 = 1; pub const PF_ALTQ_QRF_WEIGHT: u32 = 1; pub const PFFRAG_FRENT_HIWAT: u32 = 5000; pub const PFFRAG_FRAG_HIWAT: u32 = 1000; pub const PFFRAG_FRCENT_HIWAT: u32 = 50000; pub const PFFRAG_FRCACHE_HIWAT: u32 = 10000; pub const PFR_KTABLE_HIWAT: u32 = 1000; pub const PFR_KENTRY_HIWAT: u32 = 200000; pub const PFR_KENTRY_HIWAT_SMALL: u32 = 100000; pub const PFTOK_PROCNAME_LEN: u32 = 64; pub const PFR_FLAG_ATOMIC: u32 = 1; pub const PFR_FLAG_DUMMY: u32 = 2; pub const PFR_FLAG_FEEDBACK: u32 = 4; pub const PFR_FLAG_CLSTATS: u32 = 8; pub const PFR_FLAG_ADDRSTOO: u32 = 16; pub const PFR_FLAG_REPLACE: u32 = 32; pub const PFR_FLAG_ALLRSETS: u32 = 64; pub const PFR_FLAG_ALLMASK: u32 = 127; pub type __int8_t = ::std::os::raw::c_schar; pub type __uint8_t = ::std::os::raw::c_uchar; pub type __int16_t = ::std::os::raw::c_short; pub type __uint16_t = ::std::os::raw::c_ushort; pub type __int32_t = ::std::os::raw::c_int; pub type __uint32_t = ::std::os::raw::c_uint; pub type __int64_t = ::std::os::raw::c_longlong; pub type __uint64_t = ::std::os::raw::c_ulonglong; pub type __darwin_intptr_t = ::std::os::raw::c_long; pub type __darwin_natural_t = ::std::os::raw::c_uint; pub type __darwin_ct_rune_t = ::std::os::raw::c_int; #[repr(C)] #[derive(Copy, Clone)] pub union __mbstate_t { pub __mbstate8: [::std::os::raw::c_char; 128usize], pub _mbstateL: ::std::os::raw::c_longlong, } #[test] fn bindgen_test_layout___mbstate_t() { const UNINIT: ::std::mem::MaybeUninit<__mbstate_t> = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::<__mbstate_t>(), 128usize, concat!("Size of: ", stringify!(__mbstate_t)) ); assert_eq!( ::std::mem::align_of::<__mbstate_t>(), 8usize, concat!("Alignment of ", stringify!(__mbstate_t)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__mbstate8) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(__mbstate_t), "::", stringify!(__mbstate8) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr)._mbstateL) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(__mbstate_t), "::", stringify!(_mbstateL) ) ); } pub type __darwin_mbstate_t = __mbstate_t; pub type __darwin_ptrdiff_t = ::std::os::raw::c_long; pub type __darwin_size_t = ::std::os::raw::c_ulong; pub type __darwin_va_list = __builtin_va_list; pub type __darwin_wchar_t = ::std::os::raw::c_int; pub type __darwin_rune_t = __darwin_wchar_t; pub type __darwin_wint_t = ::std::os::raw::c_int; pub type __darwin_clock_t = ::std::os::raw::c_ulong; pub type __darwin_socklen_t = __uint32_t; pub type __darwin_ssize_t = ::std::os::raw::c_long; pub type __darwin_time_t = ::std::os::raw::c_long; pub type __darwin_blkcnt_t = __int64_t; pub type __darwin_blksize_t = __int32_t; pub type __darwin_dev_t = __int32_t; pub type __darwin_fsblkcnt_t = ::std::os::raw::c_uint; pub type __darwin_fsfilcnt_t = ::std::os::raw::c_uint; pub type __darwin_gid_t = __uint32_t; pub type __darwin_id_t = __uint32_t; pub type __darwin_ino64_t = __uint64_t; pub type __darwin_ino_t = __darwin_ino64_t; pub type __darwin_mach_port_name_t = __darwin_natural_t; pub type __darwin_mach_port_t = __darwin_mach_port_name_t; pub type __darwin_mode_t = __uint16_t; pub type __darwin_off_t = __int64_t; pub type __darwin_pid_t = __int32_t; pub type __darwin_sigset_t = __uint32_t; pub type __darwin_suseconds_t = __int32_t; pub type __darwin_uid_t = __uint32_t; pub type __darwin_useconds_t = __uint32_t; pub type __darwin_uuid_t = [::std::os::raw::c_uchar; 16usize]; pub type __darwin_uuid_string_t = [::std::os::raw::c_char; 37usize]; #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct __darwin_pthread_handler_rec { pub __routine: ::std::option::Option, pub __arg: *mut ::std::os::raw::c_void, pub __next: *mut __darwin_pthread_handler_rec, } #[test] fn bindgen_test_layout___darwin_pthread_handler_rec() { const UNINIT: ::std::mem::MaybeUninit<__darwin_pthread_handler_rec> = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::<__darwin_pthread_handler_rec>(), 24usize, concat!("Size of: ", stringify!(__darwin_pthread_handler_rec)) ); assert_eq!( ::std::mem::align_of::<__darwin_pthread_handler_rec>(), 8usize, concat!("Alignment of ", stringify!(__darwin_pthread_handler_rec)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__routine) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(__darwin_pthread_handler_rec), "::", stringify!(__routine) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__arg) as usize - ptr as usize }, 8usize, concat!( "Offset of field: ", stringify!(__darwin_pthread_handler_rec), "::", stringify!(__arg) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__next) as usize - ptr as usize }, 16usize, concat!( "Offset of field: ", stringify!(__darwin_pthread_handler_rec), "::", stringify!(__next) ) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct _opaque_pthread_attr_t { pub __sig: ::std::os::raw::c_long, pub __opaque: [::std::os::raw::c_char; 56usize], } #[test] fn bindgen_test_layout__opaque_pthread_attr_t() { const UNINIT: ::std::mem::MaybeUninit<_opaque_pthread_attr_t> = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::<_opaque_pthread_attr_t>(), 64usize, concat!("Size of: ", stringify!(_opaque_pthread_attr_t)) ); assert_eq!( ::std::mem::align_of::<_opaque_pthread_attr_t>(), 8usize, concat!("Alignment of ", stringify!(_opaque_pthread_attr_t)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__sig) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(_opaque_pthread_attr_t), "::", stringify!(__sig) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__opaque) as usize - ptr as usize }, 8usize, concat!( "Offset of field: ", stringify!(_opaque_pthread_attr_t), "::", stringify!(__opaque) ) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct _opaque_pthread_cond_t { pub __sig: ::std::os::raw::c_long, pub __opaque: [::std::os::raw::c_char; 40usize], } #[test] fn bindgen_test_layout__opaque_pthread_cond_t() { const UNINIT: ::std::mem::MaybeUninit<_opaque_pthread_cond_t> = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::<_opaque_pthread_cond_t>(), 48usize, concat!("Size of: ", stringify!(_opaque_pthread_cond_t)) ); assert_eq!( ::std::mem::align_of::<_opaque_pthread_cond_t>(), 8usize, concat!("Alignment of ", stringify!(_opaque_pthread_cond_t)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__sig) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(_opaque_pthread_cond_t), "::", stringify!(__sig) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__opaque) as usize - ptr as usize }, 8usize, concat!( "Offset of field: ", stringify!(_opaque_pthread_cond_t), "::", stringify!(__opaque) ) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct _opaque_pthread_condattr_t { pub __sig: ::std::os::raw::c_long, pub __opaque: [::std::os::raw::c_char; 8usize], } #[test] fn bindgen_test_layout__opaque_pthread_condattr_t() { const UNINIT: ::std::mem::MaybeUninit<_opaque_pthread_condattr_t> = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::<_opaque_pthread_condattr_t>(), 16usize, concat!("Size of: ", stringify!(_opaque_pthread_condattr_t)) ); assert_eq!( ::std::mem::align_of::<_opaque_pthread_condattr_t>(), 8usize, concat!("Alignment of ", stringify!(_opaque_pthread_condattr_t)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__sig) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(_opaque_pthread_condattr_t), "::", stringify!(__sig) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__opaque) as usize - ptr as usize }, 8usize, concat!( "Offset of field: ", stringify!(_opaque_pthread_condattr_t), "::", stringify!(__opaque) ) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct _opaque_pthread_mutex_t { pub __sig: ::std::os::raw::c_long, pub __opaque: [::std::os::raw::c_char; 56usize], } #[test] fn bindgen_test_layout__opaque_pthread_mutex_t() { const UNINIT: ::std::mem::MaybeUninit<_opaque_pthread_mutex_t> = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::<_opaque_pthread_mutex_t>(), 64usize, concat!("Size of: ", stringify!(_opaque_pthread_mutex_t)) ); assert_eq!( ::std::mem::align_of::<_opaque_pthread_mutex_t>(), 8usize, concat!("Alignment of ", stringify!(_opaque_pthread_mutex_t)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__sig) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(_opaque_pthread_mutex_t), "::", stringify!(__sig) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__opaque) as usize - ptr as usize }, 8usize, concat!( "Offset of field: ", stringify!(_opaque_pthread_mutex_t), "::", stringify!(__opaque) ) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct _opaque_pthread_mutexattr_t { pub __sig: ::std::os::raw::c_long, pub __opaque: [::std::os::raw::c_char; 8usize], } #[test] fn bindgen_test_layout__opaque_pthread_mutexattr_t() { const UNINIT: ::std::mem::MaybeUninit<_opaque_pthread_mutexattr_t> = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::<_opaque_pthread_mutexattr_t>(), 16usize, concat!("Size of: ", stringify!(_opaque_pthread_mutexattr_t)) ); assert_eq!( ::std::mem::align_of::<_opaque_pthread_mutexattr_t>(), 8usize, concat!("Alignment of ", stringify!(_opaque_pthread_mutexattr_t)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__sig) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(_opaque_pthread_mutexattr_t), "::", stringify!(__sig) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__opaque) as usize - ptr as usize }, 8usize, concat!( "Offset of field: ", stringify!(_opaque_pthread_mutexattr_t), "::", stringify!(__opaque) ) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct _opaque_pthread_once_t { pub __sig: ::std::os::raw::c_long, pub __opaque: [::std::os::raw::c_char; 8usize], } #[test] fn bindgen_test_layout__opaque_pthread_once_t() { const UNINIT: ::std::mem::MaybeUninit<_opaque_pthread_once_t> = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::<_opaque_pthread_once_t>(), 16usize, concat!("Size of: ", stringify!(_opaque_pthread_once_t)) ); assert_eq!( ::std::mem::align_of::<_opaque_pthread_once_t>(), 8usize, concat!("Alignment of ", stringify!(_opaque_pthread_once_t)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__sig) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(_opaque_pthread_once_t), "::", stringify!(__sig) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__opaque) as usize - ptr as usize }, 8usize, concat!( "Offset of field: ", stringify!(_opaque_pthread_once_t), "::", stringify!(__opaque) ) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct _opaque_pthread_rwlock_t { pub __sig: ::std::os::raw::c_long, pub __opaque: [::std::os::raw::c_char; 192usize], } #[test] fn bindgen_test_layout__opaque_pthread_rwlock_t() { const UNINIT: ::std::mem::MaybeUninit<_opaque_pthread_rwlock_t> = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::<_opaque_pthread_rwlock_t>(), 200usize, concat!("Size of: ", stringify!(_opaque_pthread_rwlock_t)) ); assert_eq!( ::std::mem::align_of::<_opaque_pthread_rwlock_t>(), 8usize, concat!("Alignment of ", stringify!(_opaque_pthread_rwlock_t)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__sig) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(_opaque_pthread_rwlock_t), "::", stringify!(__sig) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__opaque) as usize - ptr as usize }, 8usize, concat!( "Offset of field: ", stringify!(_opaque_pthread_rwlock_t), "::", stringify!(__opaque) ) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct _opaque_pthread_rwlockattr_t { pub __sig: ::std::os::raw::c_long, pub __opaque: [::std::os::raw::c_char; 16usize], } #[test] fn bindgen_test_layout__opaque_pthread_rwlockattr_t() { const UNINIT: ::std::mem::MaybeUninit<_opaque_pthread_rwlockattr_t> = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::<_opaque_pthread_rwlockattr_t>(), 24usize, concat!("Size of: ", stringify!(_opaque_pthread_rwlockattr_t)) ); assert_eq!( ::std::mem::align_of::<_opaque_pthread_rwlockattr_t>(), 8usize, concat!("Alignment of ", stringify!(_opaque_pthread_rwlockattr_t)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__sig) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(_opaque_pthread_rwlockattr_t), "::", stringify!(__sig) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__opaque) as usize - ptr as usize }, 8usize, concat!( "Offset of field: ", stringify!(_opaque_pthread_rwlockattr_t), "::", stringify!(__opaque) ) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct _opaque_pthread_t { pub __sig: ::std::os::raw::c_long, pub __cleanup_stack: *mut __darwin_pthread_handler_rec, pub __opaque: [::std::os::raw::c_char; 8176usize], } #[test] fn bindgen_test_layout__opaque_pthread_t() { const UNINIT: ::std::mem::MaybeUninit<_opaque_pthread_t> = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::<_opaque_pthread_t>(), 8192usize, concat!("Size of: ", stringify!(_opaque_pthread_t)) ); assert_eq!( ::std::mem::align_of::<_opaque_pthread_t>(), 8usize, concat!("Alignment of ", stringify!(_opaque_pthread_t)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__sig) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(_opaque_pthread_t), "::", stringify!(__sig) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__cleanup_stack) as usize - ptr as usize }, 8usize, concat!( "Offset of field: ", stringify!(_opaque_pthread_t), "::", stringify!(__cleanup_stack) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__opaque) as usize - ptr as usize }, 16usize, concat!( "Offset of field: ", stringify!(_opaque_pthread_t), "::", stringify!(__opaque) ) ); } pub type __darwin_pthread_attr_t = _opaque_pthread_attr_t; pub type __darwin_pthread_cond_t = _opaque_pthread_cond_t; pub type __darwin_pthread_condattr_t = _opaque_pthread_condattr_t; pub type __darwin_pthread_key_t = ::std::os::raw::c_ulong; pub type __darwin_pthread_mutex_t = _opaque_pthread_mutex_t; pub type __darwin_pthread_mutexattr_t = _opaque_pthread_mutexattr_t; pub type __darwin_pthread_once_t = _opaque_pthread_once_t; pub type __darwin_pthread_rwlock_t = _opaque_pthread_rwlock_t; pub type __darwin_pthread_rwlockattr_t = _opaque_pthread_rwlockattr_t; pub type __darwin_pthread_t = *mut _opaque_pthread_t; pub type u_int8_t = ::std::os::raw::c_uchar; pub type u_int16_t = ::std::os::raw::c_ushort; pub type u_int32_t = ::std::os::raw::c_uint; pub type u_int64_t = ::std::os::raw::c_ulonglong; pub type register_t = i64; pub type user_addr_t = u_int64_t; pub type user_size_t = u_int64_t; pub type user_ssize_t = i64; pub type user_long_t = i64; pub type user_ulong_t = u_int64_t; pub type user_time_t = i64; pub type user_off_t = i64; pub type syscall_arg_t = u_int64_t; pub type u_char = ::std::os::raw::c_uchar; pub type u_short = ::std::os::raw::c_ushort; pub type u_int = ::std::os::raw::c_uint; pub type u_long = ::std::os::raw::c_ulong; pub type ushort = ::std::os::raw::c_ushort; pub type uint = ::std::os::raw::c_uint; pub type u_quad_t = u_int64_t; pub type quad_t = i64; pub type qaddr_t = *mut quad_t; pub type caddr_t = *mut ::std::os::raw::c_char; pub type daddr_t = i32; pub type dev_t = __darwin_dev_t; pub type fixpt_t = u_int32_t; pub type blkcnt_t = __darwin_blkcnt_t; pub type blksize_t = __darwin_blksize_t; pub type gid_t = __darwin_gid_t; pub type in_addr_t = __uint32_t; pub type in_port_t = __uint16_t; pub type ino_t = __darwin_ino_t; pub type ino64_t = __darwin_ino64_t; pub type key_t = __int32_t; pub type mode_t = __darwin_mode_t; pub type nlink_t = __uint16_t; pub type id_t = __darwin_id_t; pub type pid_t = __darwin_pid_t; pub type off_t = __darwin_off_t; pub type segsz_t = i32; pub type swblk_t = i32; pub type uid_t = __darwin_uid_t; pub type clock_t = __darwin_clock_t; pub type time_t = __darwin_time_t; pub type useconds_t = __darwin_useconds_t; pub type suseconds_t = __darwin_suseconds_t; pub type rsize_t = __darwin_size_t; pub type errno_t = ::std::os::raw::c_int; #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct fd_set { pub fds_bits: [__int32_t; 32usize], } #[test] fn bindgen_test_layout_fd_set() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 128usize, concat!("Size of: ", stringify!(fd_set)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(fd_set)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).fds_bits) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(fd_set), "::", stringify!(fds_bits)) ); } unsafe extern "C" { pub fn __darwin_check_fd_set_overflow( arg1: ::std::os::raw::c_int, arg2: *const ::std::os::raw::c_void, arg3: ::std::os::raw::c_int, ) -> ::std::os::raw::c_int; } pub type fd_mask = __int32_t; pub type pthread_attr_t = __darwin_pthread_attr_t; pub type pthread_cond_t = __darwin_pthread_cond_t; pub type pthread_condattr_t = __darwin_pthread_condattr_t; pub type pthread_mutex_t = __darwin_pthread_mutex_t; pub type pthread_mutexattr_t = __darwin_pthread_mutexattr_t; pub type pthread_once_t = __darwin_pthread_once_t; pub type pthread_rwlock_t = __darwin_pthread_rwlock_t; pub type pthread_rwlockattr_t = __darwin_pthread_rwlockattr_t; pub type pthread_t = __darwin_pthread_t; pub type pthread_key_t = __darwin_pthread_key_t; pub type fsblkcnt_t = __darwin_fsblkcnt_t; pub type fsfilcnt_t = __darwin_fsfilcnt_t; pub type sig_atomic_t = ::std::os::raw::c_int; #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct __darwin_i386_thread_state { pub __eax: ::std::os::raw::c_uint, pub __ebx: ::std::os::raw::c_uint, pub __ecx: ::std::os::raw::c_uint, pub __edx: ::std::os::raw::c_uint, pub __edi: ::std::os::raw::c_uint, pub __esi: ::std::os::raw::c_uint, pub __ebp: ::std::os::raw::c_uint, pub __esp: ::std::os::raw::c_uint, pub __ss: ::std::os::raw::c_uint, pub __eflags: ::std::os::raw::c_uint, pub __eip: ::std::os::raw::c_uint, pub __cs: ::std::os::raw::c_uint, pub __ds: ::std::os::raw::c_uint, pub __es: ::std::os::raw::c_uint, pub __fs: ::std::os::raw::c_uint, pub __gs: ::std::os::raw::c_uint, } #[test] fn bindgen_test_layout___darwin_i386_thread_state() { const UNINIT: ::std::mem::MaybeUninit<__darwin_i386_thread_state> = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::<__darwin_i386_thread_state>(), 64usize, concat!("Size of: ", stringify!(__darwin_i386_thread_state)) ); assert_eq!( ::std::mem::align_of::<__darwin_i386_thread_state>(), 4usize, concat!("Alignment of ", stringify!(__darwin_i386_thread_state)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__eax) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(__darwin_i386_thread_state), "::", stringify!(__eax) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__ebx) as usize - ptr as usize }, 4usize, concat!( "Offset of field: ", stringify!(__darwin_i386_thread_state), "::", stringify!(__ebx) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__ecx) as usize - ptr as usize }, 8usize, concat!( "Offset of field: ", stringify!(__darwin_i386_thread_state), "::", stringify!(__ecx) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__edx) as usize - ptr as usize }, 12usize, concat!( "Offset of field: ", stringify!(__darwin_i386_thread_state), "::", stringify!(__edx) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__edi) as usize - ptr as usize }, 16usize, concat!( "Offset of field: ", stringify!(__darwin_i386_thread_state), "::", stringify!(__edi) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__esi) as usize - ptr as usize }, 20usize, concat!( "Offset of field: ", stringify!(__darwin_i386_thread_state), "::", stringify!(__esi) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__ebp) as usize - ptr as usize }, 24usize, concat!( "Offset of field: ", stringify!(__darwin_i386_thread_state), "::", stringify!(__ebp) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__esp) as usize - ptr as usize }, 28usize, concat!( "Offset of field: ", stringify!(__darwin_i386_thread_state), "::", stringify!(__esp) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__ss) as usize - ptr as usize }, 32usize, concat!( "Offset of field: ", stringify!(__darwin_i386_thread_state), "::", stringify!(__ss) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__eflags) as usize - ptr as usize }, 36usize, concat!( "Offset of field: ", stringify!(__darwin_i386_thread_state), "::", stringify!(__eflags) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__eip) as usize - ptr as usize }, 40usize, concat!( "Offset of field: ", stringify!(__darwin_i386_thread_state), "::", stringify!(__eip) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__cs) as usize - ptr as usize }, 44usize, concat!( "Offset of field: ", stringify!(__darwin_i386_thread_state), "::", stringify!(__cs) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__ds) as usize - ptr as usize }, 48usize, concat!( "Offset of field: ", stringify!(__darwin_i386_thread_state), "::", stringify!(__ds) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__es) as usize - ptr as usize }, 52usize, concat!( "Offset of field: ", stringify!(__darwin_i386_thread_state), "::", stringify!(__es) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fs) as usize - ptr as usize }, 56usize, concat!( "Offset of field: ", stringify!(__darwin_i386_thread_state), "::", stringify!(__fs) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__gs) as usize - ptr as usize }, 60usize, concat!( "Offset of field: ", stringify!(__darwin_i386_thread_state), "::", stringify!(__gs) ) ); } #[repr(C)] #[repr(align(2))] #[derive(Debug, Copy, Clone)] pub struct __darwin_fp_control { pub _bitfield_align_1: [u8; 0], pub _bitfield_1: __BindgenBitfieldUnit<[u8; 2usize]>, } #[test] fn bindgen_test_layout___darwin_fp_control() { assert_eq!( ::std::mem::size_of::<__darwin_fp_control>(), 2usize, concat!("Size of: ", stringify!(__darwin_fp_control)) ); assert_eq!( ::std::mem::align_of::<__darwin_fp_control>(), 2usize, concat!("Alignment of ", stringify!(__darwin_fp_control)) ); } impl __darwin_fp_control { #[inline] pub fn __invalid(&self) -> ::std::os::raw::c_ushort { unsafe { ::std::mem::transmute(self._bitfield_1.get(0usize, 1u8) as u16) } } #[inline] pub fn set___invalid(&mut self, val: ::std::os::raw::c_ushort) { unsafe { let val: u16 = ::std::mem::transmute(val); self._bitfield_1.set(0usize, 1u8, val as u64) } } #[inline] pub fn __denorm(&self) -> ::std::os::raw::c_ushort { unsafe { ::std::mem::transmute(self._bitfield_1.get(1usize, 1u8) as u16) } } #[inline] pub fn set___denorm(&mut self, val: ::std::os::raw::c_ushort) { unsafe { let val: u16 = ::std::mem::transmute(val); self._bitfield_1.set(1usize, 1u8, val as u64) } } #[inline] pub fn __zdiv(&self) -> ::std::os::raw::c_ushort { unsafe { ::std::mem::transmute(self._bitfield_1.get(2usize, 1u8) as u16) } } #[inline] pub fn set___zdiv(&mut self, val: ::std::os::raw::c_ushort) { unsafe { let val: u16 = ::std::mem::transmute(val); self._bitfield_1.set(2usize, 1u8, val as u64) } } #[inline] pub fn __ovrfl(&self) -> ::std::os::raw::c_ushort { unsafe { ::std::mem::transmute(self._bitfield_1.get(3usize, 1u8) as u16) } } #[inline] pub fn set___ovrfl(&mut self, val: ::std::os::raw::c_ushort) { unsafe { let val: u16 = ::std::mem::transmute(val); self._bitfield_1.set(3usize, 1u8, val as u64) } } #[inline] pub fn __undfl(&self) -> ::std::os::raw::c_ushort { unsafe { ::std::mem::transmute(self._bitfield_1.get(4usize, 1u8) as u16) } } #[inline] pub fn set___undfl(&mut self, val: ::std::os::raw::c_ushort) { unsafe { let val: u16 = ::std::mem::transmute(val); self._bitfield_1.set(4usize, 1u8, val as u64) } } #[inline] pub fn __precis(&self) -> ::std::os::raw::c_ushort { unsafe { ::std::mem::transmute(self._bitfield_1.get(5usize, 1u8) as u16) } } #[inline] pub fn set___precis(&mut self, val: ::std::os::raw::c_ushort) { unsafe { let val: u16 = ::std::mem::transmute(val); self._bitfield_1.set(5usize, 1u8, val as u64) } } #[inline] pub fn __pc(&self) -> ::std::os::raw::c_ushort { unsafe { ::std::mem::transmute(self._bitfield_1.get(8usize, 2u8) as u16) } } #[inline] pub fn set___pc(&mut self, val: ::std::os::raw::c_ushort) { unsafe { let val: u16 = ::std::mem::transmute(val); self._bitfield_1.set(8usize, 2u8, val as u64) } } #[inline] pub fn __rc(&self) -> ::std::os::raw::c_ushort { unsafe { ::std::mem::transmute(self._bitfield_1.get(10usize, 2u8) as u16) } } #[inline] pub fn set___rc(&mut self, val: ::std::os::raw::c_ushort) { unsafe { let val: u16 = ::std::mem::transmute(val); self._bitfield_1.set(10usize, 2u8, val as u64) } } #[inline] pub fn new_bitfield_1( __invalid: ::std::os::raw::c_ushort, __denorm: ::std::os::raw::c_ushort, __zdiv: ::std::os::raw::c_ushort, __ovrfl: ::std::os::raw::c_ushort, __undfl: ::std::os::raw::c_ushort, __precis: ::std::os::raw::c_ushort, __pc: ::std::os::raw::c_ushort, __rc: ::std::os::raw::c_ushort, ) -> __BindgenBitfieldUnit<[u8; 2usize]> { let mut __bindgen_bitfield_unit: __BindgenBitfieldUnit<[u8; 2usize]> = Default::default(); __bindgen_bitfield_unit.set(0usize, 1u8, { let __invalid: u16 = unsafe { ::std::mem::transmute(__invalid) }; __invalid as u64 }); __bindgen_bitfield_unit.set(1usize, 1u8, { let __denorm: u16 = unsafe { ::std::mem::transmute(__denorm) }; __denorm as u64 }); __bindgen_bitfield_unit.set(2usize, 1u8, { let __zdiv: u16 = unsafe { ::std::mem::transmute(__zdiv) }; __zdiv as u64 }); __bindgen_bitfield_unit.set(3usize, 1u8, { let __ovrfl: u16 = unsafe { ::std::mem::transmute(__ovrfl) }; __ovrfl as u64 }); __bindgen_bitfield_unit.set(4usize, 1u8, { let __undfl: u16 = unsafe { ::std::mem::transmute(__undfl) }; __undfl as u64 }); __bindgen_bitfield_unit.set(5usize, 1u8, { let __precis: u16 = unsafe { ::std::mem::transmute(__precis) }; __precis as u64 }); __bindgen_bitfield_unit.set(8usize, 2u8, { let __pc: u16 = unsafe { ::std::mem::transmute(__pc) }; __pc as u64 }); __bindgen_bitfield_unit.set(10usize, 2u8, { let __rc: u16 = unsafe { ::std::mem::transmute(__rc) }; __rc as u64 }); __bindgen_bitfield_unit } } pub type __darwin_fp_control_t = __darwin_fp_control; #[repr(C)] #[repr(align(2))] #[derive(Debug, Copy, Clone)] pub struct __darwin_fp_status { pub _bitfield_align_1: [u8; 0], pub _bitfield_1: __BindgenBitfieldUnit<[u8; 2usize]>, } #[test] fn bindgen_test_layout___darwin_fp_status() { assert_eq!( ::std::mem::size_of::<__darwin_fp_status>(), 2usize, concat!("Size of: ", stringify!(__darwin_fp_status)) ); assert_eq!( ::std::mem::align_of::<__darwin_fp_status>(), 2usize, concat!("Alignment of ", stringify!(__darwin_fp_status)) ); } impl __darwin_fp_status { #[inline] pub fn __invalid(&self) -> ::std::os::raw::c_ushort { unsafe { ::std::mem::transmute(self._bitfield_1.get(0usize, 1u8) as u16) } } #[inline] pub fn set___invalid(&mut self, val: ::std::os::raw::c_ushort) { unsafe { let val: u16 = ::std::mem::transmute(val); self._bitfield_1.set(0usize, 1u8, val as u64) } } #[inline] pub fn __denorm(&self) -> ::std::os::raw::c_ushort { unsafe { ::std::mem::transmute(self._bitfield_1.get(1usize, 1u8) as u16) } } #[inline] pub fn set___denorm(&mut self, val: ::std::os::raw::c_ushort) { unsafe { let val: u16 = ::std::mem::transmute(val); self._bitfield_1.set(1usize, 1u8, val as u64) } } #[inline] pub fn __zdiv(&self) -> ::std::os::raw::c_ushort { unsafe { ::std::mem::transmute(self._bitfield_1.get(2usize, 1u8) as u16) } } #[inline] pub fn set___zdiv(&mut self, val: ::std::os::raw::c_ushort) { unsafe { let val: u16 = ::std::mem::transmute(val); self._bitfield_1.set(2usize, 1u8, val as u64) } } #[inline] pub fn __ovrfl(&self) -> ::std::os::raw::c_ushort { unsafe { ::std::mem::transmute(self._bitfield_1.get(3usize, 1u8) as u16) } } #[inline] pub fn set___ovrfl(&mut self, val: ::std::os::raw::c_ushort) { unsafe { let val: u16 = ::std::mem::transmute(val); self._bitfield_1.set(3usize, 1u8, val as u64) } } #[inline] pub fn __undfl(&self) -> ::std::os::raw::c_ushort { unsafe { ::std::mem::transmute(self._bitfield_1.get(4usize, 1u8) as u16) } } #[inline] pub fn set___undfl(&mut self, val: ::std::os::raw::c_ushort) { unsafe { let val: u16 = ::std::mem::transmute(val); self._bitfield_1.set(4usize, 1u8, val as u64) } } #[inline] pub fn __precis(&self) -> ::std::os::raw::c_ushort { unsafe { ::std::mem::transmute(self._bitfield_1.get(5usize, 1u8) as u16) } } #[inline] pub fn set___precis(&mut self, val: ::std::os::raw::c_ushort) { unsafe { let val: u16 = ::std::mem::transmute(val); self._bitfield_1.set(5usize, 1u8, val as u64) } } #[inline] pub fn __stkflt(&self) -> ::std::os::raw::c_ushort { unsafe { ::std::mem::transmute(self._bitfield_1.get(6usize, 1u8) as u16) } } #[inline] pub fn set___stkflt(&mut self, val: ::std::os::raw::c_ushort) { unsafe { let val: u16 = ::std::mem::transmute(val); self._bitfield_1.set(6usize, 1u8, val as u64) } } #[inline] pub fn __errsumm(&self) -> ::std::os::raw::c_ushort { unsafe { ::std::mem::transmute(self._bitfield_1.get(7usize, 1u8) as u16) } } #[inline] pub fn set___errsumm(&mut self, val: ::std::os::raw::c_ushort) { unsafe { let val: u16 = ::std::mem::transmute(val); self._bitfield_1.set(7usize, 1u8, val as u64) } } #[inline] pub fn __c0(&self) -> ::std::os::raw::c_ushort { unsafe { ::std::mem::transmute(self._bitfield_1.get(8usize, 1u8) as u16) } } #[inline] pub fn set___c0(&mut self, val: ::std::os::raw::c_ushort) { unsafe { let val: u16 = ::std::mem::transmute(val); self._bitfield_1.set(8usize, 1u8, val as u64) } } #[inline] pub fn __c1(&self) -> ::std::os::raw::c_ushort { unsafe { ::std::mem::transmute(self._bitfield_1.get(9usize, 1u8) as u16) } } #[inline] pub fn set___c1(&mut self, val: ::std::os::raw::c_ushort) { unsafe { let val: u16 = ::std::mem::transmute(val); self._bitfield_1.set(9usize, 1u8, val as u64) } } #[inline] pub fn __c2(&self) -> ::std::os::raw::c_ushort { unsafe { ::std::mem::transmute(self._bitfield_1.get(10usize, 1u8) as u16) } } #[inline] pub fn set___c2(&mut self, val: ::std::os::raw::c_ushort) { unsafe { let val: u16 = ::std::mem::transmute(val); self._bitfield_1.set(10usize, 1u8, val as u64) } } #[inline] pub fn __tos(&self) -> ::std::os::raw::c_ushort { unsafe { ::std::mem::transmute(self._bitfield_1.get(11usize, 3u8) as u16) } } #[inline] pub fn set___tos(&mut self, val: ::std::os::raw::c_ushort) { unsafe { let val: u16 = ::std::mem::transmute(val); self._bitfield_1.set(11usize, 3u8, val as u64) } } #[inline] pub fn __c3(&self) -> ::std::os::raw::c_ushort { unsafe { ::std::mem::transmute(self._bitfield_1.get(14usize, 1u8) as u16) } } #[inline] pub fn set___c3(&mut self, val: ::std::os::raw::c_ushort) { unsafe { let val: u16 = ::std::mem::transmute(val); self._bitfield_1.set(14usize, 1u8, val as u64) } } #[inline] pub fn __busy(&self) -> ::std::os::raw::c_ushort { unsafe { ::std::mem::transmute(self._bitfield_1.get(15usize, 1u8) as u16) } } #[inline] pub fn set___busy(&mut self, val: ::std::os::raw::c_ushort) { unsafe { let val: u16 = ::std::mem::transmute(val); self._bitfield_1.set(15usize, 1u8, val as u64) } } #[inline] pub fn new_bitfield_1( __invalid: ::std::os::raw::c_ushort, __denorm: ::std::os::raw::c_ushort, __zdiv: ::std::os::raw::c_ushort, __ovrfl: ::std::os::raw::c_ushort, __undfl: ::std::os::raw::c_ushort, __precis: ::std::os::raw::c_ushort, __stkflt: ::std::os::raw::c_ushort, __errsumm: ::std::os::raw::c_ushort, __c0: ::std::os::raw::c_ushort, __c1: ::std::os::raw::c_ushort, __c2: ::std::os::raw::c_ushort, __tos: ::std::os::raw::c_ushort, __c3: ::std::os::raw::c_ushort, __busy: ::std::os::raw::c_ushort, ) -> __BindgenBitfieldUnit<[u8; 2usize]> { let mut __bindgen_bitfield_unit: __BindgenBitfieldUnit<[u8; 2usize]> = Default::default(); __bindgen_bitfield_unit.set(0usize, 1u8, { let __invalid: u16 = unsafe { ::std::mem::transmute(__invalid) }; __invalid as u64 }); __bindgen_bitfield_unit.set(1usize, 1u8, { let __denorm: u16 = unsafe { ::std::mem::transmute(__denorm) }; __denorm as u64 }); __bindgen_bitfield_unit.set(2usize, 1u8, { let __zdiv: u16 = unsafe { ::std::mem::transmute(__zdiv) }; __zdiv as u64 }); __bindgen_bitfield_unit.set(3usize, 1u8, { let __ovrfl: u16 = unsafe { ::std::mem::transmute(__ovrfl) }; __ovrfl as u64 }); __bindgen_bitfield_unit.set(4usize, 1u8, { let __undfl: u16 = unsafe { ::std::mem::transmute(__undfl) }; __undfl as u64 }); __bindgen_bitfield_unit.set(5usize, 1u8, { let __precis: u16 = unsafe { ::std::mem::transmute(__precis) }; __precis as u64 }); __bindgen_bitfield_unit.set(6usize, 1u8, { let __stkflt: u16 = unsafe { ::std::mem::transmute(__stkflt) }; __stkflt as u64 }); __bindgen_bitfield_unit.set(7usize, 1u8, { let __errsumm: u16 = unsafe { ::std::mem::transmute(__errsumm) }; __errsumm as u64 }); __bindgen_bitfield_unit.set(8usize, 1u8, { let __c0: u16 = unsafe { ::std::mem::transmute(__c0) }; __c0 as u64 }); __bindgen_bitfield_unit.set(9usize, 1u8, { let __c1: u16 = unsafe { ::std::mem::transmute(__c1) }; __c1 as u64 }); __bindgen_bitfield_unit.set(10usize, 1u8, { let __c2: u16 = unsafe { ::std::mem::transmute(__c2) }; __c2 as u64 }); __bindgen_bitfield_unit.set(11usize, 3u8, { let __tos: u16 = unsafe { ::std::mem::transmute(__tos) }; __tos as u64 }); __bindgen_bitfield_unit.set(14usize, 1u8, { let __c3: u16 = unsafe { ::std::mem::transmute(__c3) }; __c3 as u64 }); __bindgen_bitfield_unit.set(15usize, 1u8, { let __busy: u16 = unsafe { ::std::mem::transmute(__busy) }; __busy as u64 }); __bindgen_bitfield_unit } } pub type __darwin_fp_status_t = __darwin_fp_status; #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct __darwin_mmst_reg { pub __mmst_reg: [::std::os::raw::c_char; 10usize], pub __mmst_rsrv: [::std::os::raw::c_char; 6usize], } #[test] fn bindgen_test_layout___darwin_mmst_reg() { const UNINIT: ::std::mem::MaybeUninit<__darwin_mmst_reg> = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::<__darwin_mmst_reg>(), 16usize, concat!("Size of: ", stringify!(__darwin_mmst_reg)) ); assert_eq!( ::std::mem::align_of::<__darwin_mmst_reg>(), 1usize, concat!("Alignment of ", stringify!(__darwin_mmst_reg)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__mmst_reg) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(__darwin_mmst_reg), "::", stringify!(__mmst_reg) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__mmst_rsrv) as usize - ptr as usize }, 10usize, concat!( "Offset of field: ", stringify!(__darwin_mmst_reg), "::", stringify!(__mmst_rsrv) ) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct __darwin_xmm_reg { pub __xmm_reg: [::std::os::raw::c_char; 16usize], } #[test] fn bindgen_test_layout___darwin_xmm_reg() { const UNINIT: ::std::mem::MaybeUninit<__darwin_xmm_reg> = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::<__darwin_xmm_reg>(), 16usize, concat!("Size of: ", stringify!(__darwin_xmm_reg)) ); assert_eq!( ::std::mem::align_of::<__darwin_xmm_reg>(), 1usize, concat!("Alignment of ", stringify!(__darwin_xmm_reg)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__xmm_reg) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(__darwin_xmm_reg), "::", stringify!(__xmm_reg) ) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct __darwin_ymm_reg { pub __ymm_reg: [::std::os::raw::c_char; 32usize], } #[test] fn bindgen_test_layout___darwin_ymm_reg() { const UNINIT: ::std::mem::MaybeUninit<__darwin_ymm_reg> = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::<__darwin_ymm_reg>(), 32usize, concat!("Size of: ", stringify!(__darwin_ymm_reg)) ); assert_eq!( ::std::mem::align_of::<__darwin_ymm_reg>(), 1usize, concat!("Alignment of ", stringify!(__darwin_ymm_reg)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__ymm_reg) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(__darwin_ymm_reg), "::", stringify!(__ymm_reg) ) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct __darwin_zmm_reg { pub __zmm_reg: [::std::os::raw::c_char; 64usize], } #[test] fn bindgen_test_layout___darwin_zmm_reg() { const UNINIT: ::std::mem::MaybeUninit<__darwin_zmm_reg> = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::<__darwin_zmm_reg>(), 64usize, concat!("Size of: ", stringify!(__darwin_zmm_reg)) ); assert_eq!( ::std::mem::align_of::<__darwin_zmm_reg>(), 1usize, concat!("Alignment of ", stringify!(__darwin_zmm_reg)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__zmm_reg) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(__darwin_zmm_reg), "::", stringify!(__zmm_reg) ) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct __darwin_opmask_reg { pub __opmask_reg: [::std::os::raw::c_char; 8usize], } #[test] fn bindgen_test_layout___darwin_opmask_reg() { const UNINIT: ::std::mem::MaybeUninit<__darwin_opmask_reg> = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::<__darwin_opmask_reg>(), 8usize, concat!("Size of: ", stringify!(__darwin_opmask_reg)) ); assert_eq!( ::std::mem::align_of::<__darwin_opmask_reg>(), 1usize, concat!("Alignment of ", stringify!(__darwin_opmask_reg)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__opmask_reg) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(__darwin_opmask_reg), "::", stringify!(__opmask_reg) ) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct __darwin_i386_float_state { pub __fpu_reserved: [::std::os::raw::c_int; 2usize], pub __fpu_fcw: __darwin_fp_control, pub __fpu_fsw: __darwin_fp_status, pub __fpu_ftw: __uint8_t, pub __fpu_rsrv1: __uint8_t, pub __fpu_fop: __uint16_t, pub __fpu_ip: __uint32_t, pub __fpu_cs: __uint16_t, pub __fpu_rsrv2: __uint16_t, pub __fpu_dp: __uint32_t, pub __fpu_ds: __uint16_t, pub __fpu_rsrv3: __uint16_t, pub __fpu_mxcsr: __uint32_t, pub __fpu_mxcsrmask: __uint32_t, pub __fpu_stmm0: __darwin_mmst_reg, pub __fpu_stmm1: __darwin_mmst_reg, pub __fpu_stmm2: __darwin_mmst_reg, pub __fpu_stmm3: __darwin_mmst_reg, pub __fpu_stmm4: __darwin_mmst_reg, pub __fpu_stmm5: __darwin_mmst_reg, pub __fpu_stmm6: __darwin_mmst_reg, pub __fpu_stmm7: __darwin_mmst_reg, pub __fpu_xmm0: __darwin_xmm_reg, pub __fpu_xmm1: __darwin_xmm_reg, pub __fpu_xmm2: __darwin_xmm_reg, pub __fpu_xmm3: __darwin_xmm_reg, pub __fpu_xmm4: __darwin_xmm_reg, pub __fpu_xmm5: __darwin_xmm_reg, pub __fpu_xmm6: __darwin_xmm_reg, pub __fpu_xmm7: __darwin_xmm_reg, pub __fpu_rsrv4: [::std::os::raw::c_char; 224usize], pub __fpu_reserved1: ::std::os::raw::c_int, } #[test] fn bindgen_test_layout___darwin_i386_float_state() { const UNINIT: ::std::mem::MaybeUninit<__darwin_i386_float_state> = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::<__darwin_i386_float_state>(), 524usize, concat!("Size of: ", stringify!(__darwin_i386_float_state)) ); assert_eq!( ::std::mem::align_of::<__darwin_i386_float_state>(), 4usize, concat!("Alignment of ", stringify!(__darwin_i386_float_state)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_reserved) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(__darwin_i386_float_state), "::", stringify!(__fpu_reserved) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_fcw) as usize - ptr as usize }, 8usize, concat!( "Offset of field: ", stringify!(__darwin_i386_float_state), "::", stringify!(__fpu_fcw) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_fsw) as usize - ptr as usize }, 10usize, concat!( "Offset of field: ", stringify!(__darwin_i386_float_state), "::", stringify!(__fpu_fsw) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_ftw) as usize - ptr as usize }, 12usize, concat!( "Offset of field: ", stringify!(__darwin_i386_float_state), "::", stringify!(__fpu_ftw) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_rsrv1) as usize - ptr as usize }, 13usize, concat!( "Offset of field: ", stringify!(__darwin_i386_float_state), "::", stringify!(__fpu_rsrv1) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_fop) as usize - ptr as usize }, 14usize, concat!( "Offset of field: ", stringify!(__darwin_i386_float_state), "::", stringify!(__fpu_fop) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_ip) as usize - ptr as usize }, 16usize, concat!( "Offset of field: ", stringify!(__darwin_i386_float_state), "::", stringify!(__fpu_ip) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_cs) as usize - ptr as usize }, 20usize, concat!( "Offset of field: ", stringify!(__darwin_i386_float_state), "::", stringify!(__fpu_cs) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_rsrv2) as usize - ptr as usize }, 22usize, concat!( "Offset of field: ", stringify!(__darwin_i386_float_state), "::", stringify!(__fpu_rsrv2) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_dp) as usize - ptr as usize }, 24usize, concat!( "Offset of field: ", stringify!(__darwin_i386_float_state), "::", stringify!(__fpu_dp) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_ds) as usize - ptr as usize }, 28usize, concat!( "Offset of field: ", stringify!(__darwin_i386_float_state), "::", stringify!(__fpu_ds) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_rsrv3) as usize - ptr as usize }, 30usize, concat!( "Offset of field: ", stringify!(__darwin_i386_float_state), "::", stringify!(__fpu_rsrv3) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_mxcsr) as usize - ptr as usize }, 32usize, concat!( "Offset of field: ", stringify!(__darwin_i386_float_state), "::", stringify!(__fpu_mxcsr) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_mxcsrmask) as usize - ptr as usize }, 36usize, concat!( "Offset of field: ", stringify!(__darwin_i386_float_state), "::", stringify!(__fpu_mxcsrmask) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_stmm0) as usize - ptr as usize }, 40usize, concat!( "Offset of field: ", stringify!(__darwin_i386_float_state), "::", stringify!(__fpu_stmm0) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_stmm1) as usize - ptr as usize }, 56usize, concat!( "Offset of field: ", stringify!(__darwin_i386_float_state), "::", stringify!(__fpu_stmm1) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_stmm2) as usize - ptr as usize }, 72usize, concat!( "Offset of field: ", stringify!(__darwin_i386_float_state), "::", stringify!(__fpu_stmm2) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_stmm3) as usize - ptr as usize }, 88usize, concat!( "Offset of field: ", stringify!(__darwin_i386_float_state), "::", stringify!(__fpu_stmm3) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_stmm4) as usize - ptr as usize }, 104usize, concat!( "Offset of field: ", stringify!(__darwin_i386_float_state), "::", stringify!(__fpu_stmm4) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_stmm5) as usize - ptr as usize }, 120usize, concat!( "Offset of field: ", stringify!(__darwin_i386_float_state), "::", stringify!(__fpu_stmm5) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_stmm6) as usize - ptr as usize }, 136usize, concat!( "Offset of field: ", stringify!(__darwin_i386_float_state), "::", stringify!(__fpu_stmm6) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_stmm7) as usize - ptr as usize }, 152usize, concat!( "Offset of field: ", stringify!(__darwin_i386_float_state), "::", stringify!(__fpu_stmm7) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_xmm0) as usize - ptr as usize }, 168usize, concat!( "Offset of field: ", stringify!(__darwin_i386_float_state), "::", stringify!(__fpu_xmm0) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_xmm1) as usize - ptr as usize }, 184usize, concat!( "Offset of field: ", stringify!(__darwin_i386_float_state), "::", stringify!(__fpu_xmm1) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_xmm2) as usize - ptr as usize }, 200usize, concat!( "Offset of field: ", stringify!(__darwin_i386_float_state), "::", stringify!(__fpu_xmm2) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_xmm3) as usize - ptr as usize }, 216usize, concat!( "Offset of field: ", stringify!(__darwin_i386_float_state), "::", stringify!(__fpu_xmm3) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_xmm4) as usize - ptr as usize }, 232usize, concat!( "Offset of field: ", stringify!(__darwin_i386_float_state), "::", stringify!(__fpu_xmm4) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_xmm5) as usize - ptr as usize }, 248usize, concat!( "Offset of field: ", stringify!(__darwin_i386_float_state), "::", stringify!(__fpu_xmm5) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_xmm6) as usize - ptr as usize }, 264usize, concat!( "Offset of field: ", stringify!(__darwin_i386_float_state), "::", stringify!(__fpu_xmm6) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_xmm7) as usize - ptr as usize }, 280usize, concat!( "Offset of field: ", stringify!(__darwin_i386_float_state), "::", stringify!(__fpu_xmm7) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_rsrv4) as usize - ptr as usize }, 296usize, concat!( "Offset of field: ", stringify!(__darwin_i386_float_state), "::", stringify!(__fpu_rsrv4) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_reserved1) as usize - ptr as usize }, 520usize, concat!( "Offset of field: ", stringify!(__darwin_i386_float_state), "::", stringify!(__fpu_reserved1) ) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct __darwin_i386_avx_state { pub __fpu_reserved: [::std::os::raw::c_int; 2usize], pub __fpu_fcw: __darwin_fp_control, pub __fpu_fsw: __darwin_fp_status, pub __fpu_ftw: __uint8_t, pub __fpu_rsrv1: __uint8_t, pub __fpu_fop: __uint16_t, pub __fpu_ip: __uint32_t, pub __fpu_cs: __uint16_t, pub __fpu_rsrv2: __uint16_t, pub __fpu_dp: __uint32_t, pub __fpu_ds: __uint16_t, pub __fpu_rsrv3: __uint16_t, pub __fpu_mxcsr: __uint32_t, pub __fpu_mxcsrmask: __uint32_t, pub __fpu_stmm0: __darwin_mmst_reg, pub __fpu_stmm1: __darwin_mmst_reg, pub __fpu_stmm2: __darwin_mmst_reg, pub __fpu_stmm3: __darwin_mmst_reg, pub __fpu_stmm4: __darwin_mmst_reg, pub __fpu_stmm5: __darwin_mmst_reg, pub __fpu_stmm6: __darwin_mmst_reg, pub __fpu_stmm7: __darwin_mmst_reg, pub __fpu_xmm0: __darwin_xmm_reg, pub __fpu_xmm1: __darwin_xmm_reg, pub __fpu_xmm2: __darwin_xmm_reg, pub __fpu_xmm3: __darwin_xmm_reg, pub __fpu_xmm4: __darwin_xmm_reg, pub __fpu_xmm5: __darwin_xmm_reg, pub __fpu_xmm6: __darwin_xmm_reg, pub __fpu_xmm7: __darwin_xmm_reg, pub __fpu_rsrv4: [::std::os::raw::c_char; 224usize], pub __fpu_reserved1: ::std::os::raw::c_int, pub __avx_reserved1: [::std::os::raw::c_char; 64usize], pub __fpu_ymmh0: __darwin_xmm_reg, pub __fpu_ymmh1: __darwin_xmm_reg, pub __fpu_ymmh2: __darwin_xmm_reg, pub __fpu_ymmh3: __darwin_xmm_reg, pub __fpu_ymmh4: __darwin_xmm_reg, pub __fpu_ymmh5: __darwin_xmm_reg, pub __fpu_ymmh6: __darwin_xmm_reg, pub __fpu_ymmh7: __darwin_xmm_reg, } #[test] fn bindgen_test_layout___darwin_i386_avx_state() { const UNINIT: ::std::mem::MaybeUninit<__darwin_i386_avx_state> = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::<__darwin_i386_avx_state>(), 716usize, concat!("Size of: ", stringify!(__darwin_i386_avx_state)) ); assert_eq!( ::std::mem::align_of::<__darwin_i386_avx_state>(), 4usize, concat!("Alignment of ", stringify!(__darwin_i386_avx_state)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_reserved) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(__darwin_i386_avx_state), "::", stringify!(__fpu_reserved) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_fcw) as usize - ptr as usize }, 8usize, concat!( "Offset of field: ", stringify!(__darwin_i386_avx_state), "::", stringify!(__fpu_fcw) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_fsw) as usize - ptr as usize }, 10usize, concat!( "Offset of field: ", stringify!(__darwin_i386_avx_state), "::", stringify!(__fpu_fsw) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_ftw) as usize - ptr as usize }, 12usize, concat!( "Offset of field: ", stringify!(__darwin_i386_avx_state), "::", stringify!(__fpu_ftw) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_rsrv1) as usize - ptr as usize }, 13usize, concat!( "Offset of field: ", stringify!(__darwin_i386_avx_state), "::", stringify!(__fpu_rsrv1) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_fop) as usize - ptr as usize }, 14usize, concat!( "Offset of field: ", stringify!(__darwin_i386_avx_state), "::", stringify!(__fpu_fop) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_ip) as usize - ptr as usize }, 16usize, concat!( "Offset of field: ", stringify!(__darwin_i386_avx_state), "::", stringify!(__fpu_ip) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_cs) as usize - ptr as usize }, 20usize, concat!( "Offset of field: ", stringify!(__darwin_i386_avx_state), "::", stringify!(__fpu_cs) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_rsrv2) as usize - ptr as usize }, 22usize, concat!( "Offset of field: ", stringify!(__darwin_i386_avx_state), "::", stringify!(__fpu_rsrv2) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_dp) as usize - ptr as usize }, 24usize, concat!( "Offset of field: ", stringify!(__darwin_i386_avx_state), "::", stringify!(__fpu_dp) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_ds) as usize - ptr as usize }, 28usize, concat!( "Offset of field: ", stringify!(__darwin_i386_avx_state), "::", stringify!(__fpu_ds) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_rsrv3) as usize - ptr as usize }, 30usize, concat!( "Offset of field: ", stringify!(__darwin_i386_avx_state), "::", stringify!(__fpu_rsrv3) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_mxcsr) as usize - ptr as usize }, 32usize, concat!( "Offset of field: ", stringify!(__darwin_i386_avx_state), "::", stringify!(__fpu_mxcsr) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_mxcsrmask) as usize - ptr as usize }, 36usize, concat!( "Offset of field: ", stringify!(__darwin_i386_avx_state), "::", stringify!(__fpu_mxcsrmask) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_stmm0) as usize - ptr as usize }, 40usize, concat!( "Offset of field: ", stringify!(__darwin_i386_avx_state), "::", stringify!(__fpu_stmm0) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_stmm1) as usize - ptr as usize }, 56usize, concat!( "Offset of field: ", stringify!(__darwin_i386_avx_state), "::", stringify!(__fpu_stmm1) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_stmm2) as usize - ptr as usize }, 72usize, concat!( "Offset of field: ", stringify!(__darwin_i386_avx_state), "::", stringify!(__fpu_stmm2) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_stmm3) as usize - ptr as usize }, 88usize, concat!( "Offset of field: ", stringify!(__darwin_i386_avx_state), "::", stringify!(__fpu_stmm3) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_stmm4) as usize - ptr as usize }, 104usize, concat!( "Offset of field: ", stringify!(__darwin_i386_avx_state), "::", stringify!(__fpu_stmm4) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_stmm5) as usize - ptr as usize }, 120usize, concat!( "Offset of field: ", stringify!(__darwin_i386_avx_state), "::", stringify!(__fpu_stmm5) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_stmm6) as usize - ptr as usize }, 136usize, concat!( "Offset of field: ", stringify!(__darwin_i386_avx_state), "::", stringify!(__fpu_stmm6) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_stmm7) as usize - ptr as usize }, 152usize, concat!( "Offset of field: ", stringify!(__darwin_i386_avx_state), "::", stringify!(__fpu_stmm7) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_xmm0) as usize - ptr as usize }, 168usize, concat!( "Offset of field: ", stringify!(__darwin_i386_avx_state), "::", stringify!(__fpu_xmm0) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_xmm1) as usize - ptr as usize }, 184usize, concat!( "Offset of field: ", stringify!(__darwin_i386_avx_state), "::", stringify!(__fpu_xmm1) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_xmm2) as usize - ptr as usize }, 200usize, concat!( "Offset of field: ", stringify!(__darwin_i386_avx_state), "::", stringify!(__fpu_xmm2) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_xmm3) as usize - ptr as usize }, 216usize, concat!( "Offset of field: ", stringify!(__darwin_i386_avx_state), "::", stringify!(__fpu_xmm3) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_xmm4) as usize - ptr as usize }, 232usize, concat!( "Offset of field: ", stringify!(__darwin_i386_avx_state), "::", stringify!(__fpu_xmm4) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_xmm5) as usize - ptr as usize }, 248usize, concat!( "Offset of field: ", stringify!(__darwin_i386_avx_state), "::", stringify!(__fpu_xmm5) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_xmm6) as usize - ptr as usize }, 264usize, concat!( "Offset of field: ", stringify!(__darwin_i386_avx_state), "::", stringify!(__fpu_xmm6) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_xmm7) as usize - ptr as usize }, 280usize, concat!( "Offset of field: ", stringify!(__darwin_i386_avx_state), "::", stringify!(__fpu_xmm7) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_rsrv4) as usize - ptr as usize }, 296usize, concat!( "Offset of field: ", stringify!(__darwin_i386_avx_state), "::", stringify!(__fpu_rsrv4) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_reserved1) as usize - ptr as usize }, 520usize, concat!( "Offset of field: ", stringify!(__darwin_i386_avx_state), "::", stringify!(__fpu_reserved1) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__avx_reserved1) as usize - ptr as usize }, 524usize, concat!( "Offset of field: ", stringify!(__darwin_i386_avx_state), "::", stringify!(__avx_reserved1) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_ymmh0) as usize - ptr as usize }, 588usize, concat!( "Offset of field: ", stringify!(__darwin_i386_avx_state), "::", stringify!(__fpu_ymmh0) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_ymmh1) as usize - ptr as usize }, 604usize, concat!( "Offset of field: ", stringify!(__darwin_i386_avx_state), "::", stringify!(__fpu_ymmh1) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_ymmh2) as usize - ptr as usize }, 620usize, concat!( "Offset of field: ", stringify!(__darwin_i386_avx_state), "::", stringify!(__fpu_ymmh2) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_ymmh3) as usize - ptr as usize }, 636usize, concat!( "Offset of field: ", stringify!(__darwin_i386_avx_state), "::", stringify!(__fpu_ymmh3) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_ymmh4) as usize - ptr as usize }, 652usize, concat!( "Offset of field: ", stringify!(__darwin_i386_avx_state), "::", stringify!(__fpu_ymmh4) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_ymmh5) as usize - ptr as usize }, 668usize, concat!( "Offset of field: ", stringify!(__darwin_i386_avx_state), "::", stringify!(__fpu_ymmh5) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_ymmh6) as usize - ptr as usize }, 684usize, concat!( "Offset of field: ", stringify!(__darwin_i386_avx_state), "::", stringify!(__fpu_ymmh6) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_ymmh7) as usize - ptr as usize }, 700usize, concat!( "Offset of field: ", stringify!(__darwin_i386_avx_state), "::", stringify!(__fpu_ymmh7) ) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct __darwin_i386_avx512_state { pub __fpu_reserved: [::std::os::raw::c_int; 2usize], pub __fpu_fcw: __darwin_fp_control, pub __fpu_fsw: __darwin_fp_status, pub __fpu_ftw: __uint8_t, pub __fpu_rsrv1: __uint8_t, pub __fpu_fop: __uint16_t, pub __fpu_ip: __uint32_t, pub __fpu_cs: __uint16_t, pub __fpu_rsrv2: __uint16_t, pub __fpu_dp: __uint32_t, pub __fpu_ds: __uint16_t, pub __fpu_rsrv3: __uint16_t, pub __fpu_mxcsr: __uint32_t, pub __fpu_mxcsrmask: __uint32_t, pub __fpu_stmm0: __darwin_mmst_reg, pub __fpu_stmm1: __darwin_mmst_reg, pub __fpu_stmm2: __darwin_mmst_reg, pub __fpu_stmm3: __darwin_mmst_reg, pub __fpu_stmm4: __darwin_mmst_reg, pub __fpu_stmm5: __darwin_mmst_reg, pub __fpu_stmm6: __darwin_mmst_reg, pub __fpu_stmm7: __darwin_mmst_reg, pub __fpu_xmm0: __darwin_xmm_reg, pub __fpu_xmm1: __darwin_xmm_reg, pub __fpu_xmm2: __darwin_xmm_reg, pub __fpu_xmm3: __darwin_xmm_reg, pub __fpu_xmm4: __darwin_xmm_reg, pub __fpu_xmm5: __darwin_xmm_reg, pub __fpu_xmm6: __darwin_xmm_reg, pub __fpu_xmm7: __darwin_xmm_reg, pub __fpu_rsrv4: [::std::os::raw::c_char; 224usize], pub __fpu_reserved1: ::std::os::raw::c_int, pub __avx_reserved1: [::std::os::raw::c_char; 64usize], pub __fpu_ymmh0: __darwin_xmm_reg, pub __fpu_ymmh1: __darwin_xmm_reg, pub __fpu_ymmh2: __darwin_xmm_reg, pub __fpu_ymmh3: __darwin_xmm_reg, pub __fpu_ymmh4: __darwin_xmm_reg, pub __fpu_ymmh5: __darwin_xmm_reg, pub __fpu_ymmh6: __darwin_xmm_reg, pub __fpu_ymmh7: __darwin_xmm_reg, pub __fpu_k0: __darwin_opmask_reg, pub __fpu_k1: __darwin_opmask_reg, pub __fpu_k2: __darwin_opmask_reg, pub __fpu_k3: __darwin_opmask_reg, pub __fpu_k4: __darwin_opmask_reg, pub __fpu_k5: __darwin_opmask_reg, pub __fpu_k6: __darwin_opmask_reg, pub __fpu_k7: __darwin_opmask_reg, pub __fpu_zmmh0: __darwin_ymm_reg, pub __fpu_zmmh1: __darwin_ymm_reg, pub __fpu_zmmh2: __darwin_ymm_reg, pub __fpu_zmmh3: __darwin_ymm_reg, pub __fpu_zmmh4: __darwin_ymm_reg, pub __fpu_zmmh5: __darwin_ymm_reg, pub __fpu_zmmh6: __darwin_ymm_reg, pub __fpu_zmmh7: __darwin_ymm_reg, } #[test] fn bindgen_test_layout___darwin_i386_avx512_state() { const UNINIT: ::std::mem::MaybeUninit<__darwin_i386_avx512_state> = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::<__darwin_i386_avx512_state>(), 1036usize, concat!("Size of: ", stringify!(__darwin_i386_avx512_state)) ); assert_eq!( ::std::mem::align_of::<__darwin_i386_avx512_state>(), 4usize, concat!("Alignment of ", stringify!(__darwin_i386_avx512_state)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_reserved) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(__darwin_i386_avx512_state), "::", stringify!(__fpu_reserved) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_fcw) as usize - ptr as usize }, 8usize, concat!( "Offset of field: ", stringify!(__darwin_i386_avx512_state), "::", stringify!(__fpu_fcw) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_fsw) as usize - ptr as usize }, 10usize, concat!( "Offset of field: ", stringify!(__darwin_i386_avx512_state), "::", stringify!(__fpu_fsw) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_ftw) as usize - ptr as usize }, 12usize, concat!( "Offset of field: ", stringify!(__darwin_i386_avx512_state), "::", stringify!(__fpu_ftw) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_rsrv1) as usize - ptr as usize }, 13usize, concat!( "Offset of field: ", stringify!(__darwin_i386_avx512_state), "::", stringify!(__fpu_rsrv1) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_fop) as usize - ptr as usize }, 14usize, concat!( "Offset of field: ", stringify!(__darwin_i386_avx512_state), "::", stringify!(__fpu_fop) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_ip) as usize - ptr as usize }, 16usize, concat!( "Offset of field: ", stringify!(__darwin_i386_avx512_state), "::", stringify!(__fpu_ip) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_cs) as usize - ptr as usize }, 20usize, concat!( "Offset of field: ", stringify!(__darwin_i386_avx512_state), "::", stringify!(__fpu_cs) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_rsrv2) as usize - ptr as usize }, 22usize, concat!( "Offset of field: ", stringify!(__darwin_i386_avx512_state), "::", stringify!(__fpu_rsrv2) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_dp) as usize - ptr as usize }, 24usize, concat!( "Offset of field: ", stringify!(__darwin_i386_avx512_state), "::", stringify!(__fpu_dp) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_ds) as usize - ptr as usize }, 28usize, concat!( "Offset of field: ", stringify!(__darwin_i386_avx512_state), "::", stringify!(__fpu_ds) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_rsrv3) as usize - ptr as usize }, 30usize, concat!( "Offset of field: ", stringify!(__darwin_i386_avx512_state), "::", stringify!(__fpu_rsrv3) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_mxcsr) as usize - ptr as usize }, 32usize, concat!( "Offset of field: ", stringify!(__darwin_i386_avx512_state), "::", stringify!(__fpu_mxcsr) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_mxcsrmask) as usize - ptr as usize }, 36usize, concat!( "Offset of field: ", stringify!(__darwin_i386_avx512_state), "::", stringify!(__fpu_mxcsrmask) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_stmm0) as usize - ptr as usize }, 40usize, concat!( "Offset of field: ", stringify!(__darwin_i386_avx512_state), "::", stringify!(__fpu_stmm0) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_stmm1) as usize - ptr as usize }, 56usize, concat!( "Offset of field: ", stringify!(__darwin_i386_avx512_state), "::", stringify!(__fpu_stmm1) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_stmm2) as usize - ptr as usize }, 72usize, concat!( "Offset of field: ", stringify!(__darwin_i386_avx512_state), "::", stringify!(__fpu_stmm2) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_stmm3) as usize - ptr as usize }, 88usize, concat!( "Offset of field: ", stringify!(__darwin_i386_avx512_state), "::", stringify!(__fpu_stmm3) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_stmm4) as usize - ptr as usize }, 104usize, concat!( "Offset of field: ", stringify!(__darwin_i386_avx512_state), "::", stringify!(__fpu_stmm4) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_stmm5) as usize - ptr as usize }, 120usize, concat!( "Offset of field: ", stringify!(__darwin_i386_avx512_state), "::", stringify!(__fpu_stmm5) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_stmm6) as usize - ptr as usize }, 136usize, concat!( "Offset of field: ", stringify!(__darwin_i386_avx512_state), "::", stringify!(__fpu_stmm6) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_stmm7) as usize - ptr as usize }, 152usize, concat!( "Offset of field: ", stringify!(__darwin_i386_avx512_state), "::", stringify!(__fpu_stmm7) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_xmm0) as usize - ptr as usize }, 168usize, concat!( "Offset of field: ", stringify!(__darwin_i386_avx512_state), "::", stringify!(__fpu_xmm0) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_xmm1) as usize - ptr as usize }, 184usize, concat!( "Offset of field: ", stringify!(__darwin_i386_avx512_state), "::", stringify!(__fpu_xmm1) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_xmm2) as usize - ptr as usize }, 200usize, concat!( "Offset of field: ", stringify!(__darwin_i386_avx512_state), "::", stringify!(__fpu_xmm2) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_xmm3) as usize - ptr as usize }, 216usize, concat!( "Offset of field: ", stringify!(__darwin_i386_avx512_state), "::", stringify!(__fpu_xmm3) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_xmm4) as usize - ptr as usize }, 232usize, concat!( "Offset of field: ", stringify!(__darwin_i386_avx512_state), "::", stringify!(__fpu_xmm4) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_xmm5) as usize - ptr as usize }, 248usize, concat!( "Offset of field: ", stringify!(__darwin_i386_avx512_state), "::", stringify!(__fpu_xmm5) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_xmm6) as usize - ptr as usize }, 264usize, concat!( "Offset of field: ", stringify!(__darwin_i386_avx512_state), "::", stringify!(__fpu_xmm6) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_xmm7) as usize - ptr as usize }, 280usize, concat!( "Offset of field: ", stringify!(__darwin_i386_avx512_state), "::", stringify!(__fpu_xmm7) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_rsrv4) as usize - ptr as usize }, 296usize, concat!( "Offset of field: ", stringify!(__darwin_i386_avx512_state), "::", stringify!(__fpu_rsrv4) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_reserved1) as usize - ptr as usize }, 520usize, concat!( "Offset of field: ", stringify!(__darwin_i386_avx512_state), "::", stringify!(__fpu_reserved1) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__avx_reserved1) as usize - ptr as usize }, 524usize, concat!( "Offset of field: ", stringify!(__darwin_i386_avx512_state), "::", stringify!(__avx_reserved1) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_ymmh0) as usize - ptr as usize }, 588usize, concat!( "Offset of field: ", stringify!(__darwin_i386_avx512_state), "::", stringify!(__fpu_ymmh0) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_ymmh1) as usize - ptr as usize }, 604usize, concat!( "Offset of field: ", stringify!(__darwin_i386_avx512_state), "::", stringify!(__fpu_ymmh1) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_ymmh2) as usize - ptr as usize }, 620usize, concat!( "Offset of field: ", stringify!(__darwin_i386_avx512_state), "::", stringify!(__fpu_ymmh2) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_ymmh3) as usize - ptr as usize }, 636usize, concat!( "Offset of field: ", stringify!(__darwin_i386_avx512_state), "::", stringify!(__fpu_ymmh3) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_ymmh4) as usize - ptr as usize }, 652usize, concat!( "Offset of field: ", stringify!(__darwin_i386_avx512_state), "::", stringify!(__fpu_ymmh4) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_ymmh5) as usize - ptr as usize }, 668usize, concat!( "Offset of field: ", stringify!(__darwin_i386_avx512_state), "::", stringify!(__fpu_ymmh5) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_ymmh6) as usize - ptr as usize }, 684usize, concat!( "Offset of field: ", stringify!(__darwin_i386_avx512_state), "::", stringify!(__fpu_ymmh6) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_ymmh7) as usize - ptr as usize }, 700usize, concat!( "Offset of field: ", stringify!(__darwin_i386_avx512_state), "::", stringify!(__fpu_ymmh7) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_k0) as usize - ptr as usize }, 716usize, concat!( "Offset of field: ", stringify!(__darwin_i386_avx512_state), "::", stringify!(__fpu_k0) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_k1) as usize - ptr as usize }, 724usize, concat!( "Offset of field: ", stringify!(__darwin_i386_avx512_state), "::", stringify!(__fpu_k1) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_k2) as usize - ptr as usize }, 732usize, concat!( "Offset of field: ", stringify!(__darwin_i386_avx512_state), "::", stringify!(__fpu_k2) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_k3) as usize - ptr as usize }, 740usize, concat!( "Offset of field: ", stringify!(__darwin_i386_avx512_state), "::", stringify!(__fpu_k3) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_k4) as usize - ptr as usize }, 748usize, concat!( "Offset of field: ", stringify!(__darwin_i386_avx512_state), "::", stringify!(__fpu_k4) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_k5) as usize - ptr as usize }, 756usize, concat!( "Offset of field: ", stringify!(__darwin_i386_avx512_state), "::", stringify!(__fpu_k5) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_k6) as usize - ptr as usize }, 764usize, concat!( "Offset of field: ", stringify!(__darwin_i386_avx512_state), "::", stringify!(__fpu_k6) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_k7) as usize - ptr as usize }, 772usize, concat!( "Offset of field: ", stringify!(__darwin_i386_avx512_state), "::", stringify!(__fpu_k7) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_zmmh0) as usize - ptr as usize }, 780usize, concat!( "Offset of field: ", stringify!(__darwin_i386_avx512_state), "::", stringify!(__fpu_zmmh0) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_zmmh1) as usize - ptr as usize }, 812usize, concat!( "Offset of field: ", stringify!(__darwin_i386_avx512_state), "::", stringify!(__fpu_zmmh1) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_zmmh2) as usize - ptr as usize }, 844usize, concat!( "Offset of field: ", stringify!(__darwin_i386_avx512_state), "::", stringify!(__fpu_zmmh2) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_zmmh3) as usize - ptr as usize }, 876usize, concat!( "Offset of field: ", stringify!(__darwin_i386_avx512_state), "::", stringify!(__fpu_zmmh3) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_zmmh4) as usize - ptr as usize }, 908usize, concat!( "Offset of field: ", stringify!(__darwin_i386_avx512_state), "::", stringify!(__fpu_zmmh4) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_zmmh5) as usize - ptr as usize }, 940usize, concat!( "Offset of field: ", stringify!(__darwin_i386_avx512_state), "::", stringify!(__fpu_zmmh5) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_zmmh6) as usize - ptr as usize }, 972usize, concat!( "Offset of field: ", stringify!(__darwin_i386_avx512_state), "::", stringify!(__fpu_zmmh6) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_zmmh7) as usize - ptr as usize }, 1004usize, concat!( "Offset of field: ", stringify!(__darwin_i386_avx512_state), "::", stringify!(__fpu_zmmh7) ) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct __darwin_i386_exception_state { pub __trapno: __uint16_t, pub __cpu: __uint16_t, pub __err: __uint32_t, pub __faultvaddr: __uint32_t, } #[test] fn bindgen_test_layout___darwin_i386_exception_state() { const UNINIT: ::std::mem::MaybeUninit<__darwin_i386_exception_state> = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::<__darwin_i386_exception_state>(), 12usize, concat!("Size of: ", stringify!(__darwin_i386_exception_state)) ); assert_eq!( ::std::mem::align_of::<__darwin_i386_exception_state>(), 4usize, concat!("Alignment of ", stringify!(__darwin_i386_exception_state)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__trapno) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(__darwin_i386_exception_state), "::", stringify!(__trapno) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__cpu) as usize - ptr as usize }, 2usize, concat!( "Offset of field: ", stringify!(__darwin_i386_exception_state), "::", stringify!(__cpu) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__err) as usize - ptr as usize }, 4usize, concat!( "Offset of field: ", stringify!(__darwin_i386_exception_state), "::", stringify!(__err) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__faultvaddr) as usize - ptr as usize }, 8usize, concat!( "Offset of field: ", stringify!(__darwin_i386_exception_state), "::", stringify!(__faultvaddr) ) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct __darwin_x86_debug_state32 { pub __dr0: ::std::os::raw::c_uint, pub __dr1: ::std::os::raw::c_uint, pub __dr2: ::std::os::raw::c_uint, pub __dr3: ::std::os::raw::c_uint, pub __dr4: ::std::os::raw::c_uint, pub __dr5: ::std::os::raw::c_uint, pub __dr6: ::std::os::raw::c_uint, pub __dr7: ::std::os::raw::c_uint, } #[test] fn bindgen_test_layout___darwin_x86_debug_state32() { const UNINIT: ::std::mem::MaybeUninit<__darwin_x86_debug_state32> = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::<__darwin_x86_debug_state32>(), 32usize, concat!("Size of: ", stringify!(__darwin_x86_debug_state32)) ); assert_eq!( ::std::mem::align_of::<__darwin_x86_debug_state32>(), 4usize, concat!("Alignment of ", stringify!(__darwin_x86_debug_state32)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__dr0) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(__darwin_x86_debug_state32), "::", stringify!(__dr0) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__dr1) as usize - ptr as usize }, 4usize, concat!( "Offset of field: ", stringify!(__darwin_x86_debug_state32), "::", stringify!(__dr1) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__dr2) as usize - ptr as usize }, 8usize, concat!( "Offset of field: ", stringify!(__darwin_x86_debug_state32), "::", stringify!(__dr2) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__dr3) as usize - ptr as usize }, 12usize, concat!( "Offset of field: ", stringify!(__darwin_x86_debug_state32), "::", stringify!(__dr3) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__dr4) as usize - ptr as usize }, 16usize, concat!( "Offset of field: ", stringify!(__darwin_x86_debug_state32), "::", stringify!(__dr4) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__dr5) as usize - ptr as usize }, 20usize, concat!( "Offset of field: ", stringify!(__darwin_x86_debug_state32), "::", stringify!(__dr5) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__dr6) as usize - ptr as usize }, 24usize, concat!( "Offset of field: ", stringify!(__darwin_x86_debug_state32), "::", stringify!(__dr6) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__dr7) as usize - ptr as usize }, 28usize, concat!( "Offset of field: ", stringify!(__darwin_x86_debug_state32), "::", stringify!(__dr7) ) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct __x86_instruction_state { pub __insn_stream_valid_bytes: ::std::os::raw::c_int, pub __insn_offset: ::std::os::raw::c_int, pub __out_of_synch: ::std::os::raw::c_int, pub __insn_bytes: [__uint8_t; 2380usize], pub __insn_cacheline: [__uint8_t; 64usize], } #[test] fn bindgen_test_layout___x86_instruction_state() { const UNINIT: ::std::mem::MaybeUninit<__x86_instruction_state> = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::<__x86_instruction_state>(), 2456usize, concat!("Size of: ", stringify!(__x86_instruction_state)) ); assert_eq!( ::std::mem::align_of::<__x86_instruction_state>(), 4usize, concat!("Alignment of ", stringify!(__x86_instruction_state)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__insn_stream_valid_bytes) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(__x86_instruction_state), "::", stringify!(__insn_stream_valid_bytes) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__insn_offset) as usize - ptr as usize }, 4usize, concat!( "Offset of field: ", stringify!(__x86_instruction_state), "::", stringify!(__insn_offset) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__out_of_synch) as usize - ptr as usize }, 8usize, concat!( "Offset of field: ", stringify!(__x86_instruction_state), "::", stringify!(__out_of_synch) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__insn_bytes) as usize - ptr as usize }, 12usize, concat!( "Offset of field: ", stringify!(__x86_instruction_state), "::", stringify!(__insn_bytes) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__insn_cacheline) as usize - ptr as usize }, 2392usize, concat!( "Offset of field: ", stringify!(__x86_instruction_state), "::", stringify!(__insn_cacheline) ) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct __last_branch_record { pub __from_ip: __uint64_t, pub __to_ip: __uint64_t, pub _bitfield_align_1: [u16; 0], pub _bitfield_1: __BindgenBitfieldUnit<[u8; 4usize]>, pub __bindgen_padding_0: u32, } #[test] fn bindgen_test_layout___last_branch_record() { const UNINIT: ::std::mem::MaybeUninit<__last_branch_record> = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::<__last_branch_record>(), 24usize, concat!("Size of: ", stringify!(__last_branch_record)) ); assert_eq!( ::std::mem::align_of::<__last_branch_record>(), 8usize, concat!("Alignment of ", stringify!(__last_branch_record)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__from_ip) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(__last_branch_record), "::", stringify!(__from_ip) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__to_ip) as usize - ptr as usize }, 8usize, concat!( "Offset of field: ", stringify!(__last_branch_record), "::", stringify!(__to_ip) ) ); } impl __last_branch_record { #[inline] pub fn __mispredict(&self) -> __uint32_t { unsafe { ::std::mem::transmute(self._bitfield_1.get(0usize, 1u8) as u32) } } #[inline] pub fn set___mispredict(&mut self, val: __uint32_t) { unsafe { let val: u32 = ::std::mem::transmute(val); self._bitfield_1.set(0usize, 1u8, val as u64) } } #[inline] pub fn __tsx_abort(&self) -> __uint32_t { unsafe { ::std::mem::transmute(self._bitfield_1.get(1usize, 1u8) as u32) } } #[inline] pub fn set___tsx_abort(&mut self, val: __uint32_t) { unsafe { let val: u32 = ::std::mem::transmute(val); self._bitfield_1.set(1usize, 1u8, val as u64) } } #[inline] pub fn __in_tsx(&self) -> __uint32_t { unsafe { ::std::mem::transmute(self._bitfield_1.get(2usize, 1u8) as u32) } } #[inline] pub fn set___in_tsx(&mut self, val: __uint32_t) { unsafe { let val: u32 = ::std::mem::transmute(val); self._bitfield_1.set(2usize, 1u8, val as u64) } } #[inline] pub fn __cycle_count(&self) -> __uint32_t { unsafe { ::std::mem::transmute(self._bitfield_1.get(3usize, 16u8) as u32) } } #[inline] pub fn set___cycle_count(&mut self, val: __uint32_t) { unsafe { let val: u32 = ::std::mem::transmute(val); self._bitfield_1.set(3usize, 16u8, val as u64) } } #[inline] pub fn __reserved(&self) -> __uint32_t { unsafe { ::std::mem::transmute(self._bitfield_1.get(19usize, 13u8) as u32) } } #[inline] pub fn set___reserved(&mut self, val: __uint32_t) { unsafe { let val: u32 = ::std::mem::transmute(val); self._bitfield_1.set(19usize, 13u8, val as u64) } } #[inline] pub fn new_bitfield_1( __mispredict: __uint32_t, __tsx_abort: __uint32_t, __in_tsx: __uint32_t, __cycle_count: __uint32_t, __reserved: __uint32_t, ) -> __BindgenBitfieldUnit<[u8; 4usize]> { let mut __bindgen_bitfield_unit: __BindgenBitfieldUnit<[u8; 4usize]> = Default::default(); __bindgen_bitfield_unit.set(0usize, 1u8, { let __mispredict: u32 = unsafe { ::std::mem::transmute(__mispredict) }; __mispredict as u64 }); __bindgen_bitfield_unit.set(1usize, 1u8, { let __tsx_abort: u32 = unsafe { ::std::mem::transmute(__tsx_abort) }; __tsx_abort as u64 }); __bindgen_bitfield_unit.set(2usize, 1u8, { let __in_tsx: u32 = unsafe { ::std::mem::transmute(__in_tsx) }; __in_tsx as u64 }); __bindgen_bitfield_unit.set(3usize, 16u8, { let __cycle_count: u32 = unsafe { ::std::mem::transmute(__cycle_count) }; __cycle_count as u64 }); __bindgen_bitfield_unit.set(19usize, 13u8, { let __reserved: u32 = unsafe { ::std::mem::transmute(__reserved) }; __reserved as u64 }); __bindgen_bitfield_unit } } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct __last_branch_state { pub __lbr_count: ::std::os::raw::c_int, pub _bitfield_align_1: [u32; 0], pub _bitfield_1: __BindgenBitfieldUnit<[u8; 4usize]>, pub __lbrs: [__last_branch_record; 32usize], } #[test] fn bindgen_test_layout___last_branch_state() { const UNINIT: ::std::mem::MaybeUninit<__last_branch_state> = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::<__last_branch_state>(), 776usize, concat!("Size of: ", stringify!(__last_branch_state)) ); assert_eq!( ::std::mem::align_of::<__last_branch_state>(), 8usize, concat!("Alignment of ", stringify!(__last_branch_state)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__lbr_count) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(__last_branch_state), "::", stringify!(__lbr_count) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__lbrs) as usize - ptr as usize }, 8usize, concat!( "Offset of field: ", stringify!(__last_branch_state), "::", stringify!(__lbrs) ) ); } impl __last_branch_state { #[inline] pub fn __lbr_supported_tsx(&self) -> __uint32_t { unsafe { ::std::mem::transmute(self._bitfield_1.get(0usize, 1u8) as u32) } } #[inline] pub fn set___lbr_supported_tsx(&mut self, val: __uint32_t) { unsafe { let val: u32 = ::std::mem::transmute(val); self._bitfield_1.set(0usize, 1u8, val as u64) } } #[inline] pub fn __lbr_supported_cycle_count(&self) -> __uint32_t { unsafe { ::std::mem::transmute(self._bitfield_1.get(1usize, 1u8) as u32) } } #[inline] pub fn set___lbr_supported_cycle_count(&mut self, val: __uint32_t) { unsafe { let val: u32 = ::std::mem::transmute(val); self._bitfield_1.set(1usize, 1u8, val as u64) } } #[inline] pub fn __reserved(&self) -> __uint32_t { unsafe { ::std::mem::transmute(self._bitfield_1.get(2usize, 30u8) as u32) } } #[inline] pub fn set___reserved(&mut self, val: __uint32_t) { unsafe { let val: u32 = ::std::mem::transmute(val); self._bitfield_1.set(2usize, 30u8, val as u64) } } #[inline] pub fn new_bitfield_1( __lbr_supported_tsx: __uint32_t, __lbr_supported_cycle_count: __uint32_t, __reserved: __uint32_t, ) -> __BindgenBitfieldUnit<[u8; 4usize]> { let mut __bindgen_bitfield_unit: __BindgenBitfieldUnit<[u8; 4usize]> = Default::default(); __bindgen_bitfield_unit.set(0usize, 1u8, { let __lbr_supported_tsx: u32 = unsafe { ::std::mem::transmute(__lbr_supported_tsx) }; __lbr_supported_tsx as u64 }); __bindgen_bitfield_unit.set(1usize, 1u8, { let __lbr_supported_cycle_count: u32 = unsafe { ::std::mem::transmute(__lbr_supported_cycle_count) }; __lbr_supported_cycle_count as u64 }); __bindgen_bitfield_unit.set(2usize, 30u8, { let __reserved: u32 = unsafe { ::std::mem::transmute(__reserved) }; __reserved as u64 }); __bindgen_bitfield_unit } } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct __x86_pagein_state { pub __pagein_error: ::std::os::raw::c_int, } #[test] fn bindgen_test_layout___x86_pagein_state() { const UNINIT: ::std::mem::MaybeUninit<__x86_pagein_state> = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::<__x86_pagein_state>(), 4usize, concat!("Size of: ", stringify!(__x86_pagein_state)) ); assert_eq!( ::std::mem::align_of::<__x86_pagein_state>(), 4usize, concat!("Alignment of ", stringify!(__x86_pagein_state)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__pagein_error) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(__x86_pagein_state), "::", stringify!(__pagein_error) ) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct __darwin_x86_thread_state64 { pub __rax: __uint64_t, pub __rbx: __uint64_t, pub __rcx: __uint64_t, pub __rdx: __uint64_t, pub __rdi: __uint64_t, pub __rsi: __uint64_t, pub __rbp: __uint64_t, pub __rsp: __uint64_t, pub __r8: __uint64_t, pub __r9: __uint64_t, pub __r10: __uint64_t, pub __r11: __uint64_t, pub __r12: __uint64_t, pub __r13: __uint64_t, pub __r14: __uint64_t, pub __r15: __uint64_t, pub __rip: __uint64_t, pub __rflags: __uint64_t, pub __cs: __uint64_t, pub __fs: __uint64_t, pub __gs: __uint64_t, } #[test] fn bindgen_test_layout___darwin_x86_thread_state64() { const UNINIT: ::std::mem::MaybeUninit<__darwin_x86_thread_state64> = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::<__darwin_x86_thread_state64>(), 168usize, concat!("Size of: ", stringify!(__darwin_x86_thread_state64)) ); assert_eq!( ::std::mem::align_of::<__darwin_x86_thread_state64>(), 8usize, concat!("Alignment of ", stringify!(__darwin_x86_thread_state64)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__rax) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(__darwin_x86_thread_state64), "::", stringify!(__rax) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__rbx) as usize - ptr as usize }, 8usize, concat!( "Offset of field: ", stringify!(__darwin_x86_thread_state64), "::", stringify!(__rbx) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__rcx) as usize - ptr as usize }, 16usize, concat!( "Offset of field: ", stringify!(__darwin_x86_thread_state64), "::", stringify!(__rcx) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__rdx) as usize - ptr as usize }, 24usize, concat!( "Offset of field: ", stringify!(__darwin_x86_thread_state64), "::", stringify!(__rdx) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__rdi) as usize - ptr as usize }, 32usize, concat!( "Offset of field: ", stringify!(__darwin_x86_thread_state64), "::", stringify!(__rdi) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__rsi) as usize - ptr as usize }, 40usize, concat!( "Offset of field: ", stringify!(__darwin_x86_thread_state64), "::", stringify!(__rsi) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__rbp) as usize - ptr as usize }, 48usize, concat!( "Offset of field: ", stringify!(__darwin_x86_thread_state64), "::", stringify!(__rbp) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__rsp) as usize - ptr as usize }, 56usize, concat!( "Offset of field: ", stringify!(__darwin_x86_thread_state64), "::", stringify!(__rsp) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__r8) as usize - ptr as usize }, 64usize, concat!( "Offset of field: ", stringify!(__darwin_x86_thread_state64), "::", stringify!(__r8) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__r9) as usize - ptr as usize }, 72usize, concat!( "Offset of field: ", stringify!(__darwin_x86_thread_state64), "::", stringify!(__r9) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__r10) as usize - ptr as usize }, 80usize, concat!( "Offset of field: ", stringify!(__darwin_x86_thread_state64), "::", stringify!(__r10) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__r11) as usize - ptr as usize }, 88usize, concat!( "Offset of field: ", stringify!(__darwin_x86_thread_state64), "::", stringify!(__r11) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__r12) as usize - ptr as usize }, 96usize, concat!( "Offset of field: ", stringify!(__darwin_x86_thread_state64), "::", stringify!(__r12) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__r13) as usize - ptr as usize }, 104usize, concat!( "Offset of field: ", stringify!(__darwin_x86_thread_state64), "::", stringify!(__r13) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__r14) as usize - ptr as usize }, 112usize, concat!( "Offset of field: ", stringify!(__darwin_x86_thread_state64), "::", stringify!(__r14) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__r15) as usize - ptr as usize }, 120usize, concat!( "Offset of field: ", stringify!(__darwin_x86_thread_state64), "::", stringify!(__r15) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__rip) as usize - ptr as usize }, 128usize, concat!( "Offset of field: ", stringify!(__darwin_x86_thread_state64), "::", stringify!(__rip) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__rflags) as usize - ptr as usize }, 136usize, concat!( "Offset of field: ", stringify!(__darwin_x86_thread_state64), "::", stringify!(__rflags) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__cs) as usize - ptr as usize }, 144usize, concat!( "Offset of field: ", stringify!(__darwin_x86_thread_state64), "::", stringify!(__cs) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fs) as usize - ptr as usize }, 152usize, concat!( "Offset of field: ", stringify!(__darwin_x86_thread_state64), "::", stringify!(__fs) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__gs) as usize - ptr as usize }, 160usize, concat!( "Offset of field: ", stringify!(__darwin_x86_thread_state64), "::", stringify!(__gs) ) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct __darwin_x86_thread_full_state64 { pub __ss64: __darwin_x86_thread_state64, pub __ds: __uint64_t, pub __es: __uint64_t, pub __ss: __uint64_t, pub __gsbase: __uint64_t, } #[test] fn bindgen_test_layout___darwin_x86_thread_full_state64() { const UNINIT: ::std::mem::MaybeUninit<__darwin_x86_thread_full_state64> = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::<__darwin_x86_thread_full_state64>(), 200usize, concat!("Size of: ", stringify!(__darwin_x86_thread_full_state64)) ); assert_eq!( ::std::mem::align_of::<__darwin_x86_thread_full_state64>(), 8usize, concat!("Alignment of ", stringify!(__darwin_x86_thread_full_state64)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__ss64) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(__darwin_x86_thread_full_state64), "::", stringify!(__ss64) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__ds) as usize - ptr as usize }, 168usize, concat!( "Offset of field: ", stringify!(__darwin_x86_thread_full_state64), "::", stringify!(__ds) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__es) as usize - ptr as usize }, 176usize, concat!( "Offset of field: ", stringify!(__darwin_x86_thread_full_state64), "::", stringify!(__es) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__ss) as usize - ptr as usize }, 184usize, concat!( "Offset of field: ", stringify!(__darwin_x86_thread_full_state64), "::", stringify!(__ss) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__gsbase) as usize - ptr as usize }, 192usize, concat!( "Offset of field: ", stringify!(__darwin_x86_thread_full_state64), "::", stringify!(__gsbase) ) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct __darwin_x86_float_state64 { pub __fpu_reserved: [::std::os::raw::c_int; 2usize], pub __fpu_fcw: __darwin_fp_control, pub __fpu_fsw: __darwin_fp_status, pub __fpu_ftw: __uint8_t, pub __fpu_rsrv1: __uint8_t, pub __fpu_fop: __uint16_t, pub __fpu_ip: __uint32_t, pub __fpu_cs: __uint16_t, pub __fpu_rsrv2: __uint16_t, pub __fpu_dp: __uint32_t, pub __fpu_ds: __uint16_t, pub __fpu_rsrv3: __uint16_t, pub __fpu_mxcsr: __uint32_t, pub __fpu_mxcsrmask: __uint32_t, pub __fpu_stmm0: __darwin_mmst_reg, pub __fpu_stmm1: __darwin_mmst_reg, pub __fpu_stmm2: __darwin_mmst_reg, pub __fpu_stmm3: __darwin_mmst_reg, pub __fpu_stmm4: __darwin_mmst_reg, pub __fpu_stmm5: __darwin_mmst_reg, pub __fpu_stmm6: __darwin_mmst_reg, pub __fpu_stmm7: __darwin_mmst_reg, pub __fpu_xmm0: __darwin_xmm_reg, pub __fpu_xmm1: __darwin_xmm_reg, pub __fpu_xmm2: __darwin_xmm_reg, pub __fpu_xmm3: __darwin_xmm_reg, pub __fpu_xmm4: __darwin_xmm_reg, pub __fpu_xmm5: __darwin_xmm_reg, pub __fpu_xmm6: __darwin_xmm_reg, pub __fpu_xmm7: __darwin_xmm_reg, pub __fpu_xmm8: __darwin_xmm_reg, pub __fpu_xmm9: __darwin_xmm_reg, pub __fpu_xmm10: __darwin_xmm_reg, pub __fpu_xmm11: __darwin_xmm_reg, pub __fpu_xmm12: __darwin_xmm_reg, pub __fpu_xmm13: __darwin_xmm_reg, pub __fpu_xmm14: __darwin_xmm_reg, pub __fpu_xmm15: __darwin_xmm_reg, pub __fpu_rsrv4: [::std::os::raw::c_char; 96usize], pub __fpu_reserved1: ::std::os::raw::c_int, } #[test] fn bindgen_test_layout___darwin_x86_float_state64() { const UNINIT: ::std::mem::MaybeUninit<__darwin_x86_float_state64> = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::<__darwin_x86_float_state64>(), 524usize, concat!("Size of: ", stringify!(__darwin_x86_float_state64)) ); assert_eq!( ::std::mem::align_of::<__darwin_x86_float_state64>(), 4usize, concat!("Alignment of ", stringify!(__darwin_x86_float_state64)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_reserved) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(__darwin_x86_float_state64), "::", stringify!(__fpu_reserved) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_fcw) as usize - ptr as usize }, 8usize, concat!( "Offset of field: ", stringify!(__darwin_x86_float_state64), "::", stringify!(__fpu_fcw) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_fsw) as usize - ptr as usize }, 10usize, concat!( "Offset of field: ", stringify!(__darwin_x86_float_state64), "::", stringify!(__fpu_fsw) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_ftw) as usize - ptr as usize }, 12usize, concat!( "Offset of field: ", stringify!(__darwin_x86_float_state64), "::", stringify!(__fpu_ftw) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_rsrv1) as usize - ptr as usize }, 13usize, concat!( "Offset of field: ", stringify!(__darwin_x86_float_state64), "::", stringify!(__fpu_rsrv1) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_fop) as usize - ptr as usize }, 14usize, concat!( "Offset of field: ", stringify!(__darwin_x86_float_state64), "::", stringify!(__fpu_fop) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_ip) as usize - ptr as usize }, 16usize, concat!( "Offset of field: ", stringify!(__darwin_x86_float_state64), "::", stringify!(__fpu_ip) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_cs) as usize - ptr as usize }, 20usize, concat!( "Offset of field: ", stringify!(__darwin_x86_float_state64), "::", stringify!(__fpu_cs) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_rsrv2) as usize - ptr as usize }, 22usize, concat!( "Offset of field: ", stringify!(__darwin_x86_float_state64), "::", stringify!(__fpu_rsrv2) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_dp) as usize - ptr as usize }, 24usize, concat!( "Offset of field: ", stringify!(__darwin_x86_float_state64), "::", stringify!(__fpu_dp) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_ds) as usize - ptr as usize }, 28usize, concat!( "Offset of field: ", stringify!(__darwin_x86_float_state64), "::", stringify!(__fpu_ds) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_rsrv3) as usize - ptr as usize }, 30usize, concat!( "Offset of field: ", stringify!(__darwin_x86_float_state64), "::", stringify!(__fpu_rsrv3) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_mxcsr) as usize - ptr as usize }, 32usize, concat!( "Offset of field: ", stringify!(__darwin_x86_float_state64), "::", stringify!(__fpu_mxcsr) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_mxcsrmask) as usize - ptr as usize }, 36usize, concat!( "Offset of field: ", stringify!(__darwin_x86_float_state64), "::", stringify!(__fpu_mxcsrmask) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_stmm0) as usize - ptr as usize }, 40usize, concat!( "Offset of field: ", stringify!(__darwin_x86_float_state64), "::", stringify!(__fpu_stmm0) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_stmm1) as usize - ptr as usize }, 56usize, concat!( "Offset of field: ", stringify!(__darwin_x86_float_state64), "::", stringify!(__fpu_stmm1) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_stmm2) as usize - ptr as usize }, 72usize, concat!( "Offset of field: ", stringify!(__darwin_x86_float_state64), "::", stringify!(__fpu_stmm2) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_stmm3) as usize - ptr as usize }, 88usize, concat!( "Offset of field: ", stringify!(__darwin_x86_float_state64), "::", stringify!(__fpu_stmm3) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_stmm4) as usize - ptr as usize }, 104usize, concat!( "Offset of field: ", stringify!(__darwin_x86_float_state64), "::", stringify!(__fpu_stmm4) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_stmm5) as usize - ptr as usize }, 120usize, concat!( "Offset of field: ", stringify!(__darwin_x86_float_state64), "::", stringify!(__fpu_stmm5) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_stmm6) as usize - ptr as usize }, 136usize, concat!( "Offset of field: ", stringify!(__darwin_x86_float_state64), "::", stringify!(__fpu_stmm6) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_stmm7) as usize - ptr as usize }, 152usize, concat!( "Offset of field: ", stringify!(__darwin_x86_float_state64), "::", stringify!(__fpu_stmm7) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_xmm0) as usize - ptr as usize }, 168usize, concat!( "Offset of field: ", stringify!(__darwin_x86_float_state64), "::", stringify!(__fpu_xmm0) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_xmm1) as usize - ptr as usize }, 184usize, concat!( "Offset of field: ", stringify!(__darwin_x86_float_state64), "::", stringify!(__fpu_xmm1) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_xmm2) as usize - ptr as usize }, 200usize, concat!( "Offset of field: ", stringify!(__darwin_x86_float_state64), "::", stringify!(__fpu_xmm2) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_xmm3) as usize - ptr as usize }, 216usize, concat!( "Offset of field: ", stringify!(__darwin_x86_float_state64), "::", stringify!(__fpu_xmm3) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_xmm4) as usize - ptr as usize }, 232usize, concat!( "Offset of field: ", stringify!(__darwin_x86_float_state64), "::", stringify!(__fpu_xmm4) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_xmm5) as usize - ptr as usize }, 248usize, concat!( "Offset of field: ", stringify!(__darwin_x86_float_state64), "::", stringify!(__fpu_xmm5) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_xmm6) as usize - ptr as usize }, 264usize, concat!( "Offset of field: ", stringify!(__darwin_x86_float_state64), "::", stringify!(__fpu_xmm6) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_xmm7) as usize - ptr as usize }, 280usize, concat!( "Offset of field: ", stringify!(__darwin_x86_float_state64), "::", stringify!(__fpu_xmm7) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_xmm8) as usize - ptr as usize }, 296usize, concat!( "Offset of field: ", stringify!(__darwin_x86_float_state64), "::", stringify!(__fpu_xmm8) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_xmm9) as usize - ptr as usize }, 312usize, concat!( "Offset of field: ", stringify!(__darwin_x86_float_state64), "::", stringify!(__fpu_xmm9) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_xmm10) as usize - ptr as usize }, 328usize, concat!( "Offset of field: ", stringify!(__darwin_x86_float_state64), "::", stringify!(__fpu_xmm10) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_xmm11) as usize - ptr as usize }, 344usize, concat!( "Offset of field: ", stringify!(__darwin_x86_float_state64), "::", stringify!(__fpu_xmm11) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_xmm12) as usize - ptr as usize }, 360usize, concat!( "Offset of field: ", stringify!(__darwin_x86_float_state64), "::", stringify!(__fpu_xmm12) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_xmm13) as usize - ptr as usize }, 376usize, concat!( "Offset of field: ", stringify!(__darwin_x86_float_state64), "::", stringify!(__fpu_xmm13) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_xmm14) as usize - ptr as usize }, 392usize, concat!( "Offset of field: ", stringify!(__darwin_x86_float_state64), "::", stringify!(__fpu_xmm14) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_xmm15) as usize - ptr as usize }, 408usize, concat!( "Offset of field: ", stringify!(__darwin_x86_float_state64), "::", stringify!(__fpu_xmm15) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_rsrv4) as usize - ptr as usize }, 424usize, concat!( "Offset of field: ", stringify!(__darwin_x86_float_state64), "::", stringify!(__fpu_rsrv4) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_reserved1) as usize - ptr as usize }, 520usize, concat!( "Offset of field: ", stringify!(__darwin_x86_float_state64), "::", stringify!(__fpu_reserved1) ) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct __darwin_x86_avx_state64 { pub __fpu_reserved: [::std::os::raw::c_int; 2usize], pub __fpu_fcw: __darwin_fp_control, pub __fpu_fsw: __darwin_fp_status, pub __fpu_ftw: __uint8_t, pub __fpu_rsrv1: __uint8_t, pub __fpu_fop: __uint16_t, pub __fpu_ip: __uint32_t, pub __fpu_cs: __uint16_t, pub __fpu_rsrv2: __uint16_t, pub __fpu_dp: __uint32_t, pub __fpu_ds: __uint16_t, pub __fpu_rsrv3: __uint16_t, pub __fpu_mxcsr: __uint32_t, pub __fpu_mxcsrmask: __uint32_t, pub __fpu_stmm0: __darwin_mmst_reg, pub __fpu_stmm1: __darwin_mmst_reg, pub __fpu_stmm2: __darwin_mmst_reg, pub __fpu_stmm3: __darwin_mmst_reg, pub __fpu_stmm4: __darwin_mmst_reg, pub __fpu_stmm5: __darwin_mmst_reg, pub __fpu_stmm6: __darwin_mmst_reg, pub __fpu_stmm7: __darwin_mmst_reg, pub __fpu_xmm0: __darwin_xmm_reg, pub __fpu_xmm1: __darwin_xmm_reg, pub __fpu_xmm2: __darwin_xmm_reg, pub __fpu_xmm3: __darwin_xmm_reg, pub __fpu_xmm4: __darwin_xmm_reg, pub __fpu_xmm5: __darwin_xmm_reg, pub __fpu_xmm6: __darwin_xmm_reg, pub __fpu_xmm7: __darwin_xmm_reg, pub __fpu_xmm8: __darwin_xmm_reg, pub __fpu_xmm9: __darwin_xmm_reg, pub __fpu_xmm10: __darwin_xmm_reg, pub __fpu_xmm11: __darwin_xmm_reg, pub __fpu_xmm12: __darwin_xmm_reg, pub __fpu_xmm13: __darwin_xmm_reg, pub __fpu_xmm14: __darwin_xmm_reg, pub __fpu_xmm15: __darwin_xmm_reg, pub __fpu_rsrv4: [::std::os::raw::c_char; 96usize], pub __fpu_reserved1: ::std::os::raw::c_int, pub __avx_reserved1: [::std::os::raw::c_char; 64usize], pub __fpu_ymmh0: __darwin_xmm_reg, pub __fpu_ymmh1: __darwin_xmm_reg, pub __fpu_ymmh2: __darwin_xmm_reg, pub __fpu_ymmh3: __darwin_xmm_reg, pub __fpu_ymmh4: __darwin_xmm_reg, pub __fpu_ymmh5: __darwin_xmm_reg, pub __fpu_ymmh6: __darwin_xmm_reg, pub __fpu_ymmh7: __darwin_xmm_reg, pub __fpu_ymmh8: __darwin_xmm_reg, pub __fpu_ymmh9: __darwin_xmm_reg, pub __fpu_ymmh10: __darwin_xmm_reg, pub __fpu_ymmh11: __darwin_xmm_reg, pub __fpu_ymmh12: __darwin_xmm_reg, pub __fpu_ymmh13: __darwin_xmm_reg, pub __fpu_ymmh14: __darwin_xmm_reg, pub __fpu_ymmh15: __darwin_xmm_reg, } #[test] fn bindgen_test_layout___darwin_x86_avx_state64() { const UNINIT: ::std::mem::MaybeUninit<__darwin_x86_avx_state64> = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::<__darwin_x86_avx_state64>(), 844usize, concat!("Size of: ", stringify!(__darwin_x86_avx_state64)) ); assert_eq!( ::std::mem::align_of::<__darwin_x86_avx_state64>(), 4usize, concat!("Alignment of ", stringify!(__darwin_x86_avx_state64)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_reserved) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(__darwin_x86_avx_state64), "::", stringify!(__fpu_reserved) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_fcw) as usize - ptr as usize }, 8usize, concat!( "Offset of field: ", stringify!(__darwin_x86_avx_state64), "::", stringify!(__fpu_fcw) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_fsw) as usize - ptr as usize }, 10usize, concat!( "Offset of field: ", stringify!(__darwin_x86_avx_state64), "::", stringify!(__fpu_fsw) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_ftw) as usize - ptr as usize }, 12usize, concat!( "Offset of field: ", stringify!(__darwin_x86_avx_state64), "::", stringify!(__fpu_ftw) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_rsrv1) as usize - ptr as usize }, 13usize, concat!( "Offset of field: ", stringify!(__darwin_x86_avx_state64), "::", stringify!(__fpu_rsrv1) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_fop) as usize - ptr as usize }, 14usize, concat!( "Offset of field: ", stringify!(__darwin_x86_avx_state64), "::", stringify!(__fpu_fop) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_ip) as usize - ptr as usize }, 16usize, concat!( "Offset of field: ", stringify!(__darwin_x86_avx_state64), "::", stringify!(__fpu_ip) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_cs) as usize - ptr as usize }, 20usize, concat!( "Offset of field: ", stringify!(__darwin_x86_avx_state64), "::", stringify!(__fpu_cs) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_rsrv2) as usize - ptr as usize }, 22usize, concat!( "Offset of field: ", stringify!(__darwin_x86_avx_state64), "::", stringify!(__fpu_rsrv2) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_dp) as usize - ptr as usize }, 24usize, concat!( "Offset of field: ", stringify!(__darwin_x86_avx_state64), "::", stringify!(__fpu_dp) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_ds) as usize - ptr as usize }, 28usize, concat!( "Offset of field: ", stringify!(__darwin_x86_avx_state64), "::", stringify!(__fpu_ds) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_rsrv3) as usize - ptr as usize }, 30usize, concat!( "Offset of field: ", stringify!(__darwin_x86_avx_state64), "::", stringify!(__fpu_rsrv3) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_mxcsr) as usize - ptr as usize }, 32usize, concat!( "Offset of field: ", stringify!(__darwin_x86_avx_state64), "::", stringify!(__fpu_mxcsr) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_mxcsrmask) as usize - ptr as usize }, 36usize, concat!( "Offset of field: ", stringify!(__darwin_x86_avx_state64), "::", stringify!(__fpu_mxcsrmask) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_stmm0) as usize - ptr as usize }, 40usize, concat!( "Offset of field: ", stringify!(__darwin_x86_avx_state64), "::", stringify!(__fpu_stmm0) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_stmm1) as usize - ptr as usize }, 56usize, concat!( "Offset of field: ", stringify!(__darwin_x86_avx_state64), "::", stringify!(__fpu_stmm1) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_stmm2) as usize - ptr as usize }, 72usize, concat!( "Offset of field: ", stringify!(__darwin_x86_avx_state64), "::", stringify!(__fpu_stmm2) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_stmm3) as usize - ptr as usize }, 88usize, concat!( "Offset of field: ", stringify!(__darwin_x86_avx_state64), "::", stringify!(__fpu_stmm3) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_stmm4) as usize - ptr as usize }, 104usize, concat!( "Offset of field: ", stringify!(__darwin_x86_avx_state64), "::", stringify!(__fpu_stmm4) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_stmm5) as usize - ptr as usize }, 120usize, concat!( "Offset of field: ", stringify!(__darwin_x86_avx_state64), "::", stringify!(__fpu_stmm5) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_stmm6) as usize - ptr as usize }, 136usize, concat!( "Offset of field: ", stringify!(__darwin_x86_avx_state64), "::", stringify!(__fpu_stmm6) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_stmm7) as usize - ptr as usize }, 152usize, concat!( "Offset of field: ", stringify!(__darwin_x86_avx_state64), "::", stringify!(__fpu_stmm7) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_xmm0) as usize - ptr as usize }, 168usize, concat!( "Offset of field: ", stringify!(__darwin_x86_avx_state64), "::", stringify!(__fpu_xmm0) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_xmm1) as usize - ptr as usize }, 184usize, concat!( "Offset of field: ", stringify!(__darwin_x86_avx_state64), "::", stringify!(__fpu_xmm1) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_xmm2) as usize - ptr as usize }, 200usize, concat!( "Offset of field: ", stringify!(__darwin_x86_avx_state64), "::", stringify!(__fpu_xmm2) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_xmm3) as usize - ptr as usize }, 216usize, concat!( "Offset of field: ", stringify!(__darwin_x86_avx_state64), "::", stringify!(__fpu_xmm3) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_xmm4) as usize - ptr as usize }, 232usize, concat!( "Offset of field: ", stringify!(__darwin_x86_avx_state64), "::", stringify!(__fpu_xmm4) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_xmm5) as usize - ptr as usize }, 248usize, concat!( "Offset of field: ", stringify!(__darwin_x86_avx_state64), "::", stringify!(__fpu_xmm5) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_xmm6) as usize - ptr as usize }, 264usize, concat!( "Offset of field: ", stringify!(__darwin_x86_avx_state64), "::", stringify!(__fpu_xmm6) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_xmm7) as usize - ptr as usize }, 280usize, concat!( "Offset of field: ", stringify!(__darwin_x86_avx_state64), "::", stringify!(__fpu_xmm7) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_xmm8) as usize - ptr as usize }, 296usize, concat!( "Offset of field: ", stringify!(__darwin_x86_avx_state64), "::", stringify!(__fpu_xmm8) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_xmm9) as usize - ptr as usize }, 312usize, concat!( "Offset of field: ", stringify!(__darwin_x86_avx_state64), "::", stringify!(__fpu_xmm9) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_xmm10) as usize - ptr as usize }, 328usize, concat!( "Offset of field: ", stringify!(__darwin_x86_avx_state64), "::", stringify!(__fpu_xmm10) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_xmm11) as usize - ptr as usize }, 344usize, concat!( "Offset of field: ", stringify!(__darwin_x86_avx_state64), "::", stringify!(__fpu_xmm11) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_xmm12) as usize - ptr as usize }, 360usize, concat!( "Offset of field: ", stringify!(__darwin_x86_avx_state64), "::", stringify!(__fpu_xmm12) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_xmm13) as usize - ptr as usize }, 376usize, concat!( "Offset of field: ", stringify!(__darwin_x86_avx_state64), "::", stringify!(__fpu_xmm13) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_xmm14) as usize - ptr as usize }, 392usize, concat!( "Offset of field: ", stringify!(__darwin_x86_avx_state64), "::", stringify!(__fpu_xmm14) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_xmm15) as usize - ptr as usize }, 408usize, concat!( "Offset of field: ", stringify!(__darwin_x86_avx_state64), "::", stringify!(__fpu_xmm15) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_rsrv4) as usize - ptr as usize }, 424usize, concat!( "Offset of field: ", stringify!(__darwin_x86_avx_state64), "::", stringify!(__fpu_rsrv4) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_reserved1) as usize - ptr as usize }, 520usize, concat!( "Offset of field: ", stringify!(__darwin_x86_avx_state64), "::", stringify!(__fpu_reserved1) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__avx_reserved1) as usize - ptr as usize }, 524usize, concat!( "Offset of field: ", stringify!(__darwin_x86_avx_state64), "::", stringify!(__avx_reserved1) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_ymmh0) as usize - ptr as usize }, 588usize, concat!( "Offset of field: ", stringify!(__darwin_x86_avx_state64), "::", stringify!(__fpu_ymmh0) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_ymmh1) as usize - ptr as usize }, 604usize, concat!( "Offset of field: ", stringify!(__darwin_x86_avx_state64), "::", stringify!(__fpu_ymmh1) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_ymmh2) as usize - ptr as usize }, 620usize, concat!( "Offset of field: ", stringify!(__darwin_x86_avx_state64), "::", stringify!(__fpu_ymmh2) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_ymmh3) as usize - ptr as usize }, 636usize, concat!( "Offset of field: ", stringify!(__darwin_x86_avx_state64), "::", stringify!(__fpu_ymmh3) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_ymmh4) as usize - ptr as usize }, 652usize, concat!( "Offset of field: ", stringify!(__darwin_x86_avx_state64), "::", stringify!(__fpu_ymmh4) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_ymmh5) as usize - ptr as usize }, 668usize, concat!( "Offset of field: ", stringify!(__darwin_x86_avx_state64), "::", stringify!(__fpu_ymmh5) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_ymmh6) as usize - ptr as usize }, 684usize, concat!( "Offset of field: ", stringify!(__darwin_x86_avx_state64), "::", stringify!(__fpu_ymmh6) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_ymmh7) as usize - ptr as usize }, 700usize, concat!( "Offset of field: ", stringify!(__darwin_x86_avx_state64), "::", stringify!(__fpu_ymmh7) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_ymmh8) as usize - ptr as usize }, 716usize, concat!( "Offset of field: ", stringify!(__darwin_x86_avx_state64), "::", stringify!(__fpu_ymmh8) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_ymmh9) as usize - ptr as usize }, 732usize, concat!( "Offset of field: ", stringify!(__darwin_x86_avx_state64), "::", stringify!(__fpu_ymmh9) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_ymmh10) as usize - ptr as usize }, 748usize, concat!( "Offset of field: ", stringify!(__darwin_x86_avx_state64), "::", stringify!(__fpu_ymmh10) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_ymmh11) as usize - ptr as usize }, 764usize, concat!( "Offset of field: ", stringify!(__darwin_x86_avx_state64), "::", stringify!(__fpu_ymmh11) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_ymmh12) as usize - ptr as usize }, 780usize, concat!( "Offset of field: ", stringify!(__darwin_x86_avx_state64), "::", stringify!(__fpu_ymmh12) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_ymmh13) as usize - ptr as usize }, 796usize, concat!( "Offset of field: ", stringify!(__darwin_x86_avx_state64), "::", stringify!(__fpu_ymmh13) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_ymmh14) as usize - ptr as usize }, 812usize, concat!( "Offset of field: ", stringify!(__darwin_x86_avx_state64), "::", stringify!(__fpu_ymmh14) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_ymmh15) as usize - ptr as usize }, 828usize, concat!( "Offset of field: ", stringify!(__darwin_x86_avx_state64), "::", stringify!(__fpu_ymmh15) ) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct __darwin_x86_avx512_state64 { pub __fpu_reserved: [::std::os::raw::c_int; 2usize], pub __fpu_fcw: __darwin_fp_control, pub __fpu_fsw: __darwin_fp_status, pub __fpu_ftw: __uint8_t, pub __fpu_rsrv1: __uint8_t, pub __fpu_fop: __uint16_t, pub __fpu_ip: __uint32_t, pub __fpu_cs: __uint16_t, pub __fpu_rsrv2: __uint16_t, pub __fpu_dp: __uint32_t, pub __fpu_ds: __uint16_t, pub __fpu_rsrv3: __uint16_t, pub __fpu_mxcsr: __uint32_t, pub __fpu_mxcsrmask: __uint32_t, pub __fpu_stmm0: __darwin_mmst_reg, pub __fpu_stmm1: __darwin_mmst_reg, pub __fpu_stmm2: __darwin_mmst_reg, pub __fpu_stmm3: __darwin_mmst_reg, pub __fpu_stmm4: __darwin_mmst_reg, pub __fpu_stmm5: __darwin_mmst_reg, pub __fpu_stmm6: __darwin_mmst_reg, pub __fpu_stmm7: __darwin_mmst_reg, pub __fpu_xmm0: __darwin_xmm_reg, pub __fpu_xmm1: __darwin_xmm_reg, pub __fpu_xmm2: __darwin_xmm_reg, pub __fpu_xmm3: __darwin_xmm_reg, pub __fpu_xmm4: __darwin_xmm_reg, pub __fpu_xmm5: __darwin_xmm_reg, pub __fpu_xmm6: __darwin_xmm_reg, pub __fpu_xmm7: __darwin_xmm_reg, pub __fpu_xmm8: __darwin_xmm_reg, pub __fpu_xmm9: __darwin_xmm_reg, pub __fpu_xmm10: __darwin_xmm_reg, pub __fpu_xmm11: __darwin_xmm_reg, pub __fpu_xmm12: __darwin_xmm_reg, pub __fpu_xmm13: __darwin_xmm_reg, pub __fpu_xmm14: __darwin_xmm_reg, pub __fpu_xmm15: __darwin_xmm_reg, pub __fpu_rsrv4: [::std::os::raw::c_char; 96usize], pub __fpu_reserved1: ::std::os::raw::c_int, pub __avx_reserved1: [::std::os::raw::c_char; 64usize], pub __fpu_ymmh0: __darwin_xmm_reg, pub __fpu_ymmh1: __darwin_xmm_reg, pub __fpu_ymmh2: __darwin_xmm_reg, pub __fpu_ymmh3: __darwin_xmm_reg, pub __fpu_ymmh4: __darwin_xmm_reg, pub __fpu_ymmh5: __darwin_xmm_reg, pub __fpu_ymmh6: __darwin_xmm_reg, pub __fpu_ymmh7: __darwin_xmm_reg, pub __fpu_ymmh8: __darwin_xmm_reg, pub __fpu_ymmh9: __darwin_xmm_reg, pub __fpu_ymmh10: __darwin_xmm_reg, pub __fpu_ymmh11: __darwin_xmm_reg, pub __fpu_ymmh12: __darwin_xmm_reg, pub __fpu_ymmh13: __darwin_xmm_reg, pub __fpu_ymmh14: __darwin_xmm_reg, pub __fpu_ymmh15: __darwin_xmm_reg, pub __fpu_k0: __darwin_opmask_reg, pub __fpu_k1: __darwin_opmask_reg, pub __fpu_k2: __darwin_opmask_reg, pub __fpu_k3: __darwin_opmask_reg, pub __fpu_k4: __darwin_opmask_reg, pub __fpu_k5: __darwin_opmask_reg, pub __fpu_k6: __darwin_opmask_reg, pub __fpu_k7: __darwin_opmask_reg, pub __fpu_zmmh0: __darwin_ymm_reg, pub __fpu_zmmh1: __darwin_ymm_reg, pub __fpu_zmmh2: __darwin_ymm_reg, pub __fpu_zmmh3: __darwin_ymm_reg, pub __fpu_zmmh4: __darwin_ymm_reg, pub __fpu_zmmh5: __darwin_ymm_reg, pub __fpu_zmmh6: __darwin_ymm_reg, pub __fpu_zmmh7: __darwin_ymm_reg, pub __fpu_zmmh8: __darwin_ymm_reg, pub __fpu_zmmh9: __darwin_ymm_reg, pub __fpu_zmmh10: __darwin_ymm_reg, pub __fpu_zmmh11: __darwin_ymm_reg, pub __fpu_zmmh12: __darwin_ymm_reg, pub __fpu_zmmh13: __darwin_ymm_reg, pub __fpu_zmmh14: __darwin_ymm_reg, pub __fpu_zmmh15: __darwin_ymm_reg, pub __fpu_zmm16: __darwin_zmm_reg, pub __fpu_zmm17: __darwin_zmm_reg, pub __fpu_zmm18: __darwin_zmm_reg, pub __fpu_zmm19: __darwin_zmm_reg, pub __fpu_zmm20: __darwin_zmm_reg, pub __fpu_zmm21: __darwin_zmm_reg, pub __fpu_zmm22: __darwin_zmm_reg, pub __fpu_zmm23: __darwin_zmm_reg, pub __fpu_zmm24: __darwin_zmm_reg, pub __fpu_zmm25: __darwin_zmm_reg, pub __fpu_zmm26: __darwin_zmm_reg, pub __fpu_zmm27: __darwin_zmm_reg, pub __fpu_zmm28: __darwin_zmm_reg, pub __fpu_zmm29: __darwin_zmm_reg, pub __fpu_zmm30: __darwin_zmm_reg, pub __fpu_zmm31: __darwin_zmm_reg, } #[test] fn bindgen_test_layout___darwin_x86_avx512_state64() { const UNINIT: ::std::mem::MaybeUninit<__darwin_x86_avx512_state64> = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::<__darwin_x86_avx512_state64>(), 2444usize, concat!("Size of: ", stringify!(__darwin_x86_avx512_state64)) ); assert_eq!( ::std::mem::align_of::<__darwin_x86_avx512_state64>(), 4usize, concat!("Alignment of ", stringify!(__darwin_x86_avx512_state64)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_reserved) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(__darwin_x86_avx512_state64), "::", stringify!(__fpu_reserved) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_fcw) as usize - ptr as usize }, 8usize, concat!( "Offset of field: ", stringify!(__darwin_x86_avx512_state64), "::", stringify!(__fpu_fcw) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_fsw) as usize - ptr as usize }, 10usize, concat!( "Offset of field: ", stringify!(__darwin_x86_avx512_state64), "::", stringify!(__fpu_fsw) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_ftw) as usize - ptr as usize }, 12usize, concat!( "Offset of field: ", stringify!(__darwin_x86_avx512_state64), "::", stringify!(__fpu_ftw) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_rsrv1) as usize - ptr as usize }, 13usize, concat!( "Offset of field: ", stringify!(__darwin_x86_avx512_state64), "::", stringify!(__fpu_rsrv1) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_fop) as usize - ptr as usize }, 14usize, concat!( "Offset of field: ", stringify!(__darwin_x86_avx512_state64), "::", stringify!(__fpu_fop) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_ip) as usize - ptr as usize }, 16usize, concat!( "Offset of field: ", stringify!(__darwin_x86_avx512_state64), "::", stringify!(__fpu_ip) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_cs) as usize - ptr as usize }, 20usize, concat!( "Offset of field: ", stringify!(__darwin_x86_avx512_state64), "::", stringify!(__fpu_cs) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_rsrv2) as usize - ptr as usize }, 22usize, concat!( "Offset of field: ", stringify!(__darwin_x86_avx512_state64), "::", stringify!(__fpu_rsrv2) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_dp) as usize - ptr as usize }, 24usize, concat!( "Offset of field: ", stringify!(__darwin_x86_avx512_state64), "::", stringify!(__fpu_dp) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_ds) as usize - ptr as usize }, 28usize, concat!( "Offset of field: ", stringify!(__darwin_x86_avx512_state64), "::", stringify!(__fpu_ds) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_rsrv3) as usize - ptr as usize }, 30usize, concat!( "Offset of field: ", stringify!(__darwin_x86_avx512_state64), "::", stringify!(__fpu_rsrv3) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_mxcsr) as usize - ptr as usize }, 32usize, concat!( "Offset of field: ", stringify!(__darwin_x86_avx512_state64), "::", stringify!(__fpu_mxcsr) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_mxcsrmask) as usize - ptr as usize }, 36usize, concat!( "Offset of field: ", stringify!(__darwin_x86_avx512_state64), "::", stringify!(__fpu_mxcsrmask) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_stmm0) as usize - ptr as usize }, 40usize, concat!( "Offset of field: ", stringify!(__darwin_x86_avx512_state64), "::", stringify!(__fpu_stmm0) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_stmm1) as usize - ptr as usize }, 56usize, concat!( "Offset of field: ", stringify!(__darwin_x86_avx512_state64), "::", stringify!(__fpu_stmm1) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_stmm2) as usize - ptr as usize }, 72usize, concat!( "Offset of field: ", stringify!(__darwin_x86_avx512_state64), "::", stringify!(__fpu_stmm2) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_stmm3) as usize - ptr as usize }, 88usize, concat!( "Offset of field: ", stringify!(__darwin_x86_avx512_state64), "::", stringify!(__fpu_stmm3) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_stmm4) as usize - ptr as usize }, 104usize, concat!( "Offset of field: ", stringify!(__darwin_x86_avx512_state64), "::", stringify!(__fpu_stmm4) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_stmm5) as usize - ptr as usize }, 120usize, concat!( "Offset of field: ", stringify!(__darwin_x86_avx512_state64), "::", stringify!(__fpu_stmm5) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_stmm6) as usize - ptr as usize }, 136usize, concat!( "Offset of field: ", stringify!(__darwin_x86_avx512_state64), "::", stringify!(__fpu_stmm6) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_stmm7) as usize - ptr as usize }, 152usize, concat!( "Offset of field: ", stringify!(__darwin_x86_avx512_state64), "::", stringify!(__fpu_stmm7) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_xmm0) as usize - ptr as usize }, 168usize, concat!( "Offset of field: ", stringify!(__darwin_x86_avx512_state64), "::", stringify!(__fpu_xmm0) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_xmm1) as usize - ptr as usize }, 184usize, concat!( "Offset of field: ", stringify!(__darwin_x86_avx512_state64), "::", stringify!(__fpu_xmm1) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_xmm2) as usize - ptr as usize }, 200usize, concat!( "Offset of field: ", stringify!(__darwin_x86_avx512_state64), "::", stringify!(__fpu_xmm2) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_xmm3) as usize - ptr as usize }, 216usize, concat!( "Offset of field: ", stringify!(__darwin_x86_avx512_state64), "::", stringify!(__fpu_xmm3) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_xmm4) as usize - ptr as usize }, 232usize, concat!( "Offset of field: ", stringify!(__darwin_x86_avx512_state64), "::", stringify!(__fpu_xmm4) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_xmm5) as usize - ptr as usize }, 248usize, concat!( "Offset of field: ", stringify!(__darwin_x86_avx512_state64), "::", stringify!(__fpu_xmm5) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_xmm6) as usize - ptr as usize }, 264usize, concat!( "Offset of field: ", stringify!(__darwin_x86_avx512_state64), "::", stringify!(__fpu_xmm6) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_xmm7) as usize - ptr as usize }, 280usize, concat!( "Offset of field: ", stringify!(__darwin_x86_avx512_state64), "::", stringify!(__fpu_xmm7) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_xmm8) as usize - ptr as usize }, 296usize, concat!( "Offset of field: ", stringify!(__darwin_x86_avx512_state64), "::", stringify!(__fpu_xmm8) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_xmm9) as usize - ptr as usize }, 312usize, concat!( "Offset of field: ", stringify!(__darwin_x86_avx512_state64), "::", stringify!(__fpu_xmm9) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_xmm10) as usize - ptr as usize }, 328usize, concat!( "Offset of field: ", stringify!(__darwin_x86_avx512_state64), "::", stringify!(__fpu_xmm10) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_xmm11) as usize - ptr as usize }, 344usize, concat!( "Offset of field: ", stringify!(__darwin_x86_avx512_state64), "::", stringify!(__fpu_xmm11) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_xmm12) as usize - ptr as usize }, 360usize, concat!( "Offset of field: ", stringify!(__darwin_x86_avx512_state64), "::", stringify!(__fpu_xmm12) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_xmm13) as usize - ptr as usize }, 376usize, concat!( "Offset of field: ", stringify!(__darwin_x86_avx512_state64), "::", stringify!(__fpu_xmm13) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_xmm14) as usize - ptr as usize }, 392usize, concat!( "Offset of field: ", stringify!(__darwin_x86_avx512_state64), "::", stringify!(__fpu_xmm14) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_xmm15) as usize - ptr as usize }, 408usize, concat!( "Offset of field: ", stringify!(__darwin_x86_avx512_state64), "::", stringify!(__fpu_xmm15) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_rsrv4) as usize - ptr as usize }, 424usize, concat!( "Offset of field: ", stringify!(__darwin_x86_avx512_state64), "::", stringify!(__fpu_rsrv4) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_reserved1) as usize - ptr as usize }, 520usize, concat!( "Offset of field: ", stringify!(__darwin_x86_avx512_state64), "::", stringify!(__fpu_reserved1) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__avx_reserved1) as usize - ptr as usize }, 524usize, concat!( "Offset of field: ", stringify!(__darwin_x86_avx512_state64), "::", stringify!(__avx_reserved1) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_ymmh0) as usize - ptr as usize }, 588usize, concat!( "Offset of field: ", stringify!(__darwin_x86_avx512_state64), "::", stringify!(__fpu_ymmh0) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_ymmh1) as usize - ptr as usize }, 604usize, concat!( "Offset of field: ", stringify!(__darwin_x86_avx512_state64), "::", stringify!(__fpu_ymmh1) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_ymmh2) as usize - ptr as usize }, 620usize, concat!( "Offset of field: ", stringify!(__darwin_x86_avx512_state64), "::", stringify!(__fpu_ymmh2) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_ymmh3) as usize - ptr as usize }, 636usize, concat!( "Offset of field: ", stringify!(__darwin_x86_avx512_state64), "::", stringify!(__fpu_ymmh3) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_ymmh4) as usize - ptr as usize }, 652usize, concat!( "Offset of field: ", stringify!(__darwin_x86_avx512_state64), "::", stringify!(__fpu_ymmh4) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_ymmh5) as usize - ptr as usize }, 668usize, concat!( "Offset of field: ", stringify!(__darwin_x86_avx512_state64), "::", stringify!(__fpu_ymmh5) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_ymmh6) as usize - ptr as usize }, 684usize, concat!( "Offset of field: ", stringify!(__darwin_x86_avx512_state64), "::", stringify!(__fpu_ymmh6) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_ymmh7) as usize - ptr as usize }, 700usize, concat!( "Offset of field: ", stringify!(__darwin_x86_avx512_state64), "::", stringify!(__fpu_ymmh7) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_ymmh8) as usize - ptr as usize }, 716usize, concat!( "Offset of field: ", stringify!(__darwin_x86_avx512_state64), "::", stringify!(__fpu_ymmh8) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_ymmh9) as usize - ptr as usize }, 732usize, concat!( "Offset of field: ", stringify!(__darwin_x86_avx512_state64), "::", stringify!(__fpu_ymmh9) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_ymmh10) as usize - ptr as usize }, 748usize, concat!( "Offset of field: ", stringify!(__darwin_x86_avx512_state64), "::", stringify!(__fpu_ymmh10) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_ymmh11) as usize - ptr as usize }, 764usize, concat!( "Offset of field: ", stringify!(__darwin_x86_avx512_state64), "::", stringify!(__fpu_ymmh11) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_ymmh12) as usize - ptr as usize }, 780usize, concat!( "Offset of field: ", stringify!(__darwin_x86_avx512_state64), "::", stringify!(__fpu_ymmh12) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_ymmh13) as usize - ptr as usize }, 796usize, concat!( "Offset of field: ", stringify!(__darwin_x86_avx512_state64), "::", stringify!(__fpu_ymmh13) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_ymmh14) as usize - ptr as usize }, 812usize, concat!( "Offset of field: ", stringify!(__darwin_x86_avx512_state64), "::", stringify!(__fpu_ymmh14) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_ymmh15) as usize - ptr as usize }, 828usize, concat!( "Offset of field: ", stringify!(__darwin_x86_avx512_state64), "::", stringify!(__fpu_ymmh15) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_k0) as usize - ptr as usize }, 844usize, concat!( "Offset of field: ", stringify!(__darwin_x86_avx512_state64), "::", stringify!(__fpu_k0) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_k1) as usize - ptr as usize }, 852usize, concat!( "Offset of field: ", stringify!(__darwin_x86_avx512_state64), "::", stringify!(__fpu_k1) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_k2) as usize - ptr as usize }, 860usize, concat!( "Offset of field: ", stringify!(__darwin_x86_avx512_state64), "::", stringify!(__fpu_k2) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_k3) as usize - ptr as usize }, 868usize, concat!( "Offset of field: ", stringify!(__darwin_x86_avx512_state64), "::", stringify!(__fpu_k3) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_k4) as usize - ptr as usize }, 876usize, concat!( "Offset of field: ", stringify!(__darwin_x86_avx512_state64), "::", stringify!(__fpu_k4) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_k5) as usize - ptr as usize }, 884usize, concat!( "Offset of field: ", stringify!(__darwin_x86_avx512_state64), "::", stringify!(__fpu_k5) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_k6) as usize - ptr as usize }, 892usize, concat!( "Offset of field: ", stringify!(__darwin_x86_avx512_state64), "::", stringify!(__fpu_k6) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_k7) as usize - ptr as usize }, 900usize, concat!( "Offset of field: ", stringify!(__darwin_x86_avx512_state64), "::", stringify!(__fpu_k7) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_zmmh0) as usize - ptr as usize }, 908usize, concat!( "Offset of field: ", stringify!(__darwin_x86_avx512_state64), "::", stringify!(__fpu_zmmh0) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_zmmh1) as usize - ptr as usize }, 940usize, concat!( "Offset of field: ", stringify!(__darwin_x86_avx512_state64), "::", stringify!(__fpu_zmmh1) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_zmmh2) as usize - ptr as usize }, 972usize, concat!( "Offset of field: ", stringify!(__darwin_x86_avx512_state64), "::", stringify!(__fpu_zmmh2) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_zmmh3) as usize - ptr as usize }, 1004usize, concat!( "Offset of field: ", stringify!(__darwin_x86_avx512_state64), "::", stringify!(__fpu_zmmh3) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_zmmh4) as usize - ptr as usize }, 1036usize, concat!( "Offset of field: ", stringify!(__darwin_x86_avx512_state64), "::", stringify!(__fpu_zmmh4) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_zmmh5) as usize - ptr as usize }, 1068usize, concat!( "Offset of field: ", stringify!(__darwin_x86_avx512_state64), "::", stringify!(__fpu_zmmh5) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_zmmh6) as usize - ptr as usize }, 1100usize, concat!( "Offset of field: ", stringify!(__darwin_x86_avx512_state64), "::", stringify!(__fpu_zmmh6) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_zmmh7) as usize - ptr as usize }, 1132usize, concat!( "Offset of field: ", stringify!(__darwin_x86_avx512_state64), "::", stringify!(__fpu_zmmh7) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_zmmh8) as usize - ptr as usize }, 1164usize, concat!( "Offset of field: ", stringify!(__darwin_x86_avx512_state64), "::", stringify!(__fpu_zmmh8) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_zmmh9) as usize - ptr as usize }, 1196usize, concat!( "Offset of field: ", stringify!(__darwin_x86_avx512_state64), "::", stringify!(__fpu_zmmh9) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_zmmh10) as usize - ptr as usize }, 1228usize, concat!( "Offset of field: ", stringify!(__darwin_x86_avx512_state64), "::", stringify!(__fpu_zmmh10) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_zmmh11) as usize - ptr as usize }, 1260usize, concat!( "Offset of field: ", stringify!(__darwin_x86_avx512_state64), "::", stringify!(__fpu_zmmh11) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_zmmh12) as usize - ptr as usize }, 1292usize, concat!( "Offset of field: ", stringify!(__darwin_x86_avx512_state64), "::", stringify!(__fpu_zmmh12) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_zmmh13) as usize - ptr as usize }, 1324usize, concat!( "Offset of field: ", stringify!(__darwin_x86_avx512_state64), "::", stringify!(__fpu_zmmh13) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_zmmh14) as usize - ptr as usize }, 1356usize, concat!( "Offset of field: ", stringify!(__darwin_x86_avx512_state64), "::", stringify!(__fpu_zmmh14) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_zmmh15) as usize - ptr as usize }, 1388usize, concat!( "Offset of field: ", stringify!(__darwin_x86_avx512_state64), "::", stringify!(__fpu_zmmh15) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_zmm16) as usize - ptr as usize }, 1420usize, concat!( "Offset of field: ", stringify!(__darwin_x86_avx512_state64), "::", stringify!(__fpu_zmm16) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_zmm17) as usize - ptr as usize }, 1484usize, concat!( "Offset of field: ", stringify!(__darwin_x86_avx512_state64), "::", stringify!(__fpu_zmm17) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_zmm18) as usize - ptr as usize }, 1548usize, concat!( "Offset of field: ", stringify!(__darwin_x86_avx512_state64), "::", stringify!(__fpu_zmm18) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_zmm19) as usize - ptr as usize }, 1612usize, concat!( "Offset of field: ", stringify!(__darwin_x86_avx512_state64), "::", stringify!(__fpu_zmm19) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_zmm20) as usize - ptr as usize }, 1676usize, concat!( "Offset of field: ", stringify!(__darwin_x86_avx512_state64), "::", stringify!(__fpu_zmm20) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_zmm21) as usize - ptr as usize }, 1740usize, concat!( "Offset of field: ", stringify!(__darwin_x86_avx512_state64), "::", stringify!(__fpu_zmm21) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_zmm22) as usize - ptr as usize }, 1804usize, concat!( "Offset of field: ", stringify!(__darwin_x86_avx512_state64), "::", stringify!(__fpu_zmm22) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_zmm23) as usize - ptr as usize }, 1868usize, concat!( "Offset of field: ", stringify!(__darwin_x86_avx512_state64), "::", stringify!(__fpu_zmm23) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_zmm24) as usize - ptr as usize }, 1932usize, concat!( "Offset of field: ", stringify!(__darwin_x86_avx512_state64), "::", stringify!(__fpu_zmm24) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_zmm25) as usize - ptr as usize }, 1996usize, concat!( "Offset of field: ", stringify!(__darwin_x86_avx512_state64), "::", stringify!(__fpu_zmm25) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_zmm26) as usize - ptr as usize }, 2060usize, concat!( "Offset of field: ", stringify!(__darwin_x86_avx512_state64), "::", stringify!(__fpu_zmm26) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_zmm27) as usize - ptr as usize }, 2124usize, concat!( "Offset of field: ", stringify!(__darwin_x86_avx512_state64), "::", stringify!(__fpu_zmm27) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_zmm28) as usize - ptr as usize }, 2188usize, concat!( "Offset of field: ", stringify!(__darwin_x86_avx512_state64), "::", stringify!(__fpu_zmm28) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_zmm29) as usize - ptr as usize }, 2252usize, concat!( "Offset of field: ", stringify!(__darwin_x86_avx512_state64), "::", stringify!(__fpu_zmm29) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_zmm30) as usize - ptr as usize }, 2316usize, concat!( "Offset of field: ", stringify!(__darwin_x86_avx512_state64), "::", stringify!(__fpu_zmm30) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fpu_zmm31) as usize - ptr as usize }, 2380usize, concat!( "Offset of field: ", stringify!(__darwin_x86_avx512_state64), "::", stringify!(__fpu_zmm31) ) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct __darwin_x86_exception_state64 { pub __trapno: __uint16_t, pub __cpu: __uint16_t, pub __err: __uint32_t, pub __faultvaddr: __uint64_t, } #[test] fn bindgen_test_layout___darwin_x86_exception_state64() { const UNINIT: ::std::mem::MaybeUninit<__darwin_x86_exception_state64> = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::<__darwin_x86_exception_state64>(), 16usize, concat!("Size of: ", stringify!(__darwin_x86_exception_state64)) ); assert_eq!( ::std::mem::align_of::<__darwin_x86_exception_state64>(), 8usize, concat!("Alignment of ", stringify!(__darwin_x86_exception_state64)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__trapno) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(__darwin_x86_exception_state64), "::", stringify!(__trapno) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__cpu) as usize - ptr as usize }, 2usize, concat!( "Offset of field: ", stringify!(__darwin_x86_exception_state64), "::", stringify!(__cpu) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__err) as usize - ptr as usize }, 4usize, concat!( "Offset of field: ", stringify!(__darwin_x86_exception_state64), "::", stringify!(__err) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__faultvaddr) as usize - ptr as usize }, 8usize, concat!( "Offset of field: ", stringify!(__darwin_x86_exception_state64), "::", stringify!(__faultvaddr) ) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct __darwin_x86_debug_state64 { pub __dr0: __uint64_t, pub __dr1: __uint64_t, pub __dr2: __uint64_t, pub __dr3: __uint64_t, pub __dr4: __uint64_t, pub __dr5: __uint64_t, pub __dr6: __uint64_t, pub __dr7: __uint64_t, } #[test] fn bindgen_test_layout___darwin_x86_debug_state64() { const UNINIT: ::std::mem::MaybeUninit<__darwin_x86_debug_state64> = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::<__darwin_x86_debug_state64>(), 64usize, concat!("Size of: ", stringify!(__darwin_x86_debug_state64)) ); assert_eq!( ::std::mem::align_of::<__darwin_x86_debug_state64>(), 8usize, concat!("Alignment of ", stringify!(__darwin_x86_debug_state64)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__dr0) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(__darwin_x86_debug_state64), "::", stringify!(__dr0) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__dr1) as usize - ptr as usize }, 8usize, concat!( "Offset of field: ", stringify!(__darwin_x86_debug_state64), "::", stringify!(__dr1) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__dr2) as usize - ptr as usize }, 16usize, concat!( "Offset of field: ", stringify!(__darwin_x86_debug_state64), "::", stringify!(__dr2) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__dr3) as usize - ptr as usize }, 24usize, concat!( "Offset of field: ", stringify!(__darwin_x86_debug_state64), "::", stringify!(__dr3) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__dr4) as usize - ptr as usize }, 32usize, concat!( "Offset of field: ", stringify!(__darwin_x86_debug_state64), "::", stringify!(__dr4) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__dr5) as usize - ptr as usize }, 40usize, concat!( "Offset of field: ", stringify!(__darwin_x86_debug_state64), "::", stringify!(__dr5) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__dr6) as usize - ptr as usize }, 48usize, concat!( "Offset of field: ", stringify!(__darwin_x86_debug_state64), "::", stringify!(__dr6) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__dr7) as usize - ptr as usize }, 56usize, concat!( "Offset of field: ", stringify!(__darwin_x86_debug_state64), "::", stringify!(__dr7) ) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct __darwin_x86_cpmu_state64 { pub __ctrs: [__uint64_t; 16usize], } #[test] fn bindgen_test_layout___darwin_x86_cpmu_state64() { const UNINIT: ::std::mem::MaybeUninit<__darwin_x86_cpmu_state64> = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::<__darwin_x86_cpmu_state64>(), 128usize, concat!("Size of: ", stringify!(__darwin_x86_cpmu_state64)) ); assert_eq!( ::std::mem::align_of::<__darwin_x86_cpmu_state64>(), 8usize, concat!("Alignment of ", stringify!(__darwin_x86_cpmu_state64)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__ctrs) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(__darwin_x86_cpmu_state64), "::", stringify!(__ctrs) ) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct __darwin_mcontext32 { pub __es: __darwin_i386_exception_state, pub __ss: __darwin_i386_thread_state, pub __fs: __darwin_i386_float_state, } #[test] fn bindgen_test_layout___darwin_mcontext32() { const UNINIT: ::std::mem::MaybeUninit<__darwin_mcontext32> = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::<__darwin_mcontext32>(), 600usize, concat!("Size of: ", stringify!(__darwin_mcontext32)) ); assert_eq!( ::std::mem::align_of::<__darwin_mcontext32>(), 4usize, concat!("Alignment of ", stringify!(__darwin_mcontext32)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__es) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(__darwin_mcontext32), "::", stringify!(__es) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__ss) as usize - ptr as usize }, 12usize, concat!( "Offset of field: ", stringify!(__darwin_mcontext32), "::", stringify!(__ss) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fs) as usize - ptr as usize }, 76usize, concat!( "Offset of field: ", stringify!(__darwin_mcontext32), "::", stringify!(__fs) ) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct __darwin_mcontext_avx32 { pub __es: __darwin_i386_exception_state, pub __ss: __darwin_i386_thread_state, pub __fs: __darwin_i386_avx_state, } #[test] fn bindgen_test_layout___darwin_mcontext_avx32() { const UNINIT: ::std::mem::MaybeUninit<__darwin_mcontext_avx32> = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::<__darwin_mcontext_avx32>(), 792usize, concat!("Size of: ", stringify!(__darwin_mcontext_avx32)) ); assert_eq!( ::std::mem::align_of::<__darwin_mcontext_avx32>(), 4usize, concat!("Alignment of ", stringify!(__darwin_mcontext_avx32)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__es) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(__darwin_mcontext_avx32), "::", stringify!(__es) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__ss) as usize - ptr as usize }, 12usize, concat!( "Offset of field: ", stringify!(__darwin_mcontext_avx32), "::", stringify!(__ss) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fs) as usize - ptr as usize }, 76usize, concat!( "Offset of field: ", stringify!(__darwin_mcontext_avx32), "::", stringify!(__fs) ) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct __darwin_mcontext_avx512_32 { pub __es: __darwin_i386_exception_state, pub __ss: __darwin_i386_thread_state, pub __fs: __darwin_i386_avx512_state, } #[test] fn bindgen_test_layout___darwin_mcontext_avx512_32() { const UNINIT: ::std::mem::MaybeUninit<__darwin_mcontext_avx512_32> = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::<__darwin_mcontext_avx512_32>(), 1112usize, concat!("Size of: ", stringify!(__darwin_mcontext_avx512_32)) ); assert_eq!( ::std::mem::align_of::<__darwin_mcontext_avx512_32>(), 4usize, concat!("Alignment of ", stringify!(__darwin_mcontext_avx512_32)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__es) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(__darwin_mcontext_avx512_32), "::", stringify!(__es) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__ss) as usize - ptr as usize }, 12usize, concat!( "Offset of field: ", stringify!(__darwin_mcontext_avx512_32), "::", stringify!(__ss) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fs) as usize - ptr as usize }, 76usize, concat!( "Offset of field: ", stringify!(__darwin_mcontext_avx512_32), "::", stringify!(__fs) ) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct __darwin_mcontext64 { pub __es: __darwin_x86_exception_state64, pub __ss: __darwin_x86_thread_state64, pub __fs: __darwin_x86_float_state64, } #[test] fn bindgen_test_layout___darwin_mcontext64() { const UNINIT: ::std::mem::MaybeUninit<__darwin_mcontext64> = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::<__darwin_mcontext64>(), 712usize, concat!("Size of: ", stringify!(__darwin_mcontext64)) ); assert_eq!( ::std::mem::align_of::<__darwin_mcontext64>(), 8usize, concat!("Alignment of ", stringify!(__darwin_mcontext64)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__es) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(__darwin_mcontext64), "::", stringify!(__es) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__ss) as usize - ptr as usize }, 16usize, concat!( "Offset of field: ", stringify!(__darwin_mcontext64), "::", stringify!(__ss) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fs) as usize - ptr as usize }, 184usize, concat!( "Offset of field: ", stringify!(__darwin_mcontext64), "::", stringify!(__fs) ) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct __darwin_mcontext64_full { pub __es: __darwin_x86_exception_state64, pub __ss: __darwin_x86_thread_full_state64, pub __fs: __darwin_x86_float_state64, } #[test] fn bindgen_test_layout___darwin_mcontext64_full() { const UNINIT: ::std::mem::MaybeUninit<__darwin_mcontext64_full> = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::<__darwin_mcontext64_full>(), 744usize, concat!("Size of: ", stringify!(__darwin_mcontext64_full)) ); assert_eq!( ::std::mem::align_of::<__darwin_mcontext64_full>(), 8usize, concat!("Alignment of ", stringify!(__darwin_mcontext64_full)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__es) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(__darwin_mcontext64_full), "::", stringify!(__es) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__ss) as usize - ptr as usize }, 16usize, concat!( "Offset of field: ", stringify!(__darwin_mcontext64_full), "::", stringify!(__ss) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fs) as usize - ptr as usize }, 216usize, concat!( "Offset of field: ", stringify!(__darwin_mcontext64_full), "::", stringify!(__fs) ) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct __darwin_mcontext_avx64 { pub __es: __darwin_x86_exception_state64, pub __ss: __darwin_x86_thread_state64, pub __fs: __darwin_x86_avx_state64, } #[test] fn bindgen_test_layout___darwin_mcontext_avx64() { const UNINIT: ::std::mem::MaybeUninit<__darwin_mcontext_avx64> = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::<__darwin_mcontext_avx64>(), 1032usize, concat!("Size of: ", stringify!(__darwin_mcontext_avx64)) ); assert_eq!( ::std::mem::align_of::<__darwin_mcontext_avx64>(), 8usize, concat!("Alignment of ", stringify!(__darwin_mcontext_avx64)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__es) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(__darwin_mcontext_avx64), "::", stringify!(__es) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__ss) as usize - ptr as usize }, 16usize, concat!( "Offset of field: ", stringify!(__darwin_mcontext_avx64), "::", stringify!(__ss) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fs) as usize - ptr as usize }, 184usize, concat!( "Offset of field: ", stringify!(__darwin_mcontext_avx64), "::", stringify!(__fs) ) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct __darwin_mcontext_avx64_full { pub __es: __darwin_x86_exception_state64, pub __ss: __darwin_x86_thread_full_state64, pub __fs: __darwin_x86_avx_state64, } #[test] fn bindgen_test_layout___darwin_mcontext_avx64_full() { const UNINIT: ::std::mem::MaybeUninit<__darwin_mcontext_avx64_full> = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::<__darwin_mcontext_avx64_full>(), 1064usize, concat!("Size of: ", stringify!(__darwin_mcontext_avx64_full)) ); assert_eq!( ::std::mem::align_of::<__darwin_mcontext_avx64_full>(), 8usize, concat!("Alignment of ", stringify!(__darwin_mcontext_avx64_full)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__es) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(__darwin_mcontext_avx64_full), "::", stringify!(__es) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__ss) as usize - ptr as usize }, 16usize, concat!( "Offset of field: ", stringify!(__darwin_mcontext_avx64_full), "::", stringify!(__ss) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fs) as usize - ptr as usize }, 216usize, concat!( "Offset of field: ", stringify!(__darwin_mcontext_avx64_full), "::", stringify!(__fs) ) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct __darwin_mcontext_avx512_64 { pub __es: __darwin_x86_exception_state64, pub __ss: __darwin_x86_thread_state64, pub __fs: __darwin_x86_avx512_state64, } #[test] fn bindgen_test_layout___darwin_mcontext_avx512_64() { const UNINIT: ::std::mem::MaybeUninit<__darwin_mcontext_avx512_64> = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::<__darwin_mcontext_avx512_64>(), 2632usize, concat!("Size of: ", stringify!(__darwin_mcontext_avx512_64)) ); assert_eq!( ::std::mem::align_of::<__darwin_mcontext_avx512_64>(), 8usize, concat!("Alignment of ", stringify!(__darwin_mcontext_avx512_64)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__es) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(__darwin_mcontext_avx512_64), "::", stringify!(__es) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__ss) as usize - ptr as usize }, 16usize, concat!( "Offset of field: ", stringify!(__darwin_mcontext_avx512_64), "::", stringify!(__ss) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fs) as usize - ptr as usize }, 184usize, concat!( "Offset of field: ", stringify!(__darwin_mcontext_avx512_64), "::", stringify!(__fs) ) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct __darwin_mcontext_avx512_64_full { pub __es: __darwin_x86_exception_state64, pub __ss: __darwin_x86_thread_full_state64, pub __fs: __darwin_x86_avx512_state64, } #[test] fn bindgen_test_layout___darwin_mcontext_avx512_64_full() { const UNINIT: ::std::mem::MaybeUninit<__darwin_mcontext_avx512_64_full> = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::<__darwin_mcontext_avx512_64_full>(), 2664usize, concat!("Size of: ", stringify!(__darwin_mcontext_avx512_64_full)) ); assert_eq!( ::std::mem::align_of::<__darwin_mcontext_avx512_64_full>(), 8usize, concat!("Alignment of ", stringify!(__darwin_mcontext_avx512_64_full)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__es) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(__darwin_mcontext_avx512_64_full), "::", stringify!(__es) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__ss) as usize - ptr as usize }, 16usize, concat!( "Offset of field: ", stringify!(__darwin_mcontext_avx512_64_full), "::", stringify!(__ss) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__fs) as usize - ptr as usize }, 216usize, concat!( "Offset of field: ", stringify!(__darwin_mcontext_avx512_64_full), "::", stringify!(__fs) ) ); } pub type mcontext_t = *mut __darwin_mcontext64; #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct __darwin_sigaltstack { pub ss_sp: *mut ::std::os::raw::c_void, pub ss_size: __darwin_size_t, pub ss_flags: ::std::os::raw::c_int, } #[test] fn bindgen_test_layout___darwin_sigaltstack() { const UNINIT: ::std::mem::MaybeUninit<__darwin_sigaltstack> = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::<__darwin_sigaltstack>(), 24usize, concat!("Size of: ", stringify!(__darwin_sigaltstack)) ); assert_eq!( ::std::mem::align_of::<__darwin_sigaltstack>(), 8usize, concat!("Alignment of ", stringify!(__darwin_sigaltstack)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ss_sp) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(__darwin_sigaltstack), "::", stringify!(ss_sp) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ss_size) as usize - ptr as usize }, 8usize, concat!( "Offset of field: ", stringify!(__darwin_sigaltstack), "::", stringify!(ss_size) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ss_flags) as usize - ptr as usize }, 16usize, concat!( "Offset of field: ", stringify!(__darwin_sigaltstack), "::", stringify!(ss_flags) ) ); } pub type stack_t = __darwin_sigaltstack; #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct __darwin_ucontext { pub uc_onstack: ::std::os::raw::c_int, pub uc_sigmask: __darwin_sigset_t, pub uc_stack: __darwin_sigaltstack, pub uc_link: *mut __darwin_ucontext, pub uc_mcsize: __darwin_size_t, pub uc_mcontext: *mut __darwin_mcontext64, } #[test] fn bindgen_test_layout___darwin_ucontext() { const UNINIT: ::std::mem::MaybeUninit<__darwin_ucontext> = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::<__darwin_ucontext>(), 56usize, concat!("Size of: ", stringify!(__darwin_ucontext)) ); assert_eq!( ::std::mem::align_of::<__darwin_ucontext>(), 8usize, concat!("Alignment of ", stringify!(__darwin_ucontext)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).uc_onstack) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(__darwin_ucontext), "::", stringify!(uc_onstack) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).uc_sigmask) as usize - ptr as usize }, 4usize, concat!( "Offset of field: ", stringify!(__darwin_ucontext), "::", stringify!(uc_sigmask) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).uc_stack) as usize - ptr as usize }, 8usize, concat!( "Offset of field: ", stringify!(__darwin_ucontext), "::", stringify!(uc_stack) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).uc_link) as usize - ptr as usize }, 32usize, concat!( "Offset of field: ", stringify!(__darwin_ucontext), "::", stringify!(uc_link) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).uc_mcsize) as usize - ptr as usize }, 40usize, concat!( "Offset of field: ", stringify!(__darwin_ucontext), "::", stringify!(uc_mcsize) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).uc_mcontext) as usize - ptr as usize }, 48usize, concat!( "Offset of field: ", stringify!(__darwin_ucontext), "::", stringify!(uc_mcontext) ) ); } pub type ucontext_t = __darwin_ucontext; pub type sigset_t = __darwin_sigset_t; #[repr(C)] #[derive(Copy, Clone)] pub union sigval { pub sival_int: ::std::os::raw::c_int, pub sival_ptr: *mut ::std::os::raw::c_void, } #[test] fn bindgen_test_layout_sigval() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 8usize, concat!("Size of: ", stringify!(sigval)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(sigval)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).sival_int) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(sigval), "::", stringify!(sival_int)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).sival_ptr) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(sigval), "::", stringify!(sival_ptr)) ); } #[repr(C)] #[derive(Copy, Clone)] pub struct sigevent { pub sigev_notify: ::std::os::raw::c_int, pub sigev_signo: ::std::os::raw::c_int, pub sigev_value: sigval, pub sigev_notify_function: ::std::option::Option, pub sigev_notify_attributes: *mut pthread_attr_t, } #[test] fn bindgen_test_layout_sigevent() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 32usize, concat!("Size of: ", stringify!(sigevent)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(sigevent)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).sigev_notify) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(sigevent), "::", stringify!(sigev_notify) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).sigev_signo) as usize - ptr as usize }, 4usize, concat!("Offset of field: ", stringify!(sigevent), "::", stringify!(sigev_signo)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).sigev_value) as usize - ptr as usize }, 8usize, concat!("Offset of field: ", stringify!(sigevent), "::", stringify!(sigev_value)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).sigev_notify_function) as usize - ptr as usize }, 16usize, concat!( "Offset of field: ", stringify!(sigevent), "::", stringify!(sigev_notify_function) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).sigev_notify_attributes) as usize - ptr as usize }, 24usize, concat!( "Offset of field: ", stringify!(sigevent), "::", stringify!(sigev_notify_attributes) ) ); } #[repr(C)] #[derive(Copy, Clone)] pub struct __siginfo { pub si_signo: ::std::os::raw::c_int, pub si_errno: ::std::os::raw::c_int, pub si_code: ::std::os::raw::c_int, pub si_pid: pid_t, pub si_uid: uid_t, pub si_status: ::std::os::raw::c_int, pub si_addr: *mut ::std::os::raw::c_void, pub si_value: sigval, pub si_band: ::std::os::raw::c_long, pub __pad: [::std::os::raw::c_ulong; 7usize], } #[test] fn bindgen_test_layout___siginfo() { const UNINIT: ::std::mem::MaybeUninit<__siginfo> = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::<__siginfo>(), 104usize, concat!("Size of: ", stringify!(__siginfo)) ); assert_eq!( ::std::mem::align_of::<__siginfo>(), 8usize, concat!("Alignment of ", stringify!(__siginfo)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).si_signo) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(__siginfo), "::", stringify!(si_signo)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).si_errno) as usize - ptr as usize }, 4usize, concat!("Offset of field: ", stringify!(__siginfo), "::", stringify!(si_errno)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).si_code) as usize - ptr as usize }, 8usize, concat!("Offset of field: ", stringify!(__siginfo), "::", stringify!(si_code)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).si_pid) as usize - ptr as usize }, 12usize, concat!("Offset of field: ", stringify!(__siginfo), "::", stringify!(si_pid)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).si_uid) as usize - ptr as usize }, 16usize, concat!("Offset of field: ", stringify!(__siginfo), "::", stringify!(si_uid)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).si_status) as usize - ptr as usize }, 20usize, concat!("Offset of field: ", stringify!(__siginfo), "::", stringify!(si_status)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).si_addr) as usize - ptr as usize }, 24usize, concat!("Offset of field: ", stringify!(__siginfo), "::", stringify!(si_addr)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).si_value) as usize - ptr as usize }, 32usize, concat!("Offset of field: ", stringify!(__siginfo), "::", stringify!(si_value)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).si_band) as usize - ptr as usize }, 40usize, concat!("Offset of field: ", stringify!(__siginfo), "::", stringify!(si_band)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__pad) as usize - ptr as usize }, 48usize, concat!("Offset of field: ", stringify!(__siginfo), "::", stringify!(__pad)) ); } pub type siginfo_t = __siginfo; #[repr(C)] #[derive(Copy, Clone)] pub union __sigaction_u { pub __sa_handler: ::std::option::Option, pub __sa_sigaction: ::std::option::Option< unsafe extern "C" fn(arg1: ::std::os::raw::c_int, arg2: *mut __siginfo, arg3: *mut ::std::os::raw::c_void), >, } #[test] fn bindgen_test_layout___sigaction_u() { const UNINIT: ::std::mem::MaybeUninit<__sigaction_u> = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::<__sigaction_u>(), 8usize, concat!("Size of: ", stringify!(__sigaction_u)) ); assert_eq!( ::std::mem::align_of::<__sigaction_u>(), 8usize, concat!("Alignment of ", stringify!(__sigaction_u)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__sa_handler) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(__sigaction_u), "::", stringify!(__sa_handler) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__sa_sigaction) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(__sigaction_u), "::", stringify!(__sa_sigaction) ) ); } #[repr(C)] #[derive(Copy, Clone)] pub struct __sigaction { pub __sigaction_u: __sigaction_u, pub sa_tramp: ::std::option::Option< unsafe extern "C" fn( arg1: *mut ::std::os::raw::c_void, arg2: ::std::os::raw::c_int, arg3: ::std::os::raw::c_int, arg4: *mut siginfo_t, arg5: *mut ::std::os::raw::c_void, ), >, pub sa_mask: sigset_t, pub sa_flags: ::std::os::raw::c_int, } #[test] fn bindgen_test_layout___sigaction() { const UNINIT: ::std::mem::MaybeUninit<__sigaction> = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::<__sigaction>(), 24usize, concat!("Size of: ", stringify!(__sigaction)) ); assert_eq!( ::std::mem::align_of::<__sigaction>(), 8usize, concat!("Alignment of ", stringify!(__sigaction)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__sigaction_u) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(__sigaction), "::", stringify!(__sigaction_u) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).sa_tramp) as usize - ptr as usize }, 8usize, concat!("Offset of field: ", stringify!(__sigaction), "::", stringify!(sa_tramp)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).sa_mask) as usize - ptr as usize }, 16usize, concat!("Offset of field: ", stringify!(__sigaction), "::", stringify!(sa_mask)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).sa_flags) as usize - ptr as usize }, 20usize, concat!("Offset of field: ", stringify!(__sigaction), "::", stringify!(sa_flags)) ); } #[repr(C)] #[derive(Copy, Clone)] pub struct sigaction { pub __sigaction_u: __sigaction_u, pub sa_mask: sigset_t, pub sa_flags: ::std::os::raw::c_int, } #[test] fn bindgen_test_layout_sigaction() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 16usize, concat!("Size of: ", stringify!(sigaction)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(sigaction)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__sigaction_u) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(sigaction), "::", stringify!(__sigaction_u) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).sa_mask) as usize - ptr as usize }, 8usize, concat!("Offset of field: ", stringify!(sigaction), "::", stringify!(sa_mask)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).sa_flags) as usize - ptr as usize }, 12usize, concat!("Offset of field: ", stringify!(sigaction), "::", stringify!(sa_flags)) ); } pub type sig_t = ::std::option::Option; #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct sigvec { pub sv_handler: ::std::option::Option, pub sv_mask: ::std::os::raw::c_int, pub sv_flags: ::std::os::raw::c_int, } #[test] fn bindgen_test_layout_sigvec() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 16usize, concat!("Size of: ", stringify!(sigvec)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(sigvec)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).sv_handler) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(sigvec), "::", stringify!(sv_handler)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).sv_mask) as usize - ptr as usize }, 8usize, concat!("Offset of field: ", stringify!(sigvec), "::", stringify!(sv_mask)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).sv_flags) as usize - ptr as usize }, 12usize, concat!("Offset of field: ", stringify!(sigvec), "::", stringify!(sv_flags)) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct sigstack { pub ss_sp: *mut ::std::os::raw::c_char, pub ss_onstack: ::std::os::raw::c_int, } #[test] fn bindgen_test_layout_sigstack() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 16usize, concat!("Size of: ", stringify!(sigstack)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(sigstack)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ss_sp) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(sigstack), "::", stringify!(ss_sp)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ss_onstack) as usize - ptr as usize }, 8usize, concat!("Offset of field: ", stringify!(sigstack), "::", stringify!(ss_onstack)) ); } unsafe extern "C" { pub fn signal( arg1: ::std::os::raw::c_int, arg2: ::std::option::Option, ) -> ::std::option::Option< unsafe extern "C" fn( arg1: ::std::os::raw::c_int, arg2: ::std::option::Option, ), >; } #[repr(C)] #[derive(Copy, Clone)] pub struct radix_node { pub rn_mklist: *mut radix_mask, pub rn_parent: *mut radix_node, pub rn_bit: ::std::os::raw::c_short, pub rn_bmask: ::std::os::raw::c_char, pub rn_flags: u_char, pub rn_u: radix_node__bindgen_ty_1, } #[repr(C)] #[derive(Copy, Clone)] pub union radix_node__bindgen_ty_1 { pub rn_leaf: radix_node__bindgen_ty_1__bindgen_ty_1, pub rn_node: radix_node__bindgen_ty_1__bindgen_ty_2, } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct radix_node__bindgen_ty_1__bindgen_ty_1 { pub rn_Key: caddr_t, pub rn_Mask: caddr_t, pub rn_Dupedkey: *mut radix_node, } #[test] fn bindgen_test_layout_radix_node__bindgen_ty_1__bindgen_ty_1() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 24usize, concat!("Size of: ", stringify!(radix_node__bindgen_ty_1__bindgen_ty_1)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(radix_node__bindgen_ty_1__bindgen_ty_1)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rn_Key) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(radix_node__bindgen_ty_1__bindgen_ty_1), "::", stringify!(rn_Key) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rn_Mask) as usize - ptr as usize }, 8usize, concat!( "Offset of field: ", stringify!(radix_node__bindgen_ty_1__bindgen_ty_1), "::", stringify!(rn_Mask) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rn_Dupedkey) as usize - ptr as usize }, 16usize, concat!( "Offset of field: ", stringify!(radix_node__bindgen_ty_1__bindgen_ty_1), "::", stringify!(rn_Dupedkey) ) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct radix_node__bindgen_ty_1__bindgen_ty_2 { pub rn_Off: ::std::os::raw::c_int, pub rn_L: *mut radix_node, pub rn_R: *mut radix_node, } #[test] fn bindgen_test_layout_radix_node__bindgen_ty_1__bindgen_ty_2() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 24usize, concat!("Size of: ", stringify!(radix_node__bindgen_ty_1__bindgen_ty_2)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(radix_node__bindgen_ty_1__bindgen_ty_2)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rn_Off) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(radix_node__bindgen_ty_1__bindgen_ty_2), "::", stringify!(rn_Off) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rn_L) as usize - ptr as usize }, 8usize, concat!( "Offset of field: ", stringify!(radix_node__bindgen_ty_1__bindgen_ty_2), "::", stringify!(rn_L) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rn_R) as usize - ptr as usize }, 16usize, concat!( "Offset of field: ", stringify!(radix_node__bindgen_ty_1__bindgen_ty_2), "::", stringify!(rn_R) ) ); } #[test] fn bindgen_test_layout_radix_node__bindgen_ty_1() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 24usize, concat!("Size of: ", stringify!(radix_node__bindgen_ty_1)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(radix_node__bindgen_ty_1)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rn_leaf) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(radix_node__bindgen_ty_1), "::", stringify!(rn_leaf) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rn_node) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(radix_node__bindgen_ty_1), "::", stringify!(rn_node) ) ); } #[test] fn bindgen_test_layout_radix_node() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 48usize, concat!("Size of: ", stringify!(radix_node)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(radix_node)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rn_mklist) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(radix_node), "::", stringify!(rn_mklist)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rn_parent) as usize - ptr as usize }, 8usize, concat!("Offset of field: ", stringify!(radix_node), "::", stringify!(rn_parent)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rn_bit) as usize - ptr as usize }, 16usize, concat!("Offset of field: ", stringify!(radix_node), "::", stringify!(rn_bit)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rn_bmask) as usize - ptr as usize }, 18usize, concat!("Offset of field: ", stringify!(radix_node), "::", stringify!(rn_bmask)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rn_flags) as usize - ptr as usize }, 19usize, concat!("Offset of field: ", stringify!(radix_node), "::", stringify!(rn_flags)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rn_u) as usize - ptr as usize }, 24usize, concat!("Offset of field: ", stringify!(radix_node), "::", stringify!(rn_u)) ); } #[repr(C)] #[derive(Copy, Clone)] pub struct radix_mask { pub rm_bit: ::std::os::raw::c_short, pub rm_unused: ::std::os::raw::c_char, pub rm_flags: u_char, pub rm_mklist: *mut radix_mask, pub rm_rmu: radix_mask__bindgen_ty_1, pub rm_refs: ::std::os::raw::c_int, } #[repr(C)] #[derive(Copy, Clone)] pub union radix_mask__bindgen_ty_1 { pub rmu_mask: caddr_t, pub rmu_leaf: *mut radix_node, } #[test] fn bindgen_test_layout_radix_mask__bindgen_ty_1() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 8usize, concat!("Size of: ", stringify!(radix_mask__bindgen_ty_1)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(radix_mask__bindgen_ty_1)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rmu_mask) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(radix_mask__bindgen_ty_1), "::", stringify!(rmu_mask) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rmu_leaf) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(radix_mask__bindgen_ty_1), "::", stringify!(rmu_leaf) ) ); } #[test] fn bindgen_test_layout_radix_mask() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 32usize, concat!("Size of: ", stringify!(radix_mask)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(radix_mask)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rm_bit) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(radix_mask), "::", stringify!(rm_bit)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rm_unused) as usize - ptr as usize }, 2usize, concat!("Offset of field: ", stringify!(radix_mask), "::", stringify!(rm_unused)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rm_flags) as usize - ptr as usize }, 3usize, concat!("Offset of field: ", stringify!(radix_mask), "::", stringify!(rm_flags)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rm_mklist) as usize - ptr as usize }, 8usize, concat!("Offset of field: ", stringify!(radix_mask), "::", stringify!(rm_mklist)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rm_rmu) as usize - ptr as usize }, 16usize, concat!("Offset of field: ", stringify!(radix_mask), "::", stringify!(rm_rmu)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rm_refs) as usize - ptr as usize }, 24usize, concat!("Offset of field: ", stringify!(radix_mask), "::", stringify!(rm_refs)) ); } pub type walktree_f_t = ::std::option::Option< unsafe extern "C" fn(arg1: *mut radix_node, arg2: *mut ::std::os::raw::c_void) -> ::std::os::raw::c_int, >; pub type rn_matchf_t = ::std::option::Option< unsafe extern "C" fn(arg1: *mut radix_node, arg2: *mut ::std::os::raw::c_void) -> ::std::os::raw::c_int, >; #[repr(C)] #[derive(Copy, Clone)] pub struct radix_node_head { pub rnh_treetop: *mut radix_node, pub rnh_addrsize: ::std::os::raw::c_int, pub rnh_pktsize: ::std::os::raw::c_int, pub rnh_addaddr: ::std::option::Option< unsafe extern "C" fn( v: *mut ::std::os::raw::c_void, mask: *mut ::std::os::raw::c_void, head: *mut radix_node_head, nodes: *mut radix_node, ) -> *mut radix_node, >, pub rnh_addpkt: ::std::option::Option< unsafe extern "C" fn( v: *mut ::std::os::raw::c_void, mask: *mut ::std::os::raw::c_void, head: *mut radix_node_head, nodes: *mut radix_node, ) -> *mut radix_node, >, pub rnh_deladdr: ::std::option::Option< unsafe extern "C" fn( v: *mut ::std::os::raw::c_void, mask: *mut ::std::os::raw::c_void, head: *mut radix_node_head, ) -> *mut radix_node, >, pub rnh_delpkt: ::std::option::Option< unsafe extern "C" fn( v: *mut ::std::os::raw::c_void, mask: *mut ::std::os::raw::c_void, head: *mut radix_node_head, ) -> *mut radix_node, >, pub rnh_matchaddr: ::std::option::Option< unsafe extern "C" fn(v: *mut ::std::os::raw::c_void, head: *mut radix_node_head) -> *mut radix_node, >, pub rnh_matchaddr_args: ::std::option::Option< unsafe extern "C" fn( v: *mut ::std::os::raw::c_void, head: *mut radix_node_head, f: rn_matchf_t, w: *mut ::std::os::raw::c_void, ) -> *mut radix_node, >, pub rnh_lookup: ::std::option::Option< unsafe extern "C" fn( v: *mut ::std::os::raw::c_void, mask: *mut ::std::os::raw::c_void, head: *mut radix_node_head, ) -> *mut radix_node, >, pub rnh_lookup_args: ::std::option::Option< unsafe extern "C" fn( v: *mut ::std::os::raw::c_void, mask: *mut ::std::os::raw::c_void, head: *mut radix_node_head, f: rn_matchf_t, arg1: *mut ::std::os::raw::c_void, ) -> *mut radix_node, >, pub rnh_matchpkt: ::std::option::Option< unsafe extern "C" fn(v: *mut ::std::os::raw::c_void, head: *mut radix_node_head) -> *mut radix_node, >, pub rnh_walktree: ::std::option::Option< unsafe extern "C" fn( head: *mut radix_node_head, f: walktree_f_t, w: *mut ::std::os::raw::c_void, ) -> ::std::os::raw::c_int, >, pub rnh_walktree_from: ::std::option::Option< unsafe extern "C" fn( head: *mut radix_node_head, a: *mut ::std::os::raw::c_void, m: *mut ::std::os::raw::c_void, f: walktree_f_t, w: *mut ::std::os::raw::c_void, ) -> ::std::os::raw::c_int, >, pub rnh_close: ::std::option::Option, pub rnh_nodes: [radix_node; 3usize], pub rnh_cnt: ::std::os::raw::c_int, } #[test] fn bindgen_test_layout_radix_node_head() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 264usize, concat!("Size of: ", stringify!(radix_node_head)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(radix_node_head)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rnh_treetop) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(radix_node_head), "::", stringify!(rnh_treetop) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rnh_addrsize) as usize - ptr as usize }, 8usize, concat!( "Offset of field: ", stringify!(radix_node_head), "::", stringify!(rnh_addrsize) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rnh_pktsize) as usize - ptr as usize }, 12usize, concat!( "Offset of field: ", stringify!(radix_node_head), "::", stringify!(rnh_pktsize) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rnh_addaddr) as usize - ptr as usize }, 16usize, concat!( "Offset of field: ", stringify!(radix_node_head), "::", stringify!(rnh_addaddr) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rnh_addpkt) as usize - ptr as usize }, 24usize, concat!( "Offset of field: ", stringify!(radix_node_head), "::", stringify!(rnh_addpkt) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rnh_deladdr) as usize - ptr as usize }, 32usize, concat!( "Offset of field: ", stringify!(radix_node_head), "::", stringify!(rnh_deladdr) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rnh_delpkt) as usize - ptr as usize }, 40usize, concat!( "Offset of field: ", stringify!(radix_node_head), "::", stringify!(rnh_delpkt) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rnh_matchaddr) as usize - ptr as usize }, 48usize, concat!( "Offset of field: ", stringify!(radix_node_head), "::", stringify!(rnh_matchaddr) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rnh_matchaddr_args) as usize - ptr as usize }, 56usize, concat!( "Offset of field: ", stringify!(radix_node_head), "::", stringify!(rnh_matchaddr_args) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rnh_lookup) as usize - ptr as usize }, 64usize, concat!( "Offset of field: ", stringify!(radix_node_head), "::", stringify!(rnh_lookup) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rnh_lookup_args) as usize - ptr as usize }, 72usize, concat!( "Offset of field: ", stringify!(radix_node_head), "::", stringify!(rnh_lookup_args) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rnh_matchpkt) as usize - ptr as usize }, 80usize, concat!( "Offset of field: ", stringify!(radix_node_head), "::", stringify!(rnh_matchpkt) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rnh_walktree) as usize - ptr as usize }, 88usize, concat!( "Offset of field: ", stringify!(radix_node_head), "::", stringify!(rnh_walktree) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rnh_walktree_from) as usize - ptr as usize }, 96usize, concat!( "Offset of field: ", stringify!(radix_node_head), "::", stringify!(rnh_walktree_from) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rnh_close) as usize - ptr as usize }, 104usize, concat!( "Offset of field: ", stringify!(radix_node_head), "::", stringify!(rnh_close) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rnh_nodes) as usize - ptr as usize }, 112usize, concat!( "Offset of field: ", stringify!(radix_node_head), "::", stringify!(rnh_nodes) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rnh_cnt) as usize - ptr as usize }, 256usize, concat!( "Offset of field: ", stringify!(radix_node_head), "::", stringify!(rnh_cnt) ) ); } unsafe extern "C" { pub fn rn_init(); } unsafe extern "C" { pub fn rn_inithead(arg1: *mut *mut ::std::os::raw::c_void, arg2: ::std::os::raw::c_int) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn rn_refines(arg1: *mut ::std::os::raw::c_void, arg2: *mut ::std::os::raw::c_void) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn rn_addmask( arg1: *mut ::std::os::raw::c_void, arg2: ::std::os::raw::c_int, arg3: ::std::os::raw::c_int, ) -> *mut radix_node; } unsafe extern "C" { pub fn rn_addroute( arg1: *mut ::std::os::raw::c_void, arg2: *mut ::std::os::raw::c_void, arg3: *mut radix_node_head, arg4: *mut radix_node, ) -> *mut radix_node; } unsafe extern "C" { pub fn rn_delete( arg1: *mut ::std::os::raw::c_void, arg2: *mut ::std::os::raw::c_void, arg3: *mut radix_node_head, ) -> *mut radix_node; } unsafe extern "C" { pub fn rn_lookup( v_arg: *mut ::std::os::raw::c_void, m_arg: *mut ::std::os::raw::c_void, head: *mut radix_node_head, ) -> *mut radix_node; } unsafe extern "C" { pub fn rn_lookup_args( v_arg: *mut ::std::os::raw::c_void, m_arg: *mut ::std::os::raw::c_void, head: *mut radix_node_head, arg1: rn_matchf_t, arg2: *mut ::std::os::raw::c_void, ) -> *mut radix_node; } unsafe extern "C" { pub fn rn_match(arg1: *mut ::std::os::raw::c_void, arg2: *mut radix_node_head) -> *mut radix_node; } unsafe extern "C" { pub fn rn_match_args( arg1: *mut ::std::os::raw::c_void, arg2: *mut radix_node_head, arg3: rn_matchf_t, arg4: *mut ::std::os::raw::c_void, ) -> *mut radix_node; } pub type int_least8_t = i8; pub type int_least16_t = i16; pub type int_least32_t = i32; pub type int_least64_t = i64; pub type uint_least8_t = u8; pub type uint_least16_t = u16; pub type uint_least32_t = u32; pub type uint_least64_t = u64; pub type int_fast8_t = i8; pub type int_fast16_t = i16; pub type int_fast32_t = i32; pub type int_fast64_t = i64; pub type uint_fast8_t = u8; pub type uint_fast16_t = u16; pub type uint_fast32_t = u32; pub type uint_fast64_t = u64; pub type intmax_t = ::std::os::raw::c_long; pub type uintmax_t = ::std::os::raw::c_ulong; pub type uuid_t = __darwin_uuid_t; pub type uuid_string_t = __darwin_uuid_string_t; unsafe extern "C" { pub static UUID_NULL: uuid_t; } unsafe extern "C" { pub fn uuid_clear(uu: *mut ::std::os::raw::c_uchar); } unsafe extern "C" { pub fn uuid_compare(uu1: *mut ::std::os::raw::c_uchar, uu2: *mut ::std::os::raw::c_uchar) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn uuid_copy(dst: *mut ::std::os::raw::c_uchar, src: *mut ::std::os::raw::c_uchar); } unsafe extern "C" { pub fn uuid_generate(out: *mut ::std::os::raw::c_uchar); } unsafe extern "C" { pub fn uuid_generate_random(out: *mut ::std::os::raw::c_uchar); } unsafe extern "C" { pub fn uuid_generate_time(out: *mut ::std::os::raw::c_uchar); } unsafe extern "C" { pub fn uuid_generate_early_random(out: *mut ::std::os::raw::c_uchar); } unsafe extern "C" { pub fn uuid_is_null(uu: *mut ::std::os::raw::c_uchar) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn uuid_parse(in_: *mut ::std::os::raw::c_char, uu: *mut ::std::os::raw::c_uchar) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn uuid_unparse(uu: *mut ::std::os::raw::c_uchar, out: *mut ::std::os::raw::c_char); } unsafe extern "C" { pub fn uuid_unparse_lower(uu: *mut ::std::os::raw::c_uchar, out: *mut ::std::os::raw::c_char); } unsafe extern "C" { pub fn uuid_unparse_upper(uu: *mut ::std::os::raw::c_uchar, out: *mut ::std::os::raw::c_char); } pub type sa_family_t = __uint8_t; pub type socklen_t = __darwin_socklen_t; #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct iovec { pub iov_base: *mut ::std::os::raw::c_void, pub iov_len: usize, } #[test] fn bindgen_test_layout_iovec() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 16usize, concat!("Size of: ", stringify!(iovec)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(iovec)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).iov_base) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(iovec), "::", stringify!(iov_base)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).iov_len) as usize - ptr as usize }, 8usize, concat!("Offset of field: ", stringify!(iovec), "::", stringify!(iov_len)) ); } unsafe extern "C" { pub static sotc_by_netservicetype: [::std::os::raw::c_int; 9usize]; } pub type sae_associd_t = __uint32_t; pub type sae_connid_t = __uint32_t; #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct sa_endpoints { pub sae_srcif: ::std::os::raw::c_uint, pub sae_srcaddr: *const sockaddr, pub sae_srcaddrlen: socklen_t, pub sae_dstaddr: *const sockaddr, pub sae_dstaddrlen: socklen_t, } #[test] fn bindgen_test_layout_sa_endpoints() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 40usize, concat!("Size of: ", stringify!(sa_endpoints)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(sa_endpoints)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).sae_srcif) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(sa_endpoints), "::", stringify!(sae_srcif) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).sae_srcaddr) as usize - ptr as usize }, 8usize, concat!( "Offset of field: ", stringify!(sa_endpoints), "::", stringify!(sae_srcaddr) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).sae_srcaddrlen) as usize - ptr as usize }, 16usize, concat!( "Offset of field: ", stringify!(sa_endpoints), "::", stringify!(sae_srcaddrlen) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).sae_dstaddr) as usize - ptr as usize }, 24usize, concat!( "Offset of field: ", stringify!(sa_endpoints), "::", stringify!(sae_dstaddr) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).sae_dstaddrlen) as usize - ptr as usize }, 32usize, concat!( "Offset of field: ", stringify!(sa_endpoints), "::", stringify!(sae_dstaddrlen) ) ); } pub type sa_endpoints_t = sa_endpoints; #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct linger { pub l_onoff: ::std::os::raw::c_int, pub l_linger: ::std::os::raw::c_int, } #[test] fn bindgen_test_layout_linger() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 8usize, concat!("Size of: ", stringify!(linger)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(linger)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).l_onoff) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(linger), "::", stringify!(l_onoff)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).l_linger) as usize - ptr as usize }, 4usize, concat!("Offset of field: ", stringify!(linger), "::", stringify!(l_linger)) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct so_np_extensions { pub npx_flags: u_int32_t, pub npx_mask: u_int32_t, } #[test] fn bindgen_test_layout_so_np_extensions() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 8usize, concat!("Size of: ", stringify!(so_np_extensions)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(so_np_extensions)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).npx_flags) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(so_np_extensions), "::", stringify!(npx_flags) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).npx_mask) as usize - ptr as usize }, 4usize, concat!( "Offset of field: ", stringify!(so_np_extensions), "::", stringify!(npx_mask) ) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct sockaddr { pub sa_len: __uint8_t, pub sa_family: sa_family_t, pub sa_data: [::std::os::raw::c_char; 14usize], } #[test] fn bindgen_test_layout_sockaddr() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 16usize, concat!("Size of: ", stringify!(sockaddr)) ); assert_eq!( ::std::mem::align_of::(), 1usize, concat!("Alignment of ", stringify!(sockaddr)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).sa_len) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(sockaddr), "::", stringify!(sa_len)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).sa_family) as usize - ptr as usize }, 1usize, concat!("Offset of field: ", stringify!(sockaddr), "::", stringify!(sa_family)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).sa_data) as usize - ptr as usize }, 2usize, concat!("Offset of field: ", stringify!(sockaddr), "::", stringify!(sa_data)) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct sockproto { pub sp_family: __uint16_t, pub sp_protocol: __uint16_t, } #[test] fn bindgen_test_layout_sockproto() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 4usize, concat!("Size of: ", stringify!(sockproto)) ); assert_eq!( ::std::mem::align_of::(), 2usize, concat!("Alignment of ", stringify!(sockproto)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).sp_family) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(sockproto), "::", stringify!(sp_family)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).sp_protocol) as usize - ptr as usize }, 2usize, concat!( "Offset of field: ", stringify!(sockproto), "::", stringify!(sp_protocol) ) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct sockaddr_storage { pub ss_len: __uint8_t, pub ss_family: sa_family_t, pub __ss_pad1: [::std::os::raw::c_char; 6usize], pub __ss_align: __int64_t, pub __ss_pad2: [::std::os::raw::c_char; 112usize], } #[test] fn bindgen_test_layout_sockaddr_storage() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 128usize, concat!("Size of: ", stringify!(sockaddr_storage)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(sockaddr_storage)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ss_len) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(sockaddr_storage), "::", stringify!(ss_len) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ss_family) as usize - ptr as usize }, 1usize, concat!( "Offset of field: ", stringify!(sockaddr_storage), "::", stringify!(ss_family) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__ss_pad1) as usize - ptr as usize }, 2usize, concat!( "Offset of field: ", stringify!(sockaddr_storage), "::", stringify!(__ss_pad1) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__ss_align) as usize - ptr as usize }, 8usize, concat!( "Offset of field: ", stringify!(sockaddr_storage), "::", stringify!(__ss_align) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__ss_pad2) as usize - ptr as usize }, 16usize, concat!( "Offset of field: ", stringify!(sockaddr_storage), "::", stringify!(__ss_pad2) ) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct msghdr { pub msg_name: *mut ::std::os::raw::c_void, pub msg_namelen: socklen_t, pub msg_iov: *mut iovec, pub msg_iovlen: ::std::os::raw::c_int, pub msg_control: *mut ::std::os::raw::c_void, pub msg_controllen: socklen_t, pub msg_flags: ::std::os::raw::c_int, } #[test] fn bindgen_test_layout_msghdr() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 48usize, concat!("Size of: ", stringify!(msghdr)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(msghdr)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).msg_name) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(msghdr), "::", stringify!(msg_name)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).msg_namelen) as usize - ptr as usize }, 8usize, concat!("Offset of field: ", stringify!(msghdr), "::", stringify!(msg_namelen)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).msg_iov) as usize - ptr as usize }, 16usize, concat!("Offset of field: ", stringify!(msghdr), "::", stringify!(msg_iov)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).msg_iovlen) as usize - ptr as usize }, 24usize, concat!("Offset of field: ", stringify!(msghdr), "::", stringify!(msg_iovlen)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).msg_control) as usize - ptr as usize }, 32usize, concat!("Offset of field: ", stringify!(msghdr), "::", stringify!(msg_control)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).msg_controllen) as usize - ptr as usize }, 40usize, concat!( "Offset of field: ", stringify!(msghdr), "::", stringify!(msg_controllen) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).msg_flags) as usize - ptr as usize }, 44usize, concat!("Offset of field: ", stringify!(msghdr), "::", stringify!(msg_flags)) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct msghdr_x { pub msg_name: *mut ::std::os::raw::c_void, pub msg_namelen: socklen_t, pub msg_iov: *mut iovec, pub msg_iovlen: ::std::os::raw::c_int, pub msg_control: *mut ::std::os::raw::c_void, pub msg_controllen: socklen_t, pub msg_flags: ::std::os::raw::c_int, pub msg_datalen: usize, } #[test] fn bindgen_test_layout_msghdr_x() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 56usize, concat!("Size of: ", stringify!(msghdr_x)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(msghdr_x)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).msg_name) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(msghdr_x), "::", stringify!(msg_name)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).msg_namelen) as usize - ptr as usize }, 8usize, concat!("Offset of field: ", stringify!(msghdr_x), "::", stringify!(msg_namelen)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).msg_iov) as usize - ptr as usize }, 16usize, concat!("Offset of field: ", stringify!(msghdr_x), "::", stringify!(msg_iov)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).msg_iovlen) as usize - ptr as usize }, 24usize, concat!("Offset of field: ", stringify!(msghdr_x), "::", stringify!(msg_iovlen)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).msg_control) as usize - ptr as usize }, 32usize, concat!("Offset of field: ", stringify!(msghdr_x), "::", stringify!(msg_control)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).msg_controllen) as usize - ptr as usize }, 40usize, concat!( "Offset of field: ", stringify!(msghdr_x), "::", stringify!(msg_controllen) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).msg_flags) as usize - ptr as usize }, 44usize, concat!("Offset of field: ", stringify!(msghdr_x), "::", stringify!(msg_flags)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).msg_datalen) as usize - ptr as usize }, 48usize, concat!("Offset of field: ", stringify!(msghdr_x), "::", stringify!(msg_datalen)) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct cmsghdr { pub cmsg_len: socklen_t, pub cmsg_level: ::std::os::raw::c_int, pub cmsg_type: ::std::os::raw::c_int, } #[test] fn bindgen_test_layout_cmsghdr() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 12usize, concat!("Size of: ", stringify!(cmsghdr)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(cmsghdr)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).cmsg_len) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(cmsghdr), "::", stringify!(cmsg_len)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).cmsg_level) as usize - ptr as usize }, 4usize, concat!("Offset of field: ", stringify!(cmsghdr), "::", stringify!(cmsg_level)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).cmsg_type) as usize - ptr as usize }, 8usize, concat!("Offset of field: ", stringify!(cmsghdr), "::", stringify!(cmsg_type)) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct sf_hdtr { pub headers: *mut iovec, pub hdr_cnt: ::std::os::raw::c_int, pub trailers: *mut iovec, pub trl_cnt: ::std::os::raw::c_int, } #[test] fn bindgen_test_layout_sf_hdtr() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 32usize, concat!("Size of: ", stringify!(sf_hdtr)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(sf_hdtr)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).headers) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(sf_hdtr), "::", stringify!(headers)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).hdr_cnt) as usize - ptr as usize }, 8usize, concat!("Offset of field: ", stringify!(sf_hdtr), "::", stringify!(hdr_cnt)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).trailers) as usize - ptr as usize }, 16usize, concat!("Offset of field: ", stringify!(sf_hdtr), "::", stringify!(trailers)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).trl_cnt) as usize - ptr as usize }, 24usize, concat!("Offset of field: ", stringify!(sf_hdtr), "::", stringify!(trl_cnt)) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct so_aidreq { pub sar_cnt: __uint32_t, pub sar_aidp: *mut sae_associd_t, } #[test] fn bindgen_test_layout_so_aidreq() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 16usize, concat!("Size of: ", stringify!(so_aidreq)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(so_aidreq)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).sar_cnt) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(so_aidreq), "::", stringify!(sar_cnt)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).sar_aidp) as usize - ptr as usize }, 8usize, concat!("Offset of field: ", stringify!(so_aidreq), "::", stringify!(sar_aidp)) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct so_cidreq { pub scr_aid: sae_associd_t, pub scr_cnt: __uint32_t, pub scr_cidp: *mut sae_connid_t, } #[test] fn bindgen_test_layout_so_cidreq() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 16usize, concat!("Size of: ", stringify!(so_cidreq)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(so_cidreq)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).scr_aid) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(so_cidreq), "::", stringify!(scr_aid)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).scr_cnt) as usize - ptr as usize }, 4usize, concat!("Offset of field: ", stringify!(so_cidreq), "::", stringify!(scr_cnt)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).scr_cidp) as usize - ptr as usize }, 8usize, concat!("Offset of field: ", stringify!(so_cidreq), "::", stringify!(scr_cidp)) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct so_cinforeq { pub scir_cid: sae_connid_t, pub scir_flags: __uint32_t, pub scir_ifindex: __uint32_t, pub scir_error: __int32_t, pub scir_src: *mut sockaddr, pub scir_src_len: socklen_t, pub scir_dst: *mut sockaddr, pub scir_dst_len: socklen_t, pub scir_aux_type: __uint32_t, pub scir_aux_data: *mut ::std::os::raw::c_void, pub scir_aux_len: __uint32_t, } #[test] fn bindgen_test_layout_so_cinforeq() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 64usize, concat!("Size of: ", stringify!(so_cinforeq)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(so_cinforeq)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).scir_cid) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(so_cinforeq), "::", stringify!(scir_cid)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).scir_flags) as usize - ptr as usize }, 4usize, concat!( "Offset of field: ", stringify!(so_cinforeq), "::", stringify!(scir_flags) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).scir_ifindex) as usize - ptr as usize }, 8usize, concat!( "Offset of field: ", stringify!(so_cinforeq), "::", stringify!(scir_ifindex) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).scir_error) as usize - ptr as usize }, 12usize, concat!( "Offset of field: ", stringify!(so_cinforeq), "::", stringify!(scir_error) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).scir_src) as usize - ptr as usize }, 16usize, concat!("Offset of field: ", stringify!(so_cinforeq), "::", stringify!(scir_src)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).scir_src_len) as usize - ptr as usize }, 24usize, concat!( "Offset of field: ", stringify!(so_cinforeq), "::", stringify!(scir_src_len) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).scir_dst) as usize - ptr as usize }, 32usize, concat!("Offset of field: ", stringify!(so_cinforeq), "::", stringify!(scir_dst)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).scir_dst_len) as usize - ptr as usize }, 40usize, concat!( "Offset of field: ", stringify!(so_cinforeq), "::", stringify!(scir_dst_len) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).scir_aux_type) as usize - ptr as usize }, 44usize, concat!( "Offset of field: ", stringify!(so_cinforeq), "::", stringify!(scir_aux_type) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).scir_aux_data) as usize - ptr as usize }, 48usize, concat!( "Offset of field: ", stringify!(so_cinforeq), "::", stringify!(scir_aux_data) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).scir_aux_len) as usize - ptr as usize }, 56usize, concat!( "Offset of field: ", stringify!(so_cinforeq), "::", stringify!(scir_aux_len) ) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct so_cordreq { pub sco_cid: sae_connid_t, pub sco_rank: __uint32_t, } #[test] fn bindgen_test_layout_so_cordreq() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 8usize, concat!("Size of: ", stringify!(so_cordreq)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(so_cordreq)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).sco_cid) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(so_cordreq), "::", stringify!(sco_cid)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).sco_rank) as usize - ptr as usize }, 4usize, concat!("Offset of field: ", stringify!(so_cordreq), "::", stringify!(sco_rank)) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct netpolicy_event_data { pub eupid: __uint64_t, pub epid: __uint64_t, pub euuid: uuid_t, } #[test] fn bindgen_test_layout_netpolicy_event_data() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 32usize, concat!("Size of: ", stringify!(netpolicy_event_data)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(netpolicy_event_data)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).eupid) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(netpolicy_event_data), "::", stringify!(eupid) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).epid) as usize - ptr as usize }, 8usize, concat!( "Offset of field: ", stringify!(netpolicy_event_data), "::", stringify!(epid) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).euuid) as usize - ptr as usize }, 16usize, concat!( "Offset of field: ", stringify!(netpolicy_event_data), "::", stringify!(euuid) ) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct kev_netpolicy_ifdenied { pub ev_data: netpolicy_event_data, pub ev_if_functional_type: __uint32_t, } #[test] fn bindgen_test_layout_kev_netpolicy_ifdenied() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 40usize, concat!("Size of: ", stringify!(kev_netpolicy_ifdenied)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(kev_netpolicy_ifdenied)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ev_data) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(kev_netpolicy_ifdenied), "::", stringify!(ev_data) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ev_if_functional_type) as usize - ptr as usize }, 32usize, concat!( "Offset of field: ", stringify!(kev_netpolicy_ifdenied), "::", stringify!(ev_if_functional_type) ) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct kev_netpolicy_netdenied { pub ev_data: netpolicy_event_data, pub ev_network_type: __uint32_t, } #[test] fn bindgen_test_layout_kev_netpolicy_netdenied() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 40usize, concat!("Size of: ", stringify!(kev_netpolicy_netdenied)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(kev_netpolicy_netdenied)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ev_data) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(kev_netpolicy_netdenied), "::", stringify!(ev_data) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ev_network_type) as usize - ptr as usize }, 32usize, concat!( "Offset of field: ", stringify!(kev_netpolicy_netdenied), "::", stringify!(ev_network_type) ) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct netsvctype_dscp_map { pub netsvctype: ::std::os::raw::c_int, pub dscp: u_int8_t, } #[test] fn bindgen_test_layout_netsvctype_dscp_map() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 8usize, concat!("Size of: ", stringify!(netsvctype_dscp_map)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(netsvctype_dscp_map)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).netsvctype) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(netsvctype_dscp_map), "::", stringify!(netsvctype) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).dscp) as usize - ptr as usize }, 4usize, concat!( "Offset of field: ", stringify!(netsvctype_dscp_map), "::", stringify!(dscp) ) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct so_mpkl_send_info { pub mpkl_uuid: uuid_t, pub mpkl_proto: __uint8_t, } #[test] fn bindgen_test_layout_so_mpkl_send_info() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 17usize, concat!("Size of: ", stringify!(so_mpkl_send_info)) ); assert_eq!( ::std::mem::align_of::(), 1usize, concat!("Alignment of ", stringify!(so_mpkl_send_info)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).mpkl_uuid) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(so_mpkl_send_info), "::", stringify!(mpkl_uuid) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).mpkl_proto) as usize - ptr as usize }, 16usize, concat!( "Offset of field: ", stringify!(so_mpkl_send_info), "::", stringify!(mpkl_proto) ) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct so_mpkl_recv_info { pub mpkl_seq: __uint32_t, pub mpkl_proto: __uint8_t, } #[test] fn bindgen_test_layout_so_mpkl_recv_info() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 8usize, concat!("Size of: ", stringify!(so_mpkl_recv_info)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(so_mpkl_recv_info)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).mpkl_seq) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(so_mpkl_recv_info), "::", stringify!(mpkl_seq) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).mpkl_proto) as usize - ptr as usize }, 4usize, concat!( "Offset of field: ", stringify!(so_mpkl_recv_info), "::", stringify!(mpkl_proto) ) ); } unsafe extern "C" { pub fn peeloff(s: ::std::os::raw::c_int, arg1: sae_associd_t) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn socket_delegate( arg1: ::std::os::raw::c_int, arg2: ::std::os::raw::c_int, arg3: ::std::os::raw::c_int, arg4: pid_t, ) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn recvmsg_x( s: ::std::os::raw::c_int, msgp: *const msghdr_x, cnt: u_int, flags: ::std::os::raw::c_int, ) -> isize; } unsafe extern "C" { pub fn sendmsg_x( s: ::std::os::raw::c_int, msgp: *const msghdr_x, cnt: u_int, flags: ::std::os::raw::c_int, ) -> isize; } unsafe extern "C" { #[link_name = "\u{1}_accept$UNIX2003"] pub fn accept(arg1: ::std::os::raw::c_int, arg2: *mut sockaddr, arg3: *mut socklen_t) -> ::std::os::raw::c_int; } unsafe extern "C" { #[link_name = "\u{1}_bind$UNIX2003"] pub fn bind(arg1: ::std::os::raw::c_int, arg2: *const sockaddr, arg3: socklen_t) -> ::std::os::raw::c_int; } unsafe extern "C" { #[link_name = "\u{1}_connect$UNIX2003"] pub fn connect(arg1: ::std::os::raw::c_int, arg2: *const sockaddr, arg3: socklen_t) -> ::std::os::raw::c_int; } unsafe extern "C" { #[link_name = "\u{1}_getpeername$UNIX2003"] pub fn getpeername(arg1: ::std::os::raw::c_int, arg2: *mut sockaddr, arg3: *mut socklen_t) -> ::std::os::raw::c_int; } unsafe extern "C" { #[link_name = "\u{1}_getsockname$UNIX2003"] pub fn getsockname(arg1: ::std::os::raw::c_int, arg2: *mut sockaddr, arg3: *mut socklen_t) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn getsockopt( arg1: ::std::os::raw::c_int, arg2: ::std::os::raw::c_int, arg3: ::std::os::raw::c_int, arg4: *mut ::std::os::raw::c_void, arg5: *mut socklen_t, ) -> ::std::os::raw::c_int; } unsafe extern "C" { #[link_name = "\u{1}_listen$UNIX2003"] pub fn listen(arg1: ::std::os::raw::c_int, arg2: ::std::os::raw::c_int) -> ::std::os::raw::c_int; } unsafe extern "C" { #[link_name = "\u{1}_recv$UNIX2003"] pub fn recv( arg1: ::std::os::raw::c_int, arg2: *mut ::std::os::raw::c_void, arg3: usize, arg4: ::std::os::raw::c_int, ) -> isize; } unsafe extern "C" { #[link_name = "\u{1}_recvfrom$UNIX2003"] pub fn recvfrom( arg1: ::std::os::raw::c_int, arg2: *mut ::std::os::raw::c_void, arg3: usize, arg4: ::std::os::raw::c_int, arg5: *mut sockaddr, arg6: *mut socklen_t, ) -> isize; } unsafe extern "C" { #[link_name = "\u{1}_recvmsg$UNIX2003"] pub fn recvmsg(arg1: ::std::os::raw::c_int, arg2: *mut msghdr, arg3: ::std::os::raw::c_int) -> isize; } unsafe extern "C" { #[link_name = "\u{1}_send$UNIX2003"] pub fn send( arg1: ::std::os::raw::c_int, arg2: *const ::std::os::raw::c_void, arg3: usize, arg4: ::std::os::raw::c_int, ) -> isize; } unsafe extern "C" { #[link_name = "\u{1}_sendmsg$UNIX2003"] pub fn sendmsg(arg1: ::std::os::raw::c_int, arg2: *const msghdr, arg3: ::std::os::raw::c_int) -> isize; } unsafe extern "C" { #[link_name = "\u{1}_sendto$UNIX2003"] pub fn sendto( arg1: ::std::os::raw::c_int, arg2: *const ::std::os::raw::c_void, arg3: usize, arg4: ::std::os::raw::c_int, arg5: *const sockaddr, arg6: socklen_t, ) -> isize; } unsafe extern "C" { pub fn setsockopt( arg1: ::std::os::raw::c_int, arg2: ::std::os::raw::c_int, arg3: ::std::os::raw::c_int, arg4: *const ::std::os::raw::c_void, arg5: socklen_t, ) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn shutdown(arg1: ::std::os::raw::c_int, arg2: ::std::os::raw::c_int) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn sockatmark(arg1: ::std::os::raw::c_int) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn socket( arg1: ::std::os::raw::c_int, arg2: ::std::os::raw::c_int, arg3: ::std::os::raw::c_int, ) -> ::std::os::raw::c_int; } unsafe extern "C" { #[link_name = "\u{1}_socketpair$UNIX2003"] pub fn socketpair( arg1: ::std::os::raw::c_int, arg2: ::std::os::raw::c_int, arg3: ::std::os::raw::c_int, arg4: *mut ::std::os::raw::c_int, ) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn sendfile( arg1: ::std::os::raw::c_int, arg2: ::std::os::raw::c_int, arg3: off_t, arg4: *mut off_t, arg5: *mut sf_hdtr, arg6: ::std::os::raw::c_int, ) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn pfctlinput(arg1: ::std::os::raw::c_int, arg2: *mut sockaddr); } unsafe extern "C" { pub fn connectx( arg1: ::std::os::raw::c_int, arg2: *const sa_endpoints_t, arg3: sae_associd_t, arg4: ::std::os::raw::c_uint, arg5: *const iovec, arg6: ::std::os::raw::c_uint, arg7: *mut usize, arg8: *mut sae_connid_t, ) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn disconnectx(arg1: ::std::os::raw::c_int, arg2: sae_associd_t, arg3: sae_connid_t) -> ::std::os::raw::c_int; } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct in_addr { pub s_addr: in_addr_t, } #[test] fn bindgen_test_layout_in_addr() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 4usize, concat!("Size of: ", stringify!(in_addr)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(in_addr)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).s_addr) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(in_addr), "::", stringify!(s_addr)) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct sockaddr_in { pub sin_len: __uint8_t, pub sin_family: sa_family_t, pub sin_port: in_port_t, pub sin_addr: in_addr, pub sin_zero: [::std::os::raw::c_char; 8usize], } #[test] fn bindgen_test_layout_sockaddr_in() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 16usize, concat!("Size of: ", stringify!(sockaddr_in)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(sockaddr_in)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).sin_len) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(sockaddr_in), "::", stringify!(sin_len)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).sin_family) as usize - ptr as usize }, 1usize, concat!( "Offset of field: ", stringify!(sockaddr_in), "::", stringify!(sin_family) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).sin_port) as usize - ptr as usize }, 2usize, concat!("Offset of field: ", stringify!(sockaddr_in), "::", stringify!(sin_port)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).sin_addr) as usize - ptr as usize }, 4usize, concat!("Offset of field: ", stringify!(sockaddr_in), "::", stringify!(sin_addr)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).sin_zero) as usize - ptr as usize }, 8usize, concat!("Offset of field: ", stringify!(sockaddr_in), "::", stringify!(sin_zero)) ); } #[repr(C)] #[derive(Copy, Clone)] pub struct sockaddr_inifscope { pub sin_len: __uint8_t, pub sin_family: sa_family_t, pub sin_port: in_port_t, pub sin_addr: in_addr, pub un: sockaddr_inifscope__bindgen_ty_1, } #[repr(C)] #[derive(Copy, Clone)] pub union sockaddr_inifscope__bindgen_ty_1 { pub sin_zero: [::std::os::raw::c_char; 8usize], pub _in_index: sockaddr_inifscope__bindgen_ty_1__bindgen_ty_1, } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct sockaddr_inifscope__bindgen_ty_1__bindgen_ty_1 { pub ifscope: __uint32_t, } #[test] fn bindgen_test_layout_sockaddr_inifscope__bindgen_ty_1__bindgen_ty_1() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 4usize, concat!("Size of: ", stringify!(sockaddr_inifscope__bindgen_ty_1__bindgen_ty_1)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!( "Alignment of ", stringify!(sockaddr_inifscope__bindgen_ty_1__bindgen_ty_1) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifscope) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(sockaddr_inifscope__bindgen_ty_1__bindgen_ty_1), "::", stringify!(ifscope) ) ); } #[test] fn bindgen_test_layout_sockaddr_inifscope__bindgen_ty_1() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 8usize, concat!("Size of: ", stringify!(sockaddr_inifscope__bindgen_ty_1)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(sockaddr_inifscope__bindgen_ty_1)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).sin_zero) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(sockaddr_inifscope__bindgen_ty_1), "::", stringify!(sin_zero) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr)._in_index) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(sockaddr_inifscope__bindgen_ty_1), "::", stringify!(_in_index) ) ); } #[test] fn bindgen_test_layout_sockaddr_inifscope() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 16usize, concat!("Size of: ", stringify!(sockaddr_inifscope)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(sockaddr_inifscope)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).sin_len) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(sockaddr_inifscope), "::", stringify!(sin_len) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).sin_family) as usize - ptr as usize }, 1usize, concat!( "Offset of field: ", stringify!(sockaddr_inifscope), "::", stringify!(sin_family) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).sin_port) as usize - ptr as usize }, 2usize, concat!( "Offset of field: ", stringify!(sockaddr_inifscope), "::", stringify!(sin_port) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).sin_addr) as usize - ptr as usize }, 4usize, concat!( "Offset of field: ", stringify!(sockaddr_inifscope), "::", stringify!(sin_addr) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).un) as usize - ptr as usize }, 8usize, concat!( "Offset of field: ", stringify!(sockaddr_inifscope), "::", stringify!(un) ) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct ip_opts { pub ip_dst: in_addr, pub ip_opts: [::std::os::raw::c_char; 40usize], } #[test] fn bindgen_test_layout_ip_opts() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 44usize, concat!("Size of: ", stringify!(ip_opts)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(ip_opts)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ip_dst) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(ip_opts), "::", stringify!(ip_dst)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ip_opts) as usize - ptr as usize }, 4usize, concat!("Offset of field: ", stringify!(ip_opts), "::", stringify!(ip_opts)) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct ip_mreq { pub imr_multiaddr: in_addr, pub imr_interface: in_addr, } #[test] fn bindgen_test_layout_ip_mreq() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 8usize, concat!("Size of: ", stringify!(ip_mreq)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(ip_mreq)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).imr_multiaddr) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(ip_mreq), "::", stringify!(imr_multiaddr) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).imr_interface) as usize - ptr as usize }, 4usize, concat!( "Offset of field: ", stringify!(ip_mreq), "::", stringify!(imr_interface) ) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct ip_mreqn { pub imr_multiaddr: in_addr, pub imr_address: in_addr, pub imr_ifindex: ::std::os::raw::c_int, } #[test] fn bindgen_test_layout_ip_mreqn() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 12usize, concat!("Size of: ", stringify!(ip_mreqn)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(ip_mreqn)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).imr_multiaddr) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(ip_mreqn), "::", stringify!(imr_multiaddr) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).imr_address) as usize - ptr as usize }, 4usize, concat!("Offset of field: ", stringify!(ip_mreqn), "::", stringify!(imr_address)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).imr_ifindex) as usize - ptr as usize }, 8usize, concat!("Offset of field: ", stringify!(ip_mreqn), "::", stringify!(imr_ifindex)) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct ip_mreq_source { pub imr_multiaddr: in_addr, pub imr_sourceaddr: in_addr, pub imr_interface: in_addr, } #[test] fn bindgen_test_layout_ip_mreq_source() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 12usize, concat!("Size of: ", stringify!(ip_mreq_source)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(ip_mreq_source)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).imr_multiaddr) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(ip_mreq_source), "::", stringify!(imr_multiaddr) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).imr_sourceaddr) as usize - ptr as usize }, 4usize, concat!( "Offset of field: ", stringify!(ip_mreq_source), "::", stringify!(imr_sourceaddr) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).imr_interface) as usize - ptr as usize }, 8usize, concat!( "Offset of field: ", stringify!(ip_mreq_source), "::", stringify!(imr_interface) ) ); } #[repr(C, packed(4))] #[derive(Debug, Copy, Clone)] pub struct group_req { pub gr_interface: u32, pub gr_group: sockaddr_storage, } #[test] fn bindgen_test_layout_group_req() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 132usize, concat!("Size of: ", stringify!(group_req)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(group_req)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).gr_interface) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(group_req), "::", stringify!(gr_interface) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).gr_group) as usize - ptr as usize }, 4usize, concat!("Offset of field: ", stringify!(group_req), "::", stringify!(gr_group)) ); } #[repr(C, packed(4))] #[derive(Debug, Copy, Clone)] pub struct group_source_req { pub gsr_interface: u32, pub gsr_group: sockaddr_storage, pub gsr_source: sockaddr_storage, } #[test] fn bindgen_test_layout_group_source_req() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 260usize, concat!("Size of: ", stringify!(group_source_req)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(group_source_req)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).gsr_interface) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(group_source_req), "::", stringify!(gsr_interface) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).gsr_group) as usize - ptr as usize }, 4usize, concat!( "Offset of field: ", stringify!(group_source_req), "::", stringify!(gsr_group) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).gsr_source) as usize - ptr as usize }, 132usize, concat!( "Offset of field: ", stringify!(group_source_req), "::", stringify!(gsr_source) ) ); } #[repr(C, packed(4))] #[derive(Debug, Copy, Clone)] pub struct __msfilterreq { pub msfr_ifindex: u32, pub msfr_fmode: u32, pub msfr_nsrcs: u32, pub __msfr_align: u32, pub msfr_group: sockaddr_storage, pub msfr_srcs: *mut sockaddr_storage, } #[test] fn bindgen_test_layout___msfilterreq() { const UNINIT: ::std::mem::MaybeUninit<__msfilterreq> = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::<__msfilterreq>(), 152usize, concat!("Size of: ", stringify!(__msfilterreq)) ); assert_eq!( ::std::mem::align_of::<__msfilterreq>(), 4usize, concat!("Alignment of ", stringify!(__msfilterreq)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).msfr_ifindex) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(__msfilterreq), "::", stringify!(msfr_ifindex) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).msfr_fmode) as usize - ptr as usize }, 4usize, concat!( "Offset of field: ", stringify!(__msfilterreq), "::", stringify!(msfr_fmode) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).msfr_nsrcs) as usize - ptr as usize }, 8usize, concat!( "Offset of field: ", stringify!(__msfilterreq), "::", stringify!(msfr_nsrcs) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__msfr_align) as usize - ptr as usize }, 12usize, concat!( "Offset of field: ", stringify!(__msfilterreq), "::", stringify!(__msfr_align) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).msfr_group) as usize - ptr as usize }, 16usize, concat!( "Offset of field: ", stringify!(__msfilterreq), "::", stringify!(msfr_group) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).msfr_srcs) as usize - ptr as usize }, 144usize, concat!( "Offset of field: ", stringify!(__msfilterreq), "::", stringify!(msfr_srcs) ) ); } unsafe extern "C" { pub fn setipv4sourcefilter( arg1: ::std::os::raw::c_int, arg2: in_addr, arg3: in_addr, arg4: u32, arg5: u32, arg6: *mut in_addr, ) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn getipv4sourcefilter( arg1: ::std::os::raw::c_int, arg2: in_addr, arg3: in_addr, arg4: *mut u32, arg5: *mut u32, arg6: *mut in_addr, ) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn setsourcefilter( arg1: ::std::os::raw::c_int, arg2: u32, arg3: *mut sockaddr, arg4: socklen_t, arg5: u32, arg6: u32, arg7: *mut sockaddr_storage, ) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn getsourcefilter( arg1: ::std::os::raw::c_int, arg2: u32, arg3: *mut sockaddr, arg4: socklen_t, arg5: *mut u32, arg6: *mut u32, arg7: *mut sockaddr_storage, ) -> ::std::os::raw::c_int; } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct in_pktinfo { pub ipi_ifindex: ::std::os::raw::c_uint, pub ipi_spec_dst: in_addr, pub ipi_addr: in_addr, } #[test] fn bindgen_test_layout_in_pktinfo() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 12usize, concat!("Size of: ", stringify!(in_pktinfo)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(in_pktinfo)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ipi_ifindex) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(in_pktinfo), "::", stringify!(ipi_ifindex) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ipi_spec_dst) as usize - ptr as usize }, 4usize, concat!( "Offset of field: ", stringify!(in_pktinfo), "::", stringify!(ipi_spec_dst) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ipi_addr) as usize - ptr as usize }, 8usize, concat!("Offset of field: ", stringify!(in_pktinfo), "::", stringify!(ipi_addr)) ); } #[repr(C)] #[derive(Copy, Clone)] pub struct in6_addr { pub __u6_addr: in6_addr__bindgen_ty_1, } #[repr(C)] #[derive(Copy, Clone)] pub union in6_addr__bindgen_ty_1 { pub __u6_addr8: [__uint8_t; 16usize], pub __u6_addr16: [__uint16_t; 8usize], pub __u6_addr32: [__uint32_t; 4usize], } #[test] fn bindgen_test_layout_in6_addr__bindgen_ty_1() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 16usize, concat!("Size of: ", stringify!(in6_addr__bindgen_ty_1)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(in6_addr__bindgen_ty_1)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__u6_addr8) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(in6_addr__bindgen_ty_1), "::", stringify!(__u6_addr8) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__u6_addr16) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(in6_addr__bindgen_ty_1), "::", stringify!(__u6_addr16) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__u6_addr32) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(in6_addr__bindgen_ty_1), "::", stringify!(__u6_addr32) ) ); } #[test] fn bindgen_test_layout_in6_addr() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 16usize, concat!("Size of: ", stringify!(in6_addr)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(in6_addr)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__u6_addr) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(in6_addr), "::", stringify!(__u6_addr)) ); } pub type in6_addr_t = in6_addr; #[repr(C)] #[derive(Copy, Clone)] pub struct sockaddr_in6 { pub sin6_len: __uint8_t, pub sin6_family: sa_family_t, pub sin6_port: in_port_t, pub sin6_flowinfo: __uint32_t, pub sin6_addr: in6_addr, pub sin6_scope_id: __uint32_t, } #[test] fn bindgen_test_layout_sockaddr_in6() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 28usize, concat!("Size of: ", stringify!(sockaddr_in6)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(sockaddr_in6)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).sin6_len) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(sockaddr_in6), "::", stringify!(sin6_len) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).sin6_family) as usize - ptr as usize }, 1usize, concat!( "Offset of field: ", stringify!(sockaddr_in6), "::", stringify!(sin6_family) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).sin6_port) as usize - ptr as usize }, 2usize, concat!( "Offset of field: ", stringify!(sockaddr_in6), "::", stringify!(sin6_port) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).sin6_flowinfo) as usize - ptr as usize }, 4usize, concat!( "Offset of field: ", stringify!(sockaddr_in6), "::", stringify!(sin6_flowinfo) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).sin6_addr) as usize - ptr as usize }, 8usize, concat!( "Offset of field: ", stringify!(sockaddr_in6), "::", stringify!(sin6_addr) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).sin6_scope_id) as usize - ptr as usize }, 24usize, concat!( "Offset of field: ", stringify!(sockaddr_in6), "::", stringify!(sin6_scope_id) ) ); } unsafe extern "C" { pub static in6addr_any: in6_addr; } unsafe extern "C" { pub static in6addr_loopback: in6_addr; } unsafe extern "C" { pub static in6addr_nodelocal_allnodes: in6_addr; } unsafe extern "C" { pub static in6addr_linklocal_allnodes: in6_addr; } unsafe extern "C" { pub static in6addr_linklocal_allrouters: in6_addr; } unsafe extern "C" { pub static in6addr_linklocal_allv2routers: in6_addr; } #[repr(C)] #[derive(Copy, Clone)] pub struct route_in6_old { pub ro_rt: *mut ::std::os::raw::c_void, pub ro_flags: u32, pub ro_dst: sockaddr_in6, } #[test] fn bindgen_test_layout_route_in6_old() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 40usize, concat!("Size of: ", stringify!(route_in6_old)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(route_in6_old)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ro_rt) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(route_in6_old), "::", stringify!(ro_rt)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ro_flags) as usize - ptr as usize }, 8usize, concat!( "Offset of field: ", stringify!(route_in6_old), "::", stringify!(ro_flags) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ro_dst) as usize - ptr as usize }, 12usize, concat!("Offset of field: ", stringify!(route_in6_old), "::", stringify!(ro_dst)) ); } #[repr(C)] #[derive(Copy, Clone)] pub struct ipv6_mreq { pub ipv6mr_multiaddr: in6_addr, pub ipv6mr_interface: ::std::os::raw::c_uint, } #[test] fn bindgen_test_layout_ipv6_mreq() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 20usize, concat!("Size of: ", stringify!(ipv6_mreq)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(ipv6_mreq)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ipv6mr_multiaddr) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(ipv6_mreq), "::", stringify!(ipv6mr_multiaddr) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ipv6mr_interface) as usize - ptr as usize }, 16usize, concat!( "Offset of field: ", stringify!(ipv6_mreq), "::", stringify!(ipv6mr_interface) ) ); } #[repr(C)] #[derive(Copy, Clone)] pub struct in6_pktinfo { pub ipi6_addr: in6_addr, pub ipi6_ifindex: ::std::os::raw::c_uint, } #[test] fn bindgen_test_layout_in6_pktinfo() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 20usize, concat!("Size of: ", stringify!(in6_pktinfo)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(in6_pktinfo)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ipi6_addr) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(in6_pktinfo), "::", stringify!(ipi6_addr) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ipi6_ifindex) as usize - ptr as usize }, 16usize, concat!( "Offset of field: ", stringify!(in6_pktinfo), "::", stringify!(ipi6_ifindex) ) ); } #[repr(C)] #[derive(Copy, Clone)] pub struct ip6_mtuinfo { pub ip6m_addr: sockaddr_in6, pub ip6m_mtu: u32, } #[test] fn bindgen_test_layout_ip6_mtuinfo() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 32usize, concat!("Size of: ", stringify!(ip6_mtuinfo)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(ip6_mtuinfo)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ip6m_addr) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(ip6_mtuinfo), "::", stringify!(ip6m_addr) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ip6m_mtu) as usize - ptr as usize }, 28usize, concat!("Offset of field: ", stringify!(ip6_mtuinfo), "::", stringify!(ip6m_mtu)) ); } pub const in6_clat46_evhdlr_code_t_IN6_CLAT46_EVENT_V4_FLOW: in6_clat46_evhdlr_code_t = 0; pub const in6_clat46_evhdlr_code_t_IN6_CLAT46_EVENT_V6_ADDR_CONFFAIL: in6_clat46_evhdlr_code_t = 1; pub type in6_clat46_evhdlr_code_t = ::std::os::raw::c_uint; #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct kev_netevent_clat46_data { pub clat46_event_code: in6_clat46_evhdlr_code_t, pub epid: pid_t, pub euuid: uuid_t, } #[test] fn bindgen_test_layout_kev_netevent_clat46_data() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 24usize, concat!("Size of: ", stringify!(kev_netevent_clat46_data)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(kev_netevent_clat46_data)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).clat46_event_code) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(kev_netevent_clat46_data), "::", stringify!(clat46_event_code) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).epid) as usize - ptr as usize }, 4usize, concat!( "Offset of field: ", stringify!(kev_netevent_clat46_data), "::", stringify!(epid) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).euuid) as usize - ptr as usize }, 8usize, concat!( "Offset of field: ", stringify!(kev_netevent_clat46_data), "::", stringify!(euuid) ) ); } unsafe extern "C" { pub fn inet6_option_space(arg1: ::std::os::raw::c_int) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn inet6_option_init( arg1: *mut ::std::os::raw::c_void, arg2: *mut *mut cmsghdr, arg3: ::std::os::raw::c_int, ) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn inet6_option_append( arg1: *mut cmsghdr, arg2: *const __uint8_t, arg3: ::std::os::raw::c_int, arg4: ::std::os::raw::c_int, ) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn inet6_option_alloc( arg1: *mut cmsghdr, arg2: ::std::os::raw::c_int, arg3: ::std::os::raw::c_int, arg4: ::std::os::raw::c_int, ) -> *mut __uint8_t; } unsafe extern "C" { pub fn inet6_option_next(arg1: *const cmsghdr, arg2: *mut *mut __uint8_t) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn inet6_option_find( arg1: *const cmsghdr, arg2: *mut *mut __uint8_t, arg3: ::std::os::raw::c_int, ) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn inet6_rthdr_space(arg1: ::std::os::raw::c_int, arg2: ::std::os::raw::c_int) -> usize; } unsafe extern "C" { pub fn inet6_rthdr_init(arg1: *mut ::std::os::raw::c_void, arg2: ::std::os::raw::c_int) -> *mut cmsghdr; } unsafe extern "C" { pub fn inet6_rthdr_add( arg1: *mut cmsghdr, arg2: *const in6_addr, arg3: ::std::os::raw::c_uint, ) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn inet6_rthdr_lasthop(arg1: *mut cmsghdr, arg2: ::std::os::raw::c_uint) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn inet6_rthdr_segments(arg1: *const cmsghdr) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn inet6_rthdr_getaddr(arg1: *mut cmsghdr, arg2: ::std::os::raw::c_int) -> *mut in6_addr; } unsafe extern "C" { pub fn inet6_rthdr_getflags(arg1: *const cmsghdr, arg2: ::std::os::raw::c_int) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn inet6_opt_init(arg1: *mut ::std::os::raw::c_void, arg2: socklen_t) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn inet6_opt_append( arg1: *mut ::std::os::raw::c_void, arg2: socklen_t, arg3: ::std::os::raw::c_int, arg4: __uint8_t, arg5: socklen_t, arg6: __uint8_t, arg7: *mut *mut ::std::os::raw::c_void, ) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn inet6_opt_finish( arg1: *mut ::std::os::raw::c_void, arg2: socklen_t, arg3: ::std::os::raw::c_int, ) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn inet6_opt_set_val( arg1: *mut ::std::os::raw::c_void, arg2: ::std::os::raw::c_int, arg3: *mut ::std::os::raw::c_void, arg4: socklen_t, ) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn inet6_opt_next( arg1: *mut ::std::os::raw::c_void, arg2: socklen_t, arg3: ::std::os::raw::c_int, arg4: *mut __uint8_t, arg5: *mut socklen_t, arg6: *mut *mut ::std::os::raw::c_void, ) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn inet6_opt_find( arg1: *mut ::std::os::raw::c_void, arg2: socklen_t, arg3: ::std::os::raw::c_int, arg4: __uint8_t, arg5: *mut socklen_t, arg6: *mut *mut ::std::os::raw::c_void, ) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn inet6_opt_get_val( arg1: *mut ::std::os::raw::c_void, arg2: ::std::os::raw::c_int, arg3: *mut ::std::os::raw::c_void, arg4: socklen_t, ) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn inet6_rth_space(arg1: ::std::os::raw::c_int, arg2: ::std::os::raw::c_int) -> socklen_t; } unsafe extern "C" { pub fn inet6_rth_init( arg1: *mut ::std::os::raw::c_void, arg2: socklen_t, arg3: ::std::os::raw::c_int, arg4: ::std::os::raw::c_int, ) -> *mut ::std::os::raw::c_void; } unsafe extern "C" { pub fn inet6_rth_add(arg1: *mut ::std::os::raw::c_void, arg2: *const in6_addr) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn inet6_rth_reverse( arg1: *const ::std::os::raw::c_void, arg2: *mut ::std::os::raw::c_void, ) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn inet6_rth_segments(arg1: *const ::std::os::raw::c_void) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn inet6_rth_getaddr(arg1: *const ::std::os::raw::c_void, arg2: ::std::os::raw::c_int) -> *mut in6_addr; } #[repr(C)] #[derive(Copy, Clone)] pub union sockaddr_in_4_6 { pub sa: sockaddr, pub sin: sockaddr_in, pub sin6: sockaddr_in6, } #[test] fn bindgen_test_layout_sockaddr_in_4_6() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 28usize, concat!("Size of: ", stringify!(sockaddr_in_4_6)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(sockaddr_in_4_6)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).sa) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(sockaddr_in_4_6), "::", stringify!(sa)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).sin) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(sockaddr_in_4_6), "::", stringify!(sin)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).sin6) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(sockaddr_in_4_6), "::", stringify!(sin6)) ); } unsafe extern "C" { pub fn bindresvport(arg1: ::std::os::raw::c_int, arg2: *mut sockaddr_in) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn bindresvport_sa(arg1: ::std::os::raw::c_int, arg2: *mut sockaddr) -> ::std::os::raw::c_int; } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct timespec { pub tv_sec: __darwin_time_t, pub tv_nsec: ::std::os::raw::c_long, } #[test] fn bindgen_test_layout_timespec() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 16usize, concat!("Size of: ", stringify!(timespec)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(timespec)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).tv_sec) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(timespec), "::", stringify!(tv_sec)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).tv_nsec) as usize - ptr as usize }, 8usize, concat!("Offset of field: ", stringify!(timespec), "::", stringify!(tv_nsec)) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct timeval { pub tv_sec: __darwin_time_t, pub tv_usec: __darwin_suseconds_t, } #[test] fn bindgen_test_layout_timeval() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 16usize, concat!("Size of: ", stringify!(timeval)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(timeval)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).tv_sec) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(timeval), "::", stringify!(tv_sec)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).tv_usec) as usize - ptr as usize }, 8usize, concat!("Offset of field: ", stringify!(timeval), "::", stringify!(tv_usec)) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct timeval64 { pub tv_sec: __int64_t, pub tv_usec: __int64_t, } #[test] fn bindgen_test_layout_timeval64() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 16usize, concat!("Size of: ", stringify!(timeval64)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(timeval64)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).tv_sec) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(timeval64), "::", stringify!(tv_sec)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).tv_usec) as usize - ptr as usize }, 8usize, concat!("Offset of field: ", stringify!(timeval64), "::", stringify!(tv_usec)) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct itimerval { pub it_interval: timeval, pub it_value: timeval, } #[test] fn bindgen_test_layout_itimerval() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 32usize, concat!("Size of: ", stringify!(itimerval)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(itimerval)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).it_interval) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(itimerval), "::", stringify!(it_interval) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).it_value) as usize - ptr as usize }, 16usize, concat!("Offset of field: ", stringify!(itimerval), "::", stringify!(it_value)) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct timezone { pub tz_minuteswest: ::std::os::raw::c_int, pub tz_dsttime: ::std::os::raw::c_int, } #[test] fn bindgen_test_layout_timezone() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 8usize, concat!("Size of: ", stringify!(timezone)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(timezone)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).tz_minuteswest) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(timezone), "::", stringify!(tz_minuteswest) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).tz_dsttime) as usize - ptr as usize }, 4usize, concat!("Offset of field: ", stringify!(timezone), "::", stringify!(tz_dsttime)) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct clockinfo { pub hz: ::std::os::raw::c_int, pub tick: ::std::os::raw::c_int, pub tickadj: ::std::os::raw::c_int, pub stathz: ::std::os::raw::c_int, pub profhz: ::std::os::raw::c_int, } #[test] fn bindgen_test_layout_clockinfo() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 20usize, concat!("Size of: ", stringify!(clockinfo)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(clockinfo)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).hz) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(clockinfo), "::", stringify!(hz)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).tick) as usize - ptr as usize }, 4usize, concat!("Offset of field: ", stringify!(clockinfo), "::", stringify!(tick)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).tickadj) as usize - ptr as usize }, 8usize, concat!("Offset of field: ", stringify!(clockinfo), "::", stringify!(tickadj)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).stathz) as usize - ptr as usize }, 12usize, concat!("Offset of field: ", stringify!(clockinfo), "::", stringify!(stathz)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).profhz) as usize - ptr as usize }, 16usize, concat!("Offset of field: ", stringify!(clockinfo), "::", stringify!(profhz)) ); } pub type __darwin_nl_item = ::std::os::raw::c_int; pub type __darwin_wctrans_t = ::std::os::raw::c_int; pub type __darwin_wctype_t = __uint32_t; #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct tm { pub tm_sec: ::std::os::raw::c_int, pub tm_min: ::std::os::raw::c_int, pub tm_hour: ::std::os::raw::c_int, pub tm_mday: ::std::os::raw::c_int, pub tm_mon: ::std::os::raw::c_int, pub tm_year: ::std::os::raw::c_int, pub tm_wday: ::std::os::raw::c_int, pub tm_yday: ::std::os::raw::c_int, pub tm_isdst: ::std::os::raw::c_int, pub tm_gmtoff: ::std::os::raw::c_long, pub tm_zone: *mut ::std::os::raw::c_char, } #[test] fn bindgen_test_layout_tm() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 56usize, concat!("Size of: ", stringify!(tm)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(tm)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).tm_sec) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(tm), "::", stringify!(tm_sec)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).tm_min) as usize - ptr as usize }, 4usize, concat!("Offset of field: ", stringify!(tm), "::", stringify!(tm_min)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).tm_hour) as usize - ptr as usize }, 8usize, concat!("Offset of field: ", stringify!(tm), "::", stringify!(tm_hour)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).tm_mday) as usize - ptr as usize }, 12usize, concat!("Offset of field: ", stringify!(tm), "::", stringify!(tm_mday)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).tm_mon) as usize - ptr as usize }, 16usize, concat!("Offset of field: ", stringify!(tm), "::", stringify!(tm_mon)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).tm_year) as usize - ptr as usize }, 20usize, concat!("Offset of field: ", stringify!(tm), "::", stringify!(tm_year)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).tm_wday) as usize - ptr as usize }, 24usize, concat!("Offset of field: ", stringify!(tm), "::", stringify!(tm_wday)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).tm_yday) as usize - ptr as usize }, 28usize, concat!("Offset of field: ", stringify!(tm), "::", stringify!(tm_yday)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).tm_isdst) as usize - ptr as usize }, 32usize, concat!("Offset of field: ", stringify!(tm), "::", stringify!(tm_isdst)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).tm_gmtoff) as usize - ptr as usize }, 40usize, concat!("Offset of field: ", stringify!(tm), "::", stringify!(tm_gmtoff)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).tm_zone) as usize - ptr as usize }, 48usize, concat!("Offset of field: ", stringify!(tm), "::", stringify!(tm_zone)) ); } unsafe extern "C" { pub static mut tzname: [*mut ::std::os::raw::c_char; 0usize]; } unsafe extern "C" { pub static mut getdate_err: ::std::os::raw::c_int; } unsafe extern "C" { #[link_name = "\u{1}_timezone$UNIX2003"] pub static mut timezone: ::std::os::raw::c_long; } unsafe extern "C" { pub static mut daylight: ::std::os::raw::c_int; } unsafe extern "C" { pub fn asctime(arg1: *const tm) -> *mut ::std::os::raw::c_char; } unsafe extern "C" { #[link_name = "\u{1}_clock$UNIX2003"] pub fn clock() -> clock_t; } unsafe extern "C" { pub fn ctime(arg1: *const time_t) -> *mut ::std::os::raw::c_char; } unsafe extern "C" { pub fn difftime(arg1: time_t, arg2: time_t) -> f64; } unsafe extern "C" { pub fn getdate(arg1: *const ::std::os::raw::c_char) -> *mut tm; } unsafe extern "C" { pub fn gmtime(arg1: *const time_t) -> *mut tm; } unsafe extern "C" { pub fn localtime(arg1: *const time_t) -> *mut tm; } unsafe extern "C" { #[link_name = "\u{1}_mktime$UNIX2003"] pub fn mktime(arg1: *mut tm) -> time_t; } unsafe extern "C" { #[link_name = "\u{1}_strftime$UNIX2003"] pub fn strftime( arg1: *mut ::std::os::raw::c_char, arg2: usize, arg3: *const ::std::os::raw::c_char, arg4: *const tm, ) -> usize; } unsafe extern "C" { #[link_name = "\u{1}_strptime$UNIX2003"] pub fn strptime( arg1: *const ::std::os::raw::c_char, arg2: *const ::std::os::raw::c_char, arg3: *mut tm, ) -> *mut ::std::os::raw::c_char; } unsafe extern "C" { pub fn time(arg1: *mut time_t) -> time_t; } unsafe extern "C" { pub fn tzset(); } unsafe extern "C" { pub fn asctime_r(arg1: *const tm, arg2: *mut ::std::os::raw::c_char) -> *mut ::std::os::raw::c_char; } unsafe extern "C" { pub fn ctime_r(arg1: *const time_t, arg2: *mut ::std::os::raw::c_char) -> *mut ::std::os::raw::c_char; } unsafe extern "C" { pub fn gmtime_r(arg1: *const time_t, arg2: *mut tm) -> *mut tm; } unsafe extern "C" { pub fn localtime_r(arg1: *const time_t, arg2: *mut tm) -> *mut tm; } unsafe extern "C" { pub fn posix2time(arg1: time_t) -> time_t; } unsafe extern "C" { pub fn tzsetwall(); } unsafe extern "C" { pub fn time2posix(arg1: time_t) -> time_t; } unsafe extern "C" { pub fn timelocal(arg1: *mut tm) -> time_t; } unsafe extern "C" { pub fn timegm(arg1: *mut tm) -> time_t; } unsafe extern "C" { #[link_name = "\u{1}_nanosleep$UNIX2003"] pub fn nanosleep(__rqtp: *const timespec, __rmtp: *mut timespec) -> ::std::os::raw::c_int; } pub const clockid_t__CLOCK_REALTIME: clockid_t = 0; pub const clockid_t__CLOCK_MONOTONIC: clockid_t = 6; pub const clockid_t__CLOCK_MONOTONIC_RAW: clockid_t = 4; pub const clockid_t__CLOCK_MONOTONIC_RAW_APPROX: clockid_t = 5; pub const clockid_t__CLOCK_UPTIME_RAW: clockid_t = 8; pub const clockid_t__CLOCK_UPTIME_RAW_APPROX: clockid_t = 9; pub const clockid_t__CLOCK_PROCESS_CPUTIME_ID: clockid_t = 12; pub const clockid_t__CLOCK_THREAD_CPUTIME_ID: clockid_t = 16; pub type clockid_t = ::std::os::raw::c_uint; unsafe extern "C" { pub fn clock_getres(__clock_id: clockid_t, __res: *mut timespec) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn clock_gettime(__clock_id: clockid_t, __tp: *mut timespec) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn clock_gettime_nsec_np(__clock_id: clockid_t) -> __uint64_t; } unsafe extern "C" { pub fn clock_settime(__clock_id: clockid_t, __tp: *const timespec) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn timespec_get(ts: *mut timespec, base: ::std::os::raw::c_int) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn adjtime(arg1: *const timeval, arg2: *mut timeval) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn futimes(arg1: ::std::os::raw::c_int, arg2: *const timeval) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn lutimes(arg1: *const ::std::os::raw::c_char, arg2: *const timeval) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn settimeofday(arg1: *const timeval, arg2: *const timezone) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn getitimer(arg1: ::std::os::raw::c_int, arg2: *mut itimerval) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn gettimeofday(arg1: *mut timeval, arg2: *mut ::std::os::raw::c_void) -> ::std::os::raw::c_int; } unsafe extern "C" { #[link_name = "\u{1}_select$1050"] pub fn select( arg1: ::std::os::raw::c_int, arg2: *mut fd_set, arg3: *mut fd_set, arg4: *mut fd_set, arg5: *mut timeval, ) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn setitimer( arg1: ::std::os::raw::c_int, arg2: *const itimerval, arg3: *mut itimerval, ) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn utimes(arg1: *const ::std::os::raw::c_char, arg2: *const timeval) -> ::std::os::raw::c_int; } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct rt_metrics { pub rmx_locks: u_int32_t, pub rmx_mtu: u_int32_t, pub rmx_hopcount: u_int32_t, pub rmx_expire: i32, pub rmx_recvpipe: u_int32_t, pub rmx_sendpipe: u_int32_t, pub rmx_ssthresh: u_int32_t, pub rmx_rtt: u_int32_t, pub rmx_rttvar: u_int32_t, pub rmx_pksent: u_int32_t, pub rmx_state: u_int32_t, pub rmx_filler: [u_int32_t; 3usize], } #[test] fn bindgen_test_layout_rt_metrics() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 56usize, concat!("Size of: ", stringify!(rt_metrics)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(rt_metrics)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rmx_locks) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(rt_metrics), "::", stringify!(rmx_locks)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rmx_mtu) as usize - ptr as usize }, 4usize, concat!("Offset of field: ", stringify!(rt_metrics), "::", stringify!(rmx_mtu)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rmx_hopcount) as usize - ptr as usize }, 8usize, concat!( "Offset of field: ", stringify!(rt_metrics), "::", stringify!(rmx_hopcount) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rmx_expire) as usize - ptr as usize }, 12usize, concat!( "Offset of field: ", stringify!(rt_metrics), "::", stringify!(rmx_expire) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rmx_recvpipe) as usize - ptr as usize }, 16usize, concat!( "Offset of field: ", stringify!(rt_metrics), "::", stringify!(rmx_recvpipe) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rmx_sendpipe) as usize - ptr as usize }, 20usize, concat!( "Offset of field: ", stringify!(rt_metrics), "::", stringify!(rmx_sendpipe) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rmx_ssthresh) as usize - ptr as usize }, 24usize, concat!( "Offset of field: ", stringify!(rt_metrics), "::", stringify!(rmx_ssthresh) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rmx_rtt) as usize - ptr as usize }, 28usize, concat!("Offset of field: ", stringify!(rt_metrics), "::", stringify!(rmx_rtt)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rmx_rttvar) as usize - ptr as usize }, 32usize, concat!( "Offset of field: ", stringify!(rt_metrics), "::", stringify!(rmx_rttvar) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rmx_pksent) as usize - ptr as usize }, 36usize, concat!( "Offset of field: ", stringify!(rt_metrics), "::", stringify!(rmx_pksent) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rmx_state) as usize - ptr as usize }, 40usize, concat!("Offset of field: ", stringify!(rt_metrics), "::", stringify!(rmx_state)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rmx_filler) as usize - ptr as usize }, 44usize, concat!( "Offset of field: ", stringify!(rt_metrics), "::", stringify!(rmx_filler) ) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct route_old { pub ro_rt: *mut ::std::os::raw::c_void, pub ro_flags: u32, pub ro_dst: sockaddr, } #[test] fn bindgen_test_layout_route_old() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 32usize, concat!("Size of: ", stringify!(route_old)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(route_old)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ro_rt) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(route_old), "::", stringify!(ro_rt)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ro_flags) as usize - ptr as usize }, 8usize, concat!("Offset of field: ", stringify!(route_old), "::", stringify!(ro_flags)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ro_dst) as usize - ptr as usize }, 12usize, concat!("Offset of field: ", stringify!(route_old), "::", stringify!(ro_dst)) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct rtstat { pub rts_badredirect: ::std::os::raw::c_short, pub rts_dynamic: ::std::os::raw::c_short, pub rts_newgateway: ::std::os::raw::c_short, pub rts_unreach: ::std::os::raw::c_short, pub rts_wildcard: ::std::os::raw::c_short, pub rts_badrtgwroute: ::std::os::raw::c_short, } #[test] fn bindgen_test_layout_rtstat() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 12usize, concat!("Size of: ", stringify!(rtstat)) ); assert_eq!( ::std::mem::align_of::(), 2usize, concat!("Alignment of ", stringify!(rtstat)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rts_badredirect) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(rtstat), "::", stringify!(rts_badredirect) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rts_dynamic) as usize - ptr as usize }, 2usize, concat!("Offset of field: ", stringify!(rtstat), "::", stringify!(rts_dynamic)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rts_newgateway) as usize - ptr as usize }, 4usize, concat!( "Offset of field: ", stringify!(rtstat), "::", stringify!(rts_newgateway) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rts_unreach) as usize - ptr as usize }, 6usize, concat!("Offset of field: ", stringify!(rtstat), "::", stringify!(rts_unreach)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rts_wildcard) as usize - ptr as usize }, 8usize, concat!("Offset of field: ", stringify!(rtstat), "::", stringify!(rts_wildcard)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rts_badrtgwroute) as usize - ptr as usize }, 10usize, concat!( "Offset of field: ", stringify!(rtstat), "::", stringify!(rts_badrtgwroute) ) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct rt_msghdr { pub rtm_msglen: u_short, pub rtm_version: u_char, pub rtm_type: u_char, pub rtm_index: u_short, pub rtm_flags: ::std::os::raw::c_int, pub rtm_addrs: ::std::os::raw::c_int, pub rtm_pid: pid_t, pub rtm_seq: ::std::os::raw::c_int, pub rtm_errno: ::std::os::raw::c_int, pub rtm_use: ::std::os::raw::c_int, pub rtm_inits: u_int32_t, pub rtm_rmx: rt_metrics, } #[test] fn bindgen_test_layout_rt_msghdr() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 92usize, concat!("Size of: ", stringify!(rt_msghdr)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(rt_msghdr)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rtm_msglen) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(rt_msghdr), "::", stringify!(rtm_msglen)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rtm_version) as usize - ptr as usize }, 2usize, concat!( "Offset of field: ", stringify!(rt_msghdr), "::", stringify!(rtm_version) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rtm_type) as usize - ptr as usize }, 3usize, concat!("Offset of field: ", stringify!(rt_msghdr), "::", stringify!(rtm_type)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rtm_index) as usize - ptr as usize }, 4usize, concat!("Offset of field: ", stringify!(rt_msghdr), "::", stringify!(rtm_index)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rtm_flags) as usize - ptr as usize }, 8usize, concat!("Offset of field: ", stringify!(rt_msghdr), "::", stringify!(rtm_flags)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rtm_addrs) as usize - ptr as usize }, 12usize, concat!("Offset of field: ", stringify!(rt_msghdr), "::", stringify!(rtm_addrs)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rtm_pid) as usize - ptr as usize }, 16usize, concat!("Offset of field: ", stringify!(rt_msghdr), "::", stringify!(rtm_pid)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rtm_seq) as usize - ptr as usize }, 20usize, concat!("Offset of field: ", stringify!(rt_msghdr), "::", stringify!(rtm_seq)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rtm_errno) as usize - ptr as usize }, 24usize, concat!("Offset of field: ", stringify!(rt_msghdr), "::", stringify!(rtm_errno)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rtm_use) as usize - ptr as usize }, 28usize, concat!("Offset of field: ", stringify!(rt_msghdr), "::", stringify!(rtm_use)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rtm_inits) as usize - ptr as usize }, 32usize, concat!("Offset of field: ", stringify!(rt_msghdr), "::", stringify!(rtm_inits)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rtm_rmx) as usize - ptr as usize }, 36usize, concat!("Offset of field: ", stringify!(rt_msghdr), "::", stringify!(rtm_rmx)) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct rt_msghdr2 { pub rtm_msglen: u_short, pub rtm_version: u_char, pub rtm_type: u_char, pub rtm_index: u_short, pub rtm_flags: ::std::os::raw::c_int, pub rtm_addrs: ::std::os::raw::c_int, pub rtm_refcnt: i32, pub rtm_parentflags: ::std::os::raw::c_int, pub rtm_reserved: ::std::os::raw::c_int, pub rtm_use: ::std::os::raw::c_int, pub rtm_inits: u_int32_t, pub rtm_rmx: rt_metrics, } #[test] fn bindgen_test_layout_rt_msghdr2() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 92usize, concat!("Size of: ", stringify!(rt_msghdr2)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(rt_msghdr2)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rtm_msglen) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(rt_msghdr2), "::", stringify!(rtm_msglen) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rtm_version) as usize - ptr as usize }, 2usize, concat!( "Offset of field: ", stringify!(rt_msghdr2), "::", stringify!(rtm_version) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rtm_type) as usize - ptr as usize }, 3usize, concat!("Offset of field: ", stringify!(rt_msghdr2), "::", stringify!(rtm_type)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rtm_index) as usize - ptr as usize }, 4usize, concat!("Offset of field: ", stringify!(rt_msghdr2), "::", stringify!(rtm_index)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rtm_flags) as usize - ptr as usize }, 8usize, concat!("Offset of field: ", stringify!(rt_msghdr2), "::", stringify!(rtm_flags)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rtm_addrs) as usize - ptr as usize }, 12usize, concat!("Offset of field: ", stringify!(rt_msghdr2), "::", stringify!(rtm_addrs)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rtm_refcnt) as usize - ptr as usize }, 16usize, concat!( "Offset of field: ", stringify!(rt_msghdr2), "::", stringify!(rtm_refcnt) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rtm_parentflags) as usize - ptr as usize }, 20usize, concat!( "Offset of field: ", stringify!(rt_msghdr2), "::", stringify!(rtm_parentflags) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rtm_reserved) as usize - ptr as usize }, 24usize, concat!( "Offset of field: ", stringify!(rt_msghdr2), "::", stringify!(rtm_reserved) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rtm_use) as usize - ptr as usize }, 28usize, concat!("Offset of field: ", stringify!(rt_msghdr2), "::", stringify!(rtm_use)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rtm_inits) as usize - ptr as usize }, 32usize, concat!("Offset of field: ", stringify!(rt_msghdr2), "::", stringify!(rtm_inits)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rtm_rmx) as usize - ptr as usize }, 36usize, concat!("Offset of field: ", stringify!(rt_msghdr2), "::", stringify!(rtm_rmx)) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct kev_netevent_apnfallbk_data { pub epid: pid_t, pub euuid: uuid_t, } #[test] fn bindgen_test_layout_kev_netevent_apnfallbk_data() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 20usize, concat!("Size of: ", stringify!(kev_netevent_apnfallbk_data)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(kev_netevent_apnfallbk_data)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).epid) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(kev_netevent_apnfallbk_data), "::", stringify!(epid) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).euuid) as usize - ptr as usize }, 4usize, concat!( "Offset of field: ", stringify!(kev_netevent_apnfallbk_data), "::", stringify!(euuid) ) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct rt_reach_info { pub ri_refcnt: u_int32_t, pub ri_probes: u_int32_t, pub ri_snd_expire: u_int64_t, pub ri_rcv_expire: u_int64_t, pub ri_rssi: i32, pub ri_lqm: i32, pub ri_npm: i32, } #[test] fn bindgen_test_layout_rt_reach_info() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 40usize, concat!("Size of: ", stringify!(rt_reach_info)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(rt_reach_info)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ri_refcnt) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(rt_reach_info), "::", stringify!(ri_refcnt) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ri_probes) as usize - ptr as usize }, 4usize, concat!( "Offset of field: ", stringify!(rt_reach_info), "::", stringify!(ri_probes) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ri_snd_expire) as usize - ptr as usize }, 8usize, concat!( "Offset of field: ", stringify!(rt_reach_info), "::", stringify!(ri_snd_expire) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ri_rcv_expire) as usize - ptr as usize }, 16usize, concat!( "Offset of field: ", stringify!(rt_reach_info), "::", stringify!(ri_rcv_expire) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ri_rssi) as usize - ptr as usize }, 24usize, concat!( "Offset of field: ", stringify!(rt_reach_info), "::", stringify!(ri_rssi) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ri_lqm) as usize - ptr as usize }, 28usize, concat!("Offset of field: ", stringify!(rt_reach_info), "::", stringify!(ri_lqm)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ri_npm) as usize - ptr as usize }, 32usize, concat!("Offset of field: ", stringify!(rt_reach_info), "::", stringify!(ri_npm)) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct rt_msghdr_ext { pub rtm_msglen: u_short, pub rtm_version: u_char, pub rtm_type: u_char, pub rtm_index: u_int32_t, pub rtm_flags: u_int32_t, pub rtm_reserved: u_int32_t, pub rtm_addrs: u_int32_t, pub rtm_pid: pid_t, pub rtm_seq: ::std::os::raw::c_int, pub rtm_errno: ::std::os::raw::c_int, pub rtm_use: u_int32_t, pub rtm_inits: u_int32_t, pub rtm_rmx: rt_metrics, pub rtm_ri: rt_reach_info, } #[test] fn bindgen_test_layout_rt_msghdr_ext() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 136usize, concat!("Size of: ", stringify!(rt_msghdr_ext)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(rt_msghdr_ext)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rtm_msglen) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(rt_msghdr_ext), "::", stringify!(rtm_msglen) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rtm_version) as usize - ptr as usize }, 2usize, concat!( "Offset of field: ", stringify!(rt_msghdr_ext), "::", stringify!(rtm_version) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rtm_type) as usize - ptr as usize }, 3usize, concat!( "Offset of field: ", stringify!(rt_msghdr_ext), "::", stringify!(rtm_type) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rtm_index) as usize - ptr as usize }, 4usize, concat!( "Offset of field: ", stringify!(rt_msghdr_ext), "::", stringify!(rtm_index) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rtm_flags) as usize - ptr as usize }, 8usize, concat!( "Offset of field: ", stringify!(rt_msghdr_ext), "::", stringify!(rtm_flags) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rtm_reserved) as usize - ptr as usize }, 12usize, concat!( "Offset of field: ", stringify!(rt_msghdr_ext), "::", stringify!(rtm_reserved) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rtm_addrs) as usize - ptr as usize }, 16usize, concat!( "Offset of field: ", stringify!(rt_msghdr_ext), "::", stringify!(rtm_addrs) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rtm_pid) as usize - ptr as usize }, 20usize, concat!( "Offset of field: ", stringify!(rt_msghdr_ext), "::", stringify!(rtm_pid) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rtm_seq) as usize - ptr as usize }, 24usize, concat!( "Offset of field: ", stringify!(rt_msghdr_ext), "::", stringify!(rtm_seq) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rtm_errno) as usize - ptr as usize }, 28usize, concat!( "Offset of field: ", stringify!(rt_msghdr_ext), "::", stringify!(rtm_errno) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rtm_use) as usize - ptr as usize }, 32usize, concat!( "Offset of field: ", stringify!(rt_msghdr_ext), "::", stringify!(rtm_use) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rtm_inits) as usize - ptr as usize }, 36usize, concat!( "Offset of field: ", stringify!(rt_msghdr_ext), "::", stringify!(rtm_inits) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rtm_rmx) as usize - ptr as usize }, 40usize, concat!( "Offset of field: ", stringify!(rt_msghdr_ext), "::", stringify!(rtm_rmx) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rtm_ri) as usize - ptr as usize }, 96usize, concat!("Offset of field: ", stringify!(rt_msghdr_ext), "::", stringify!(rtm_ri)) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct rt_addrinfo { pub rti_addrs: ::std::os::raw::c_int, pub rti_info: [*mut sockaddr; 8usize], } #[test] fn bindgen_test_layout_rt_addrinfo() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 72usize, concat!("Size of: ", stringify!(rt_addrinfo)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(rt_addrinfo)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rti_addrs) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(rt_addrinfo), "::", stringify!(rti_addrs) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rti_info) as usize - ptr as usize }, 8usize, concat!("Offset of field: ", stringify!(rt_addrinfo), "::", stringify!(rti_info)) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct net_event_data { pub if_family: u_int32_t, pub if_unit: u_int32_t, pub if_name: [::std::os::raw::c_char; 16usize], } #[test] fn bindgen_test_layout_net_event_data() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 24usize, concat!("Size of: ", stringify!(net_event_data)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(net_event_data)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).if_family) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(net_event_data), "::", stringify!(if_family) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).if_unit) as usize - ptr as usize }, 4usize, concat!( "Offset of field: ", stringify!(net_event_data), "::", stringify!(if_unit) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).if_name) as usize - ptr as usize }, 8usize, concat!( "Offset of field: ", stringify!(net_event_data), "::", stringify!(if_name) ) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct timeval32 { pub tv_sec: __int32_t, pub tv_usec: __int32_t, } #[test] fn bindgen_test_layout_timeval32() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 8usize, concat!("Size of: ", stringify!(timeval32)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(timeval32)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).tv_sec) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(timeval32), "::", stringify!(tv_sec)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).tv_usec) as usize - ptr as usize }, 4usize, concat!("Offset of field: ", stringify!(timeval32), "::", stringify!(tv_usec)) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct if_data { pub ifi_type: u_char, pub ifi_typelen: u_char, pub ifi_physical: u_char, pub ifi_addrlen: u_char, pub ifi_hdrlen: u_char, pub ifi_recvquota: u_char, pub ifi_xmitquota: u_char, pub ifi_unused1: u_char, pub ifi_mtu: u_int32_t, pub ifi_metric: u_int32_t, pub ifi_baudrate: u_int32_t, pub ifi_ipackets: u_int32_t, pub ifi_ierrors: u_int32_t, pub ifi_opackets: u_int32_t, pub ifi_oerrors: u_int32_t, pub ifi_collisions: u_int32_t, pub ifi_ibytes: u_int32_t, pub ifi_obytes: u_int32_t, pub ifi_imcasts: u_int32_t, pub ifi_omcasts: u_int32_t, pub ifi_iqdrops: u_int32_t, pub ifi_noproto: u_int32_t, pub ifi_recvtiming: u_int32_t, pub ifi_xmittiming: u_int32_t, pub ifi_lastchange: timeval32, pub ifi_unused2: u_int32_t, pub ifi_hwassist: u_int32_t, pub ifi_reserved1: u_int32_t, pub ifi_reserved2: u_int32_t, } #[test] fn bindgen_test_layout_if_data() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 96usize, concat!("Size of: ", stringify!(if_data)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(if_data)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifi_type) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(if_data), "::", stringify!(ifi_type)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifi_typelen) as usize - ptr as usize }, 1usize, concat!("Offset of field: ", stringify!(if_data), "::", stringify!(ifi_typelen)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifi_physical) as usize - ptr as usize }, 2usize, concat!("Offset of field: ", stringify!(if_data), "::", stringify!(ifi_physical)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifi_addrlen) as usize - ptr as usize }, 3usize, concat!("Offset of field: ", stringify!(if_data), "::", stringify!(ifi_addrlen)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifi_hdrlen) as usize - ptr as usize }, 4usize, concat!("Offset of field: ", stringify!(if_data), "::", stringify!(ifi_hdrlen)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifi_recvquota) as usize - ptr as usize }, 5usize, concat!( "Offset of field: ", stringify!(if_data), "::", stringify!(ifi_recvquota) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifi_xmitquota) as usize - ptr as usize }, 6usize, concat!( "Offset of field: ", stringify!(if_data), "::", stringify!(ifi_xmitquota) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifi_unused1) as usize - ptr as usize }, 7usize, concat!("Offset of field: ", stringify!(if_data), "::", stringify!(ifi_unused1)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifi_mtu) as usize - ptr as usize }, 8usize, concat!("Offset of field: ", stringify!(if_data), "::", stringify!(ifi_mtu)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifi_metric) as usize - ptr as usize }, 12usize, concat!("Offset of field: ", stringify!(if_data), "::", stringify!(ifi_metric)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifi_baudrate) as usize - ptr as usize }, 16usize, concat!("Offset of field: ", stringify!(if_data), "::", stringify!(ifi_baudrate)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifi_ipackets) as usize - ptr as usize }, 20usize, concat!("Offset of field: ", stringify!(if_data), "::", stringify!(ifi_ipackets)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifi_ierrors) as usize - ptr as usize }, 24usize, concat!("Offset of field: ", stringify!(if_data), "::", stringify!(ifi_ierrors)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifi_opackets) as usize - ptr as usize }, 28usize, concat!("Offset of field: ", stringify!(if_data), "::", stringify!(ifi_opackets)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifi_oerrors) as usize - ptr as usize }, 32usize, concat!("Offset of field: ", stringify!(if_data), "::", stringify!(ifi_oerrors)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifi_collisions) as usize - ptr as usize }, 36usize, concat!( "Offset of field: ", stringify!(if_data), "::", stringify!(ifi_collisions) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifi_ibytes) as usize - ptr as usize }, 40usize, concat!("Offset of field: ", stringify!(if_data), "::", stringify!(ifi_ibytes)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifi_obytes) as usize - ptr as usize }, 44usize, concat!("Offset of field: ", stringify!(if_data), "::", stringify!(ifi_obytes)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifi_imcasts) as usize - ptr as usize }, 48usize, concat!("Offset of field: ", stringify!(if_data), "::", stringify!(ifi_imcasts)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifi_omcasts) as usize - ptr as usize }, 52usize, concat!("Offset of field: ", stringify!(if_data), "::", stringify!(ifi_omcasts)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifi_iqdrops) as usize - ptr as usize }, 56usize, concat!("Offset of field: ", stringify!(if_data), "::", stringify!(ifi_iqdrops)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifi_noproto) as usize - ptr as usize }, 60usize, concat!("Offset of field: ", stringify!(if_data), "::", stringify!(ifi_noproto)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifi_recvtiming) as usize - ptr as usize }, 64usize, concat!( "Offset of field: ", stringify!(if_data), "::", stringify!(ifi_recvtiming) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifi_xmittiming) as usize - ptr as usize }, 68usize, concat!( "Offset of field: ", stringify!(if_data), "::", stringify!(ifi_xmittiming) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifi_lastchange) as usize - ptr as usize }, 72usize, concat!( "Offset of field: ", stringify!(if_data), "::", stringify!(ifi_lastchange) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifi_unused2) as usize - ptr as usize }, 80usize, concat!("Offset of field: ", stringify!(if_data), "::", stringify!(ifi_unused2)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifi_hwassist) as usize - ptr as usize }, 84usize, concat!("Offset of field: ", stringify!(if_data), "::", stringify!(ifi_hwassist)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifi_reserved1) as usize - ptr as usize }, 88usize, concat!( "Offset of field: ", stringify!(if_data), "::", stringify!(ifi_reserved1) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifi_reserved2) as usize - ptr as usize }, 92usize, concat!( "Offset of field: ", stringify!(if_data), "::", stringify!(ifi_reserved2) ) ); } #[repr(C, packed(4))] #[derive(Debug, Copy, Clone)] pub struct if_data64 { pub ifi_type: u_char, pub ifi_typelen: u_char, pub ifi_physical: u_char, pub ifi_addrlen: u_char, pub ifi_hdrlen: u_char, pub ifi_recvquota: u_char, pub ifi_xmitquota: u_char, pub ifi_unused1: u_char, pub ifi_mtu: u_int32_t, pub ifi_metric: u_int32_t, pub ifi_baudrate: u_int64_t, pub ifi_ipackets: u_int64_t, pub ifi_ierrors: u_int64_t, pub ifi_opackets: u_int64_t, pub ifi_oerrors: u_int64_t, pub ifi_collisions: u_int64_t, pub ifi_ibytes: u_int64_t, pub ifi_obytes: u_int64_t, pub ifi_imcasts: u_int64_t, pub ifi_omcasts: u_int64_t, pub ifi_iqdrops: u_int64_t, pub ifi_noproto: u_int64_t, pub ifi_recvtiming: u_int32_t, pub ifi_xmittiming: u_int32_t, pub ifi_lastchange: timeval32, } #[test] fn bindgen_test_layout_if_data64() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 128usize, concat!("Size of: ", stringify!(if_data64)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(if_data64)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifi_type) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(if_data64), "::", stringify!(ifi_type)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifi_typelen) as usize - ptr as usize }, 1usize, concat!( "Offset of field: ", stringify!(if_data64), "::", stringify!(ifi_typelen) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifi_physical) as usize - ptr as usize }, 2usize, concat!( "Offset of field: ", stringify!(if_data64), "::", stringify!(ifi_physical) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifi_addrlen) as usize - ptr as usize }, 3usize, concat!( "Offset of field: ", stringify!(if_data64), "::", stringify!(ifi_addrlen) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifi_hdrlen) as usize - ptr as usize }, 4usize, concat!("Offset of field: ", stringify!(if_data64), "::", stringify!(ifi_hdrlen)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifi_recvquota) as usize - ptr as usize }, 5usize, concat!( "Offset of field: ", stringify!(if_data64), "::", stringify!(ifi_recvquota) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifi_xmitquota) as usize - ptr as usize }, 6usize, concat!( "Offset of field: ", stringify!(if_data64), "::", stringify!(ifi_xmitquota) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifi_unused1) as usize - ptr as usize }, 7usize, concat!( "Offset of field: ", stringify!(if_data64), "::", stringify!(ifi_unused1) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifi_mtu) as usize - ptr as usize }, 8usize, concat!("Offset of field: ", stringify!(if_data64), "::", stringify!(ifi_mtu)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifi_metric) as usize - ptr as usize }, 12usize, concat!("Offset of field: ", stringify!(if_data64), "::", stringify!(ifi_metric)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifi_baudrate) as usize - ptr as usize }, 16usize, concat!( "Offset of field: ", stringify!(if_data64), "::", stringify!(ifi_baudrate) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifi_ipackets) as usize - ptr as usize }, 24usize, concat!( "Offset of field: ", stringify!(if_data64), "::", stringify!(ifi_ipackets) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifi_ierrors) as usize - ptr as usize }, 32usize, concat!( "Offset of field: ", stringify!(if_data64), "::", stringify!(ifi_ierrors) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifi_opackets) as usize - ptr as usize }, 40usize, concat!( "Offset of field: ", stringify!(if_data64), "::", stringify!(ifi_opackets) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifi_oerrors) as usize - ptr as usize }, 48usize, concat!( "Offset of field: ", stringify!(if_data64), "::", stringify!(ifi_oerrors) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifi_collisions) as usize - ptr as usize }, 56usize, concat!( "Offset of field: ", stringify!(if_data64), "::", stringify!(ifi_collisions) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifi_ibytes) as usize - ptr as usize }, 64usize, concat!("Offset of field: ", stringify!(if_data64), "::", stringify!(ifi_ibytes)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifi_obytes) as usize - ptr as usize }, 72usize, concat!("Offset of field: ", stringify!(if_data64), "::", stringify!(ifi_obytes)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifi_imcasts) as usize - ptr as usize }, 80usize, concat!( "Offset of field: ", stringify!(if_data64), "::", stringify!(ifi_imcasts) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifi_omcasts) as usize - ptr as usize }, 88usize, concat!( "Offset of field: ", stringify!(if_data64), "::", stringify!(ifi_omcasts) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifi_iqdrops) as usize - ptr as usize }, 96usize, concat!( "Offset of field: ", stringify!(if_data64), "::", stringify!(ifi_iqdrops) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifi_noproto) as usize - ptr as usize }, 104usize, concat!( "Offset of field: ", stringify!(if_data64), "::", stringify!(ifi_noproto) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifi_recvtiming) as usize - ptr as usize }, 112usize, concat!( "Offset of field: ", stringify!(if_data64), "::", stringify!(ifi_recvtiming) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifi_xmittiming) as usize - ptr as usize }, 116usize, concat!( "Offset of field: ", stringify!(if_data64), "::", stringify!(ifi_xmittiming) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifi_lastchange) as usize - ptr as usize }, 120usize, concat!( "Offset of field: ", stringify!(if_data64), "::", stringify!(ifi_lastchange) ) ); } #[repr(C, packed(4))] #[derive(Debug, Copy, Clone)] pub struct if_traffic_class { pub ifi_ibepackets: u_int64_t, pub ifi_ibebytes: u_int64_t, pub ifi_obepackets: u_int64_t, pub ifi_obebytes: u_int64_t, pub ifi_ibkpackets: u_int64_t, pub ifi_ibkbytes: u_int64_t, pub ifi_obkpackets: u_int64_t, pub ifi_obkbytes: u_int64_t, pub ifi_ivipackets: u_int64_t, pub ifi_ivibytes: u_int64_t, pub ifi_ovipackets: u_int64_t, pub ifi_ovibytes: u_int64_t, pub ifi_ivopackets: u_int64_t, pub ifi_ivobytes: u_int64_t, pub ifi_ovopackets: u_int64_t, pub ifi_ovobytes: u_int64_t, pub ifi_ipvpackets: u_int64_t, pub ifi_ipvbytes: u_int64_t, pub ifi_opvpackets: u_int64_t, pub ifi_opvbytes: u_int64_t, } #[test] fn bindgen_test_layout_if_traffic_class() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 160usize, concat!("Size of: ", stringify!(if_traffic_class)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(if_traffic_class)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifi_ibepackets) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(if_traffic_class), "::", stringify!(ifi_ibepackets) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifi_ibebytes) as usize - ptr as usize }, 8usize, concat!( "Offset of field: ", stringify!(if_traffic_class), "::", stringify!(ifi_ibebytes) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifi_obepackets) as usize - ptr as usize }, 16usize, concat!( "Offset of field: ", stringify!(if_traffic_class), "::", stringify!(ifi_obepackets) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifi_obebytes) as usize - ptr as usize }, 24usize, concat!( "Offset of field: ", stringify!(if_traffic_class), "::", stringify!(ifi_obebytes) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifi_ibkpackets) as usize - ptr as usize }, 32usize, concat!( "Offset of field: ", stringify!(if_traffic_class), "::", stringify!(ifi_ibkpackets) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifi_ibkbytes) as usize - ptr as usize }, 40usize, concat!( "Offset of field: ", stringify!(if_traffic_class), "::", stringify!(ifi_ibkbytes) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifi_obkpackets) as usize - ptr as usize }, 48usize, concat!( "Offset of field: ", stringify!(if_traffic_class), "::", stringify!(ifi_obkpackets) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifi_obkbytes) as usize - ptr as usize }, 56usize, concat!( "Offset of field: ", stringify!(if_traffic_class), "::", stringify!(ifi_obkbytes) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifi_ivipackets) as usize - ptr as usize }, 64usize, concat!( "Offset of field: ", stringify!(if_traffic_class), "::", stringify!(ifi_ivipackets) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifi_ivibytes) as usize - ptr as usize }, 72usize, concat!( "Offset of field: ", stringify!(if_traffic_class), "::", stringify!(ifi_ivibytes) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifi_ovipackets) as usize - ptr as usize }, 80usize, concat!( "Offset of field: ", stringify!(if_traffic_class), "::", stringify!(ifi_ovipackets) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifi_ovibytes) as usize - ptr as usize }, 88usize, concat!( "Offset of field: ", stringify!(if_traffic_class), "::", stringify!(ifi_ovibytes) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifi_ivopackets) as usize - ptr as usize }, 96usize, concat!( "Offset of field: ", stringify!(if_traffic_class), "::", stringify!(ifi_ivopackets) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifi_ivobytes) as usize - ptr as usize }, 104usize, concat!( "Offset of field: ", stringify!(if_traffic_class), "::", stringify!(ifi_ivobytes) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifi_ovopackets) as usize - ptr as usize }, 112usize, concat!( "Offset of field: ", stringify!(if_traffic_class), "::", stringify!(ifi_ovopackets) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifi_ovobytes) as usize - ptr as usize }, 120usize, concat!( "Offset of field: ", stringify!(if_traffic_class), "::", stringify!(ifi_ovobytes) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifi_ipvpackets) as usize - ptr as usize }, 128usize, concat!( "Offset of field: ", stringify!(if_traffic_class), "::", stringify!(ifi_ipvpackets) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifi_ipvbytes) as usize - ptr as usize }, 136usize, concat!( "Offset of field: ", stringify!(if_traffic_class), "::", stringify!(ifi_ipvbytes) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifi_opvpackets) as usize - ptr as usize }, 144usize, concat!( "Offset of field: ", stringify!(if_traffic_class), "::", stringify!(ifi_opvpackets) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifi_opvbytes) as usize - ptr as usize }, 152usize, concat!( "Offset of field: ", stringify!(if_traffic_class), "::", stringify!(ifi_opvbytes) ) ); } #[repr(C, packed(4))] #[derive(Debug, Copy, Clone)] pub struct if_data_extended { pub ifi_alignerrs: u_int64_t, pub ifi_dt_bytes: u_int64_t, pub ifi_fpackets: u_int64_t, pub ifi_fbytes: u_int64_t, pub reserved: [u_int64_t; 12usize], } #[test] fn bindgen_test_layout_if_data_extended() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 128usize, concat!("Size of: ", stringify!(if_data_extended)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(if_data_extended)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifi_alignerrs) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(if_data_extended), "::", stringify!(ifi_alignerrs) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifi_dt_bytes) as usize - ptr as usize }, 8usize, concat!( "Offset of field: ", stringify!(if_data_extended), "::", stringify!(ifi_dt_bytes) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifi_fpackets) as usize - ptr as usize }, 16usize, concat!( "Offset of field: ", stringify!(if_data_extended), "::", stringify!(ifi_fpackets) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifi_fbytes) as usize - ptr as usize }, 24usize, concat!( "Offset of field: ", stringify!(if_data_extended), "::", stringify!(ifi_fbytes) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).reserved) as usize - ptr as usize }, 32usize, concat!( "Offset of field: ", stringify!(if_data_extended), "::", stringify!(reserved) ) ); } #[repr(C, packed(4))] #[derive(Debug, Copy, Clone)] pub struct if_packet_stats { pub ifi_tcp_badformat: u_int64_t, pub ifi_tcp_unspecv6: u_int64_t, pub ifi_tcp_synfin: u_int64_t, pub ifi_tcp_badformatipsec: u_int64_t, pub ifi_tcp_noconnnolist: u_int64_t, pub ifi_tcp_noconnlist: u_int64_t, pub ifi_tcp_listbadsyn: u_int64_t, pub ifi_tcp_icmp6unreach: u_int64_t, pub ifi_tcp_deprecate6: u_int64_t, pub ifi_tcp_rstinsynrcv: u_int64_t, pub ifi_tcp_ooopacket: u_int64_t, pub ifi_tcp_dospacket: u_int64_t, pub ifi_tcp_cleanup: u_int64_t, pub ifi_tcp_synwindow: u_int64_t, pub reserved: [u_int64_t; 6usize], pub ifi_udp_port_unreach: u_int64_t, pub ifi_udp_faithprefix: u_int64_t, pub ifi_udp_port0: u_int64_t, pub ifi_udp_badlength: u_int64_t, pub ifi_udp_badchksum: u_int64_t, pub ifi_udp_badmcast: u_int64_t, pub ifi_udp_cleanup: u_int64_t, pub ifi_udp_badipsec: u_int64_t, pub _reserved: [u_int64_t; 4usize], } #[test] fn bindgen_test_layout_if_packet_stats() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 256usize, concat!("Size of: ", stringify!(if_packet_stats)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(if_packet_stats)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifi_tcp_badformat) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(if_packet_stats), "::", stringify!(ifi_tcp_badformat) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifi_tcp_unspecv6) as usize - ptr as usize }, 8usize, concat!( "Offset of field: ", stringify!(if_packet_stats), "::", stringify!(ifi_tcp_unspecv6) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifi_tcp_synfin) as usize - ptr as usize }, 16usize, concat!( "Offset of field: ", stringify!(if_packet_stats), "::", stringify!(ifi_tcp_synfin) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifi_tcp_badformatipsec) as usize - ptr as usize }, 24usize, concat!( "Offset of field: ", stringify!(if_packet_stats), "::", stringify!(ifi_tcp_badformatipsec) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifi_tcp_noconnnolist) as usize - ptr as usize }, 32usize, concat!( "Offset of field: ", stringify!(if_packet_stats), "::", stringify!(ifi_tcp_noconnnolist) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifi_tcp_noconnlist) as usize - ptr as usize }, 40usize, concat!( "Offset of field: ", stringify!(if_packet_stats), "::", stringify!(ifi_tcp_noconnlist) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifi_tcp_listbadsyn) as usize - ptr as usize }, 48usize, concat!( "Offset of field: ", stringify!(if_packet_stats), "::", stringify!(ifi_tcp_listbadsyn) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifi_tcp_icmp6unreach) as usize - ptr as usize }, 56usize, concat!( "Offset of field: ", stringify!(if_packet_stats), "::", stringify!(ifi_tcp_icmp6unreach) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifi_tcp_deprecate6) as usize - ptr as usize }, 64usize, concat!( "Offset of field: ", stringify!(if_packet_stats), "::", stringify!(ifi_tcp_deprecate6) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifi_tcp_rstinsynrcv) as usize - ptr as usize }, 72usize, concat!( "Offset of field: ", stringify!(if_packet_stats), "::", stringify!(ifi_tcp_rstinsynrcv) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifi_tcp_ooopacket) as usize - ptr as usize }, 80usize, concat!( "Offset of field: ", stringify!(if_packet_stats), "::", stringify!(ifi_tcp_ooopacket) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifi_tcp_dospacket) as usize - ptr as usize }, 88usize, concat!( "Offset of field: ", stringify!(if_packet_stats), "::", stringify!(ifi_tcp_dospacket) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifi_tcp_cleanup) as usize - ptr as usize }, 96usize, concat!( "Offset of field: ", stringify!(if_packet_stats), "::", stringify!(ifi_tcp_cleanup) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifi_tcp_synwindow) as usize - ptr as usize }, 104usize, concat!( "Offset of field: ", stringify!(if_packet_stats), "::", stringify!(ifi_tcp_synwindow) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).reserved) as usize - ptr as usize }, 112usize, concat!( "Offset of field: ", stringify!(if_packet_stats), "::", stringify!(reserved) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifi_udp_port_unreach) as usize - ptr as usize }, 160usize, concat!( "Offset of field: ", stringify!(if_packet_stats), "::", stringify!(ifi_udp_port_unreach) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifi_udp_faithprefix) as usize - ptr as usize }, 168usize, concat!( "Offset of field: ", stringify!(if_packet_stats), "::", stringify!(ifi_udp_faithprefix) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifi_udp_port0) as usize - ptr as usize }, 176usize, concat!( "Offset of field: ", stringify!(if_packet_stats), "::", stringify!(ifi_udp_port0) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifi_udp_badlength) as usize - ptr as usize }, 184usize, concat!( "Offset of field: ", stringify!(if_packet_stats), "::", stringify!(ifi_udp_badlength) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifi_udp_badchksum) as usize - ptr as usize }, 192usize, concat!( "Offset of field: ", stringify!(if_packet_stats), "::", stringify!(ifi_udp_badchksum) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifi_udp_badmcast) as usize - ptr as usize }, 200usize, concat!( "Offset of field: ", stringify!(if_packet_stats), "::", stringify!(ifi_udp_badmcast) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifi_udp_cleanup) as usize - ptr as usize }, 208usize, concat!( "Offset of field: ", stringify!(if_packet_stats), "::", stringify!(ifi_udp_cleanup) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifi_udp_badipsec) as usize - ptr as usize }, 216usize, concat!( "Offset of field: ", stringify!(if_packet_stats), "::", stringify!(ifi_udp_badipsec) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr)._reserved) as usize - ptr as usize }, 224usize, concat!( "Offset of field: ", stringify!(if_packet_stats), "::", stringify!(_reserved) ) ); } #[repr(C, packed(4))] #[derive(Debug, Copy, Clone)] pub struct if_description { pub ifd_maxlen: u_int32_t, pub ifd_len: u_int32_t, pub ifd_desc: *mut u_int8_t, } #[test] fn bindgen_test_layout_if_description() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 16usize, concat!("Size of: ", stringify!(if_description)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(if_description)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifd_maxlen) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(if_description), "::", stringify!(ifd_maxlen) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifd_len) as usize - ptr as usize }, 4usize, concat!( "Offset of field: ", stringify!(if_description), "::", stringify!(ifd_len) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifd_desc) as usize - ptr as usize }, 8usize, concat!( "Offset of field: ", stringify!(if_description), "::", stringify!(ifd_desc) ) ); } #[repr(C, packed(4))] #[derive(Debug, Copy, Clone)] pub struct if_bandwidths { pub eff_bw: u64, pub max_bw: u64, } #[test] fn bindgen_test_layout_if_bandwidths() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 16usize, concat!("Size of: ", stringify!(if_bandwidths)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(if_bandwidths)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).eff_bw) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(if_bandwidths), "::", stringify!(eff_bw)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).max_bw) as usize - ptr as usize }, 8usize, concat!("Offset of field: ", stringify!(if_bandwidths), "::", stringify!(max_bw)) ); } #[repr(C, packed(4))] #[derive(Debug, Copy, Clone)] pub struct if_latencies { pub eff_lt: u_int64_t, pub max_lt: u_int64_t, } #[test] fn bindgen_test_layout_if_latencies() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 16usize, concat!("Size of: ", stringify!(if_latencies)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(if_latencies)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).eff_lt) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(if_latencies), "::", stringify!(eff_lt)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).max_lt) as usize - ptr as usize }, 8usize, concat!("Offset of field: ", stringify!(if_latencies), "::", stringify!(max_lt)) ); } #[repr(C, packed(4))] #[derive(Debug, Copy, Clone)] pub struct if_netem_params { pub ifnetem_bandwidth_bps: u64, pub ifnetem_latency_ms: u32, pub ifnetem_jitter_ms: u32, pub ifnetem_corruption_p: u32, pub ifnetem_duplication_p: u32, pub ifnetem_loss_p_gr_gl: u32, pub ifnetem_loss_p_gr_bl: u32, pub ifnetem_loss_p_bl_br: u32, pub ifnetem_loss_p_bl_gr: u32, pub ifnetem_loss_p_br_bl: u32, pub ifnetem_reordering_p: u32, } #[test] fn bindgen_test_layout_if_netem_params() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 48usize, concat!("Size of: ", stringify!(if_netem_params)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(if_netem_params)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifnetem_bandwidth_bps) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(if_netem_params), "::", stringify!(ifnetem_bandwidth_bps) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifnetem_latency_ms) as usize - ptr as usize }, 8usize, concat!( "Offset of field: ", stringify!(if_netem_params), "::", stringify!(ifnetem_latency_ms) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifnetem_jitter_ms) as usize - ptr as usize }, 12usize, concat!( "Offset of field: ", stringify!(if_netem_params), "::", stringify!(ifnetem_jitter_ms) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifnetem_corruption_p) as usize - ptr as usize }, 16usize, concat!( "Offset of field: ", stringify!(if_netem_params), "::", stringify!(ifnetem_corruption_p) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifnetem_duplication_p) as usize - ptr as usize }, 20usize, concat!( "Offset of field: ", stringify!(if_netem_params), "::", stringify!(ifnetem_duplication_p) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifnetem_loss_p_gr_gl) as usize - ptr as usize }, 24usize, concat!( "Offset of field: ", stringify!(if_netem_params), "::", stringify!(ifnetem_loss_p_gr_gl) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifnetem_loss_p_gr_bl) as usize - ptr as usize }, 28usize, concat!( "Offset of field: ", stringify!(if_netem_params), "::", stringify!(ifnetem_loss_p_gr_bl) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifnetem_loss_p_bl_br) as usize - ptr as usize }, 32usize, concat!( "Offset of field: ", stringify!(if_netem_params), "::", stringify!(ifnetem_loss_p_bl_br) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifnetem_loss_p_bl_gr) as usize - ptr as usize }, 36usize, concat!( "Offset of field: ", stringify!(if_netem_params), "::", stringify!(ifnetem_loss_p_bl_gr) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifnetem_loss_p_br_bl) as usize - ptr as usize }, 40usize, concat!( "Offset of field: ", stringify!(if_netem_params), "::", stringify!(ifnetem_loss_p_br_bl) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifnetem_reordering_p) as usize - ptr as usize }, 44usize, concat!( "Offset of field: ", stringify!(if_netem_params), "::", stringify!(ifnetem_reordering_p) ) ); } #[repr(C, packed(4))] #[derive(Debug, Copy, Clone)] pub struct if_rxpoll_stats { pub ifi_poll_off_req: u_int32_t, pub ifi_poll_off_err: u_int32_t, pub ifi_poll_on_req: u_int32_t, pub ifi_poll_on_err: u_int32_t, pub ifi_poll_wakeups_avg: u_int32_t, pub ifi_poll_wakeups_lowat: u_int32_t, pub ifi_poll_wakeups_hiwat: u_int32_t, pub ifi_poll_packets: u_int64_t, pub ifi_poll_packets_avg: u_int32_t, pub ifi_poll_packets_min: u_int32_t, pub ifi_poll_packets_max: u_int32_t, pub ifi_poll_packets_lowat: u_int32_t, pub ifi_poll_packets_hiwat: u_int32_t, pub ifi_poll_bytes: u_int64_t, pub ifi_poll_bytes_avg: u_int32_t, pub ifi_poll_bytes_min: u_int32_t, pub ifi_poll_bytes_max: u_int32_t, pub ifi_poll_bytes_lowat: u_int32_t, pub ifi_poll_bytes_hiwat: u_int32_t, pub ifi_poll_packets_limit: u_int32_t, pub ifi_poll_interval_time: u_int64_t, } #[test] fn bindgen_test_layout_if_rxpoll_stats() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 96usize, concat!("Size of: ", stringify!(if_rxpoll_stats)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(if_rxpoll_stats)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifi_poll_off_req) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(if_rxpoll_stats), "::", stringify!(ifi_poll_off_req) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifi_poll_off_err) as usize - ptr as usize }, 4usize, concat!( "Offset of field: ", stringify!(if_rxpoll_stats), "::", stringify!(ifi_poll_off_err) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifi_poll_on_req) as usize - ptr as usize }, 8usize, concat!( "Offset of field: ", stringify!(if_rxpoll_stats), "::", stringify!(ifi_poll_on_req) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifi_poll_on_err) as usize - ptr as usize }, 12usize, concat!( "Offset of field: ", stringify!(if_rxpoll_stats), "::", stringify!(ifi_poll_on_err) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifi_poll_wakeups_avg) as usize - ptr as usize }, 16usize, concat!( "Offset of field: ", stringify!(if_rxpoll_stats), "::", stringify!(ifi_poll_wakeups_avg) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifi_poll_wakeups_lowat) as usize - ptr as usize }, 20usize, concat!( "Offset of field: ", stringify!(if_rxpoll_stats), "::", stringify!(ifi_poll_wakeups_lowat) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifi_poll_wakeups_hiwat) as usize - ptr as usize }, 24usize, concat!( "Offset of field: ", stringify!(if_rxpoll_stats), "::", stringify!(ifi_poll_wakeups_hiwat) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifi_poll_packets) as usize - ptr as usize }, 28usize, concat!( "Offset of field: ", stringify!(if_rxpoll_stats), "::", stringify!(ifi_poll_packets) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifi_poll_packets_avg) as usize - ptr as usize }, 36usize, concat!( "Offset of field: ", stringify!(if_rxpoll_stats), "::", stringify!(ifi_poll_packets_avg) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifi_poll_packets_min) as usize - ptr as usize }, 40usize, concat!( "Offset of field: ", stringify!(if_rxpoll_stats), "::", stringify!(ifi_poll_packets_min) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifi_poll_packets_max) as usize - ptr as usize }, 44usize, concat!( "Offset of field: ", stringify!(if_rxpoll_stats), "::", stringify!(ifi_poll_packets_max) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifi_poll_packets_lowat) as usize - ptr as usize }, 48usize, concat!( "Offset of field: ", stringify!(if_rxpoll_stats), "::", stringify!(ifi_poll_packets_lowat) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifi_poll_packets_hiwat) as usize - ptr as usize }, 52usize, concat!( "Offset of field: ", stringify!(if_rxpoll_stats), "::", stringify!(ifi_poll_packets_hiwat) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifi_poll_bytes) as usize - ptr as usize }, 56usize, concat!( "Offset of field: ", stringify!(if_rxpoll_stats), "::", stringify!(ifi_poll_bytes) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifi_poll_bytes_avg) as usize - ptr as usize }, 64usize, concat!( "Offset of field: ", stringify!(if_rxpoll_stats), "::", stringify!(ifi_poll_bytes_avg) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifi_poll_bytes_min) as usize - ptr as usize }, 68usize, concat!( "Offset of field: ", stringify!(if_rxpoll_stats), "::", stringify!(ifi_poll_bytes_min) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifi_poll_bytes_max) as usize - ptr as usize }, 72usize, concat!( "Offset of field: ", stringify!(if_rxpoll_stats), "::", stringify!(ifi_poll_bytes_max) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifi_poll_bytes_lowat) as usize - ptr as usize }, 76usize, concat!( "Offset of field: ", stringify!(if_rxpoll_stats), "::", stringify!(ifi_poll_bytes_lowat) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifi_poll_bytes_hiwat) as usize - ptr as usize }, 80usize, concat!( "Offset of field: ", stringify!(if_rxpoll_stats), "::", stringify!(ifi_poll_bytes_hiwat) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifi_poll_packets_limit) as usize - ptr as usize }, 84usize, concat!( "Offset of field: ", stringify!(if_rxpoll_stats), "::", stringify!(ifi_poll_packets_limit) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifi_poll_interval_time) as usize - ptr as usize }, 88usize, concat!( "Offset of field: ", stringify!(if_rxpoll_stats), "::", stringify!(ifi_poll_interval_time) ) ); } #[repr(C, packed(4))] #[derive(Debug, Copy, Clone)] pub struct if_netif_stats { pub ifn_rx_mit_interval: u_int64_t, pub ifn_rx_mit_mode: u_int32_t, pub ifn_rx_mit_packets_avg: u_int32_t, pub ifn_rx_mit_packets_min: u_int32_t, pub ifn_rx_mit_packets_max: u_int32_t, pub ifn_rx_mit_bytes_avg: u_int32_t, pub ifn_rx_mit_bytes_min: u_int32_t, pub ifn_rx_mit_bytes_max: u_int32_t, pub ifn_rx_mit_cfg_idx: u_int32_t, pub ifn_rx_mit_cfg_packets_lowat: u_int32_t, pub ifn_rx_mit_cfg_packets_hiwat: u_int32_t, pub ifn_rx_mit_cfg_bytes_lowat: u_int32_t, pub ifn_rx_mit_cfg_bytes_hiwat: u_int32_t, pub ifn_rx_mit_cfg_interval: u_int32_t, } #[test] fn bindgen_test_layout_if_netif_stats() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 60usize, concat!("Size of: ", stringify!(if_netif_stats)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(if_netif_stats)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifn_rx_mit_interval) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(if_netif_stats), "::", stringify!(ifn_rx_mit_interval) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifn_rx_mit_mode) as usize - ptr as usize }, 8usize, concat!( "Offset of field: ", stringify!(if_netif_stats), "::", stringify!(ifn_rx_mit_mode) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifn_rx_mit_packets_avg) as usize - ptr as usize }, 12usize, concat!( "Offset of field: ", stringify!(if_netif_stats), "::", stringify!(ifn_rx_mit_packets_avg) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifn_rx_mit_packets_min) as usize - ptr as usize }, 16usize, concat!( "Offset of field: ", stringify!(if_netif_stats), "::", stringify!(ifn_rx_mit_packets_min) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifn_rx_mit_packets_max) as usize - ptr as usize }, 20usize, concat!( "Offset of field: ", stringify!(if_netif_stats), "::", stringify!(ifn_rx_mit_packets_max) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifn_rx_mit_bytes_avg) as usize - ptr as usize }, 24usize, concat!( "Offset of field: ", stringify!(if_netif_stats), "::", stringify!(ifn_rx_mit_bytes_avg) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifn_rx_mit_bytes_min) as usize - ptr as usize }, 28usize, concat!( "Offset of field: ", stringify!(if_netif_stats), "::", stringify!(ifn_rx_mit_bytes_min) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifn_rx_mit_bytes_max) as usize - ptr as usize }, 32usize, concat!( "Offset of field: ", stringify!(if_netif_stats), "::", stringify!(ifn_rx_mit_bytes_max) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifn_rx_mit_cfg_idx) as usize - ptr as usize }, 36usize, concat!( "Offset of field: ", stringify!(if_netif_stats), "::", stringify!(ifn_rx_mit_cfg_idx) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifn_rx_mit_cfg_packets_lowat) as usize - ptr as usize }, 40usize, concat!( "Offset of field: ", stringify!(if_netif_stats), "::", stringify!(ifn_rx_mit_cfg_packets_lowat) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifn_rx_mit_cfg_packets_hiwat) as usize - ptr as usize }, 44usize, concat!( "Offset of field: ", stringify!(if_netif_stats), "::", stringify!(ifn_rx_mit_cfg_packets_hiwat) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifn_rx_mit_cfg_bytes_lowat) as usize - ptr as usize }, 48usize, concat!( "Offset of field: ", stringify!(if_netif_stats), "::", stringify!(ifn_rx_mit_cfg_bytes_lowat) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifn_rx_mit_cfg_bytes_hiwat) as usize - ptr as usize }, 52usize, concat!( "Offset of field: ", stringify!(if_netif_stats), "::", stringify!(ifn_rx_mit_cfg_bytes_hiwat) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifn_rx_mit_cfg_interval) as usize - ptr as usize }, 56usize, concat!( "Offset of field: ", stringify!(if_netif_stats), "::", stringify!(ifn_rx_mit_cfg_interval) ) ); } #[repr(C, packed(4))] #[derive(Debug, Copy, Clone)] pub struct if_tcp_ecn_perf_stat { pub total_txpkts: u_int64_t, pub total_rxmitpkts: u_int64_t, pub total_rxpkts: u_int64_t, pub total_oopkts: u_int64_t, pub total_reorderpkts: u_int64_t, pub rtt_avg: u_int64_t, pub rtt_var: u_int64_t, pub sack_episodes: u_int64_t, pub rxmit_drop: u_int64_t, pub rst_drop: u_int64_t, pub oo_percent: u_int64_t, pub reorder_percent: u_int64_t, pub rxmit_percent: u_int64_t, } #[test] fn bindgen_test_layout_if_tcp_ecn_perf_stat() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 104usize, concat!("Size of: ", stringify!(if_tcp_ecn_perf_stat)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(if_tcp_ecn_perf_stat)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).total_txpkts) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(if_tcp_ecn_perf_stat), "::", stringify!(total_txpkts) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).total_rxmitpkts) as usize - ptr as usize }, 8usize, concat!( "Offset of field: ", stringify!(if_tcp_ecn_perf_stat), "::", stringify!(total_rxmitpkts) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).total_rxpkts) as usize - ptr as usize }, 16usize, concat!( "Offset of field: ", stringify!(if_tcp_ecn_perf_stat), "::", stringify!(total_rxpkts) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).total_oopkts) as usize - ptr as usize }, 24usize, concat!( "Offset of field: ", stringify!(if_tcp_ecn_perf_stat), "::", stringify!(total_oopkts) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).total_reorderpkts) as usize - ptr as usize }, 32usize, concat!( "Offset of field: ", stringify!(if_tcp_ecn_perf_stat), "::", stringify!(total_reorderpkts) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rtt_avg) as usize - ptr as usize }, 40usize, concat!( "Offset of field: ", stringify!(if_tcp_ecn_perf_stat), "::", stringify!(rtt_avg) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rtt_var) as usize - ptr as usize }, 48usize, concat!( "Offset of field: ", stringify!(if_tcp_ecn_perf_stat), "::", stringify!(rtt_var) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).sack_episodes) as usize - ptr as usize }, 56usize, concat!( "Offset of field: ", stringify!(if_tcp_ecn_perf_stat), "::", stringify!(sack_episodes) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rxmit_drop) as usize - ptr as usize }, 64usize, concat!( "Offset of field: ", stringify!(if_tcp_ecn_perf_stat), "::", stringify!(rxmit_drop) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rst_drop) as usize - ptr as usize }, 72usize, concat!( "Offset of field: ", stringify!(if_tcp_ecn_perf_stat), "::", stringify!(rst_drop) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).oo_percent) as usize - ptr as usize }, 80usize, concat!( "Offset of field: ", stringify!(if_tcp_ecn_perf_stat), "::", stringify!(oo_percent) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).reorder_percent) as usize - ptr as usize }, 88usize, concat!( "Offset of field: ", stringify!(if_tcp_ecn_perf_stat), "::", stringify!(reorder_percent) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rxmit_percent) as usize - ptr as usize }, 96usize, concat!( "Offset of field: ", stringify!(if_tcp_ecn_perf_stat), "::", stringify!(rxmit_percent) ) ); } #[repr(C, packed(4))] #[derive(Debug, Copy, Clone)] pub struct if_tcp_ecn_stat { pub timestamp: u_int64_t, pub ecn_client_setup: u_int64_t, pub ecn_server_setup: u_int64_t, pub ecn_client_success: u_int64_t, pub ecn_server_success: u_int64_t, pub ecn_peer_nosupport: u_int64_t, pub ecn_syn_lost: u_int64_t, pub ecn_synack_lost: u_int64_t, pub ecn_recv_ce: u_int64_t, pub ecn_recv_ece: u_int64_t, pub ecn_conn_recv_ce: u_int64_t, pub ecn_conn_recv_ece: u_int64_t, pub ecn_conn_plnoce: u_int64_t, pub ecn_conn_plce: u_int64_t, pub ecn_conn_noplce: u_int64_t, pub ecn_fallback_synloss: u_int64_t, pub ecn_fallback_reorder: u_int64_t, pub ecn_fallback_ce: u_int64_t, pub ecn_off_conn: u_int64_t, pub ecn_total_conn: u_int64_t, pub ecn_fallback_droprst: u_int64_t, pub ecn_fallback_droprxmt: u_int64_t, pub ecn_fallback_synrst: u_int64_t, pub ecn_on: if_tcp_ecn_perf_stat, pub ecn_off: if_tcp_ecn_perf_stat, } #[test] fn bindgen_test_layout_if_tcp_ecn_stat() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 392usize, concat!("Size of: ", stringify!(if_tcp_ecn_stat)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(if_tcp_ecn_stat)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).timestamp) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(if_tcp_ecn_stat), "::", stringify!(timestamp) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ecn_client_setup) as usize - ptr as usize }, 8usize, concat!( "Offset of field: ", stringify!(if_tcp_ecn_stat), "::", stringify!(ecn_client_setup) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ecn_server_setup) as usize - ptr as usize }, 16usize, concat!( "Offset of field: ", stringify!(if_tcp_ecn_stat), "::", stringify!(ecn_server_setup) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ecn_client_success) as usize - ptr as usize }, 24usize, concat!( "Offset of field: ", stringify!(if_tcp_ecn_stat), "::", stringify!(ecn_client_success) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ecn_server_success) as usize - ptr as usize }, 32usize, concat!( "Offset of field: ", stringify!(if_tcp_ecn_stat), "::", stringify!(ecn_server_success) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ecn_peer_nosupport) as usize - ptr as usize }, 40usize, concat!( "Offset of field: ", stringify!(if_tcp_ecn_stat), "::", stringify!(ecn_peer_nosupport) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ecn_syn_lost) as usize - ptr as usize }, 48usize, concat!( "Offset of field: ", stringify!(if_tcp_ecn_stat), "::", stringify!(ecn_syn_lost) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ecn_synack_lost) as usize - ptr as usize }, 56usize, concat!( "Offset of field: ", stringify!(if_tcp_ecn_stat), "::", stringify!(ecn_synack_lost) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ecn_recv_ce) as usize - ptr as usize }, 64usize, concat!( "Offset of field: ", stringify!(if_tcp_ecn_stat), "::", stringify!(ecn_recv_ce) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ecn_recv_ece) as usize - ptr as usize }, 72usize, concat!( "Offset of field: ", stringify!(if_tcp_ecn_stat), "::", stringify!(ecn_recv_ece) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ecn_conn_recv_ce) as usize - ptr as usize }, 80usize, concat!( "Offset of field: ", stringify!(if_tcp_ecn_stat), "::", stringify!(ecn_conn_recv_ce) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ecn_conn_recv_ece) as usize - ptr as usize }, 88usize, concat!( "Offset of field: ", stringify!(if_tcp_ecn_stat), "::", stringify!(ecn_conn_recv_ece) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ecn_conn_plnoce) as usize - ptr as usize }, 96usize, concat!( "Offset of field: ", stringify!(if_tcp_ecn_stat), "::", stringify!(ecn_conn_plnoce) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ecn_conn_plce) as usize - ptr as usize }, 104usize, concat!( "Offset of field: ", stringify!(if_tcp_ecn_stat), "::", stringify!(ecn_conn_plce) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ecn_conn_noplce) as usize - ptr as usize }, 112usize, concat!( "Offset of field: ", stringify!(if_tcp_ecn_stat), "::", stringify!(ecn_conn_noplce) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ecn_fallback_synloss) as usize - ptr as usize }, 120usize, concat!( "Offset of field: ", stringify!(if_tcp_ecn_stat), "::", stringify!(ecn_fallback_synloss) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ecn_fallback_reorder) as usize - ptr as usize }, 128usize, concat!( "Offset of field: ", stringify!(if_tcp_ecn_stat), "::", stringify!(ecn_fallback_reorder) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ecn_fallback_ce) as usize - ptr as usize }, 136usize, concat!( "Offset of field: ", stringify!(if_tcp_ecn_stat), "::", stringify!(ecn_fallback_ce) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ecn_off_conn) as usize - ptr as usize }, 144usize, concat!( "Offset of field: ", stringify!(if_tcp_ecn_stat), "::", stringify!(ecn_off_conn) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ecn_total_conn) as usize - ptr as usize }, 152usize, concat!( "Offset of field: ", stringify!(if_tcp_ecn_stat), "::", stringify!(ecn_total_conn) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ecn_fallback_droprst) as usize - ptr as usize }, 160usize, concat!( "Offset of field: ", stringify!(if_tcp_ecn_stat), "::", stringify!(ecn_fallback_droprst) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ecn_fallback_droprxmt) as usize - ptr as usize }, 168usize, concat!( "Offset of field: ", stringify!(if_tcp_ecn_stat), "::", stringify!(ecn_fallback_droprxmt) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ecn_fallback_synrst) as usize - ptr as usize }, 176usize, concat!( "Offset of field: ", stringify!(if_tcp_ecn_stat), "::", stringify!(ecn_fallback_synrst) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ecn_on) as usize - ptr as usize }, 184usize, concat!( "Offset of field: ", stringify!(if_tcp_ecn_stat), "::", stringify!(ecn_on) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ecn_off) as usize - ptr as usize }, 288usize, concat!( "Offset of field: ", stringify!(if_tcp_ecn_stat), "::", stringify!(ecn_off) ) ); } #[repr(C, packed(4))] #[derive(Debug, Copy, Clone)] pub struct if_lim_perf_stat { pub lim_dl_max_bandwidth: u_int64_t, pub lim_ul_max_bandwidth: u_int64_t, pub lim_total_txpkts: u_int64_t, pub lim_total_rxpkts: u_int64_t, pub lim_total_retxpkts: u_int64_t, pub lim_packet_loss_percent: u_int64_t, pub lim_total_oopkts: u_int64_t, pub lim_packet_ooo_percent: u_int64_t, pub lim_rtt_variance: u_int64_t, pub lim_rtt_average: u_int64_t, pub lim_rtt_min: u_int64_t, pub lim_conn_timeouts: u_int64_t, pub lim_conn_attempts: u_int64_t, pub lim_conn_timeout_percent: u_int64_t, pub lim_bk_txpkts: u_int64_t, pub _bitfield_align_1: [u8; 0], pub _bitfield_1: __BindgenBitfieldUnit<[u8; 1usize]>, pub __bindgen_padding_0: [u8; 3usize], } #[test] fn bindgen_test_layout_if_lim_perf_stat() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 124usize, concat!("Size of: ", stringify!(if_lim_perf_stat)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(if_lim_perf_stat)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).lim_dl_max_bandwidth) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(if_lim_perf_stat), "::", stringify!(lim_dl_max_bandwidth) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).lim_ul_max_bandwidth) as usize - ptr as usize }, 8usize, concat!( "Offset of field: ", stringify!(if_lim_perf_stat), "::", stringify!(lim_ul_max_bandwidth) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).lim_total_txpkts) as usize - ptr as usize }, 16usize, concat!( "Offset of field: ", stringify!(if_lim_perf_stat), "::", stringify!(lim_total_txpkts) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).lim_total_rxpkts) as usize - ptr as usize }, 24usize, concat!( "Offset of field: ", stringify!(if_lim_perf_stat), "::", stringify!(lim_total_rxpkts) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).lim_total_retxpkts) as usize - ptr as usize }, 32usize, concat!( "Offset of field: ", stringify!(if_lim_perf_stat), "::", stringify!(lim_total_retxpkts) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).lim_packet_loss_percent) as usize - ptr as usize }, 40usize, concat!( "Offset of field: ", stringify!(if_lim_perf_stat), "::", stringify!(lim_packet_loss_percent) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).lim_total_oopkts) as usize - ptr as usize }, 48usize, concat!( "Offset of field: ", stringify!(if_lim_perf_stat), "::", stringify!(lim_total_oopkts) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).lim_packet_ooo_percent) as usize - ptr as usize }, 56usize, concat!( "Offset of field: ", stringify!(if_lim_perf_stat), "::", stringify!(lim_packet_ooo_percent) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).lim_rtt_variance) as usize - ptr as usize }, 64usize, concat!( "Offset of field: ", stringify!(if_lim_perf_stat), "::", stringify!(lim_rtt_variance) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).lim_rtt_average) as usize - ptr as usize }, 72usize, concat!( "Offset of field: ", stringify!(if_lim_perf_stat), "::", stringify!(lim_rtt_average) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).lim_rtt_min) as usize - ptr as usize }, 80usize, concat!( "Offset of field: ", stringify!(if_lim_perf_stat), "::", stringify!(lim_rtt_min) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).lim_conn_timeouts) as usize - ptr as usize }, 88usize, concat!( "Offset of field: ", stringify!(if_lim_perf_stat), "::", stringify!(lim_conn_timeouts) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).lim_conn_attempts) as usize - ptr as usize }, 96usize, concat!( "Offset of field: ", stringify!(if_lim_perf_stat), "::", stringify!(lim_conn_attempts) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).lim_conn_timeout_percent) as usize - ptr as usize }, 104usize, concat!( "Offset of field: ", stringify!(if_lim_perf_stat), "::", stringify!(lim_conn_timeout_percent) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).lim_bk_txpkts) as usize - ptr as usize }, 112usize, concat!( "Offset of field: ", stringify!(if_lim_perf_stat), "::", stringify!(lim_bk_txpkts) ) ); } impl if_lim_perf_stat { #[inline] pub fn lim_dl_detected(&self) -> u_int64_t { unsafe { ::std::mem::transmute(self._bitfield_1.get(0usize, 1u8) as u64) } } #[inline] pub fn set_lim_dl_detected(&mut self, val: u_int64_t) { unsafe { let val: u64 = ::std::mem::transmute(val); self._bitfield_1.set(0usize, 1u8, val as u64) } } #[inline] pub fn lim_ul_detected(&self) -> u_int64_t { unsafe { ::std::mem::transmute(self._bitfield_1.get(1usize, 1u8) as u64) } } #[inline] pub fn set_lim_ul_detected(&mut self, val: u_int64_t) { unsafe { let val: u64 = ::std::mem::transmute(val); self._bitfield_1.set(1usize, 1u8, val as u64) } } #[inline] pub fn new_bitfield_1( lim_dl_detected: u_int64_t, lim_ul_detected: u_int64_t, ) -> __BindgenBitfieldUnit<[u8; 1usize]> { let mut __bindgen_bitfield_unit: __BindgenBitfieldUnit<[u8; 1usize]> = Default::default(); __bindgen_bitfield_unit.set(0usize, 1u8, { let lim_dl_detected: u64 = unsafe { ::std::mem::transmute(lim_dl_detected) }; lim_dl_detected as u64 }); __bindgen_bitfield_unit.set(1usize, 1u8, { let lim_ul_detected: u64 = unsafe { ::std::mem::transmute(lim_ul_detected) }; lim_ul_detected as u64 }); __bindgen_bitfield_unit } } #[repr(C, packed(4))] #[derive(Debug, Copy, Clone)] pub struct ifnet_stats_per_flow { pub bk_txpackets: u_int64_t, pub txpackets: u_int64_t, pub rxpackets: u_int64_t, pub txretransmitbytes: u_int32_t, pub rxoutoforderbytes: u_int32_t, pub rxmitpkts: u_int32_t, pub rcvoopack: u_int32_t, pub pawsdrop: u_int32_t, pub sack_recovery_episodes: u_int32_t, pub reordered_pkts: u_int32_t, pub dsack_sent: u_int32_t, pub dsack_recvd: u_int32_t, pub srtt: u_int32_t, pub rttupdated: u_int32_t, pub rttvar: u_int32_t, pub rttmin: u_int32_t, pub bw_sndbw_max: u_int32_t, pub bw_rcvbw_max: u_int32_t, pub ecn_recv_ece: u_int32_t, pub ecn_recv_ce: u_int32_t, pub ecn_flags: u_int16_t, pub _bitfield_align_1: [u8; 0], pub _bitfield_1: __BindgenBitfieldUnit<[u8; 2usize]>, } #[test] fn bindgen_test_layout_ifnet_stats_per_flow() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 96usize, concat!("Size of: ", stringify!(ifnet_stats_per_flow)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(ifnet_stats_per_flow)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).bk_txpackets) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(ifnet_stats_per_flow), "::", stringify!(bk_txpackets) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).txpackets) as usize - ptr as usize }, 8usize, concat!( "Offset of field: ", stringify!(ifnet_stats_per_flow), "::", stringify!(txpackets) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rxpackets) as usize - ptr as usize }, 16usize, concat!( "Offset of field: ", stringify!(ifnet_stats_per_flow), "::", stringify!(rxpackets) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).txretransmitbytes) as usize - ptr as usize }, 24usize, concat!( "Offset of field: ", stringify!(ifnet_stats_per_flow), "::", stringify!(txretransmitbytes) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rxoutoforderbytes) as usize - ptr as usize }, 28usize, concat!( "Offset of field: ", stringify!(ifnet_stats_per_flow), "::", stringify!(rxoutoforderbytes) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rxmitpkts) as usize - ptr as usize }, 32usize, concat!( "Offset of field: ", stringify!(ifnet_stats_per_flow), "::", stringify!(rxmitpkts) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rcvoopack) as usize - ptr as usize }, 36usize, concat!( "Offset of field: ", stringify!(ifnet_stats_per_flow), "::", stringify!(rcvoopack) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pawsdrop) as usize - ptr as usize }, 40usize, concat!( "Offset of field: ", stringify!(ifnet_stats_per_flow), "::", stringify!(pawsdrop) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).sack_recovery_episodes) as usize - ptr as usize }, 44usize, concat!( "Offset of field: ", stringify!(ifnet_stats_per_flow), "::", stringify!(sack_recovery_episodes) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).reordered_pkts) as usize - ptr as usize }, 48usize, concat!( "Offset of field: ", stringify!(ifnet_stats_per_flow), "::", stringify!(reordered_pkts) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).dsack_sent) as usize - ptr as usize }, 52usize, concat!( "Offset of field: ", stringify!(ifnet_stats_per_flow), "::", stringify!(dsack_sent) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).dsack_recvd) as usize - ptr as usize }, 56usize, concat!( "Offset of field: ", stringify!(ifnet_stats_per_flow), "::", stringify!(dsack_recvd) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).srtt) as usize - ptr as usize }, 60usize, concat!( "Offset of field: ", stringify!(ifnet_stats_per_flow), "::", stringify!(srtt) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rttupdated) as usize - ptr as usize }, 64usize, concat!( "Offset of field: ", stringify!(ifnet_stats_per_flow), "::", stringify!(rttupdated) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rttvar) as usize - ptr as usize }, 68usize, concat!( "Offset of field: ", stringify!(ifnet_stats_per_flow), "::", stringify!(rttvar) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rttmin) as usize - ptr as usize }, 72usize, concat!( "Offset of field: ", stringify!(ifnet_stats_per_flow), "::", stringify!(rttmin) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).bw_sndbw_max) as usize - ptr as usize }, 76usize, concat!( "Offset of field: ", stringify!(ifnet_stats_per_flow), "::", stringify!(bw_sndbw_max) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).bw_rcvbw_max) as usize - ptr as usize }, 80usize, concat!( "Offset of field: ", stringify!(ifnet_stats_per_flow), "::", stringify!(bw_rcvbw_max) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ecn_recv_ece) as usize - ptr as usize }, 84usize, concat!( "Offset of field: ", stringify!(ifnet_stats_per_flow), "::", stringify!(ecn_recv_ece) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ecn_recv_ce) as usize - ptr as usize }, 88usize, concat!( "Offset of field: ", stringify!(ifnet_stats_per_flow), "::", stringify!(ecn_recv_ce) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ecn_flags) as usize - ptr as usize }, 92usize, concat!( "Offset of field: ", stringify!(ifnet_stats_per_flow), "::", stringify!(ecn_flags) ) ); } impl ifnet_stats_per_flow { #[inline] pub fn ipv4(&self) -> u_int16_t { unsafe { ::std::mem::transmute(self._bitfield_1.get(0usize, 1u8) as u16) } } #[inline] pub fn set_ipv4(&mut self, val: u_int16_t) { unsafe { let val: u16 = ::std::mem::transmute(val); self._bitfield_1.set(0usize, 1u8, val as u64) } } #[inline] pub fn local(&self) -> u_int16_t { unsafe { ::std::mem::transmute(self._bitfield_1.get(1usize, 1u8) as u16) } } #[inline] pub fn set_local(&mut self, val: u_int16_t) { unsafe { let val: u16 = ::std::mem::transmute(val); self._bitfield_1.set(1usize, 1u8, val as u64) } } #[inline] pub fn connreset(&self) -> u_int16_t { unsafe { ::std::mem::transmute(self._bitfield_1.get(2usize, 1u8) as u16) } } #[inline] pub fn set_connreset(&mut self, val: u_int16_t) { unsafe { let val: u16 = ::std::mem::transmute(val); self._bitfield_1.set(2usize, 1u8, val as u64) } } #[inline] pub fn conntimeout(&self) -> u_int16_t { unsafe { ::std::mem::transmute(self._bitfield_1.get(3usize, 1u8) as u16) } } #[inline] pub fn set_conntimeout(&mut self, val: u_int16_t) { unsafe { let val: u16 = ::std::mem::transmute(val); self._bitfield_1.set(3usize, 1u8, val as u64) } } #[inline] pub fn rxmit_drop(&self) -> u_int16_t { unsafe { ::std::mem::transmute(self._bitfield_1.get(4usize, 1u8) as u16) } } #[inline] pub fn set_rxmit_drop(&mut self, val: u_int16_t) { unsafe { let val: u16 = ::std::mem::transmute(val); self._bitfield_1.set(4usize, 1u8, val as u64) } } #[inline] pub fn ecn_fallback_synloss(&self) -> u_int16_t { unsafe { ::std::mem::transmute(self._bitfield_1.get(5usize, 1u8) as u16) } } #[inline] pub fn set_ecn_fallback_synloss(&mut self, val: u_int16_t) { unsafe { let val: u16 = ::std::mem::transmute(val); self._bitfield_1.set(5usize, 1u8, val as u64) } } #[inline] pub fn ecn_fallback_droprst(&self) -> u_int16_t { unsafe { ::std::mem::transmute(self._bitfield_1.get(6usize, 1u8) as u16) } } #[inline] pub fn set_ecn_fallback_droprst(&mut self, val: u_int16_t) { unsafe { let val: u16 = ::std::mem::transmute(val); self._bitfield_1.set(6usize, 1u8, val as u64) } } #[inline] pub fn ecn_fallback_droprxmt(&self) -> u_int16_t { unsafe { ::std::mem::transmute(self._bitfield_1.get(7usize, 1u8) as u16) } } #[inline] pub fn set_ecn_fallback_droprxmt(&mut self, val: u_int16_t) { unsafe { let val: u16 = ::std::mem::transmute(val); self._bitfield_1.set(7usize, 1u8, val as u64) } } #[inline] pub fn ecn_fallback_ce(&self) -> u_int16_t { unsafe { ::std::mem::transmute(self._bitfield_1.get(8usize, 1u8) as u16) } } #[inline] pub fn set_ecn_fallback_ce(&mut self, val: u_int16_t) { unsafe { let val: u16 = ::std::mem::transmute(val); self._bitfield_1.set(8usize, 1u8, val as u64) } } #[inline] pub fn ecn_fallback_reorder(&self) -> u_int16_t { unsafe { ::std::mem::transmute(self._bitfield_1.get(9usize, 1u8) as u16) } } #[inline] pub fn set_ecn_fallback_reorder(&mut self, val: u_int16_t) { unsafe { let val: u16 = ::std::mem::transmute(val); self._bitfield_1.set(9usize, 1u8, val as u64) } } #[inline] pub fn new_bitfield_1( ipv4: u_int16_t, local: u_int16_t, connreset: u_int16_t, conntimeout: u_int16_t, rxmit_drop: u_int16_t, ecn_fallback_synloss: u_int16_t, ecn_fallback_droprst: u_int16_t, ecn_fallback_droprxmt: u_int16_t, ecn_fallback_ce: u_int16_t, ecn_fallback_reorder: u_int16_t, ) -> __BindgenBitfieldUnit<[u8; 2usize]> { let mut __bindgen_bitfield_unit: __BindgenBitfieldUnit<[u8; 2usize]> = Default::default(); __bindgen_bitfield_unit.set(0usize, 1u8, { let ipv4: u16 = unsafe { ::std::mem::transmute(ipv4) }; ipv4 as u64 }); __bindgen_bitfield_unit.set(1usize, 1u8, { let local: u16 = unsafe { ::std::mem::transmute(local) }; local as u64 }); __bindgen_bitfield_unit.set(2usize, 1u8, { let connreset: u16 = unsafe { ::std::mem::transmute(connreset) }; connreset as u64 }); __bindgen_bitfield_unit.set(3usize, 1u8, { let conntimeout: u16 = unsafe { ::std::mem::transmute(conntimeout) }; conntimeout as u64 }); __bindgen_bitfield_unit.set(4usize, 1u8, { let rxmit_drop: u16 = unsafe { ::std::mem::transmute(rxmit_drop) }; rxmit_drop as u64 }); __bindgen_bitfield_unit.set(5usize, 1u8, { let ecn_fallback_synloss: u16 = unsafe { ::std::mem::transmute(ecn_fallback_synloss) }; ecn_fallback_synloss as u64 }); __bindgen_bitfield_unit.set(6usize, 1u8, { let ecn_fallback_droprst: u16 = unsafe { ::std::mem::transmute(ecn_fallback_droprst) }; ecn_fallback_droprst as u64 }); __bindgen_bitfield_unit.set(7usize, 1u8, { let ecn_fallback_droprxmt: u16 = unsafe { ::std::mem::transmute(ecn_fallback_droprxmt) }; ecn_fallback_droprxmt as u64 }); __bindgen_bitfield_unit.set(8usize, 1u8, { let ecn_fallback_ce: u16 = unsafe { ::std::mem::transmute(ecn_fallback_ce) }; ecn_fallback_ce as u64 }); __bindgen_bitfield_unit.set(9usize, 1u8, { let ecn_fallback_reorder: u16 = unsafe { ::std::mem::transmute(ecn_fallback_reorder) }; ecn_fallback_reorder as u64 }); __bindgen_bitfield_unit } } #[repr(C, packed)] #[derive(Debug, Copy, Clone)] pub struct if_cellular_status_v1 { pub valid_bitmask: u_int32_t, pub link_quality_metric: u_int32_t, pub ul_effective_bandwidth: u_int32_t, pub ul_max_bandwidth: u_int32_t, pub ul_min_latency: u_int32_t, pub ul_effective_latency: u_int32_t, pub ul_max_latency: u_int32_t, pub ul_retxt_level: u_int32_t, pub ul_bytes_lost: u_int32_t, pub ul_min_queue_size: u_int32_t, pub ul_avg_queue_size: u_int32_t, pub ul_max_queue_size: u_int32_t, pub dl_effective_bandwidth: u_int32_t, pub dl_max_bandwidth: u_int32_t, pub config_inactivity_time: u_int32_t, pub config_backoff_time: u_int32_t, pub mss_recommended: u_int16_t, pub reserved_1: u_int16_t, pub reserved_2: u_int32_t, pub reserved_3: u_int64_t, pub reserved_4: u_int64_t, pub reserved_5: u_int64_t, pub reserved_6: u_int64_t, } #[test] fn bindgen_test_layout_if_cellular_status_v1() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 104usize, concat!("Size of: ", stringify!(if_cellular_status_v1)) ); assert_eq!( ::std::mem::align_of::(), 1usize, concat!("Alignment of ", stringify!(if_cellular_status_v1)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).valid_bitmask) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(if_cellular_status_v1), "::", stringify!(valid_bitmask) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).link_quality_metric) as usize - ptr as usize }, 4usize, concat!( "Offset of field: ", stringify!(if_cellular_status_v1), "::", stringify!(link_quality_metric) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ul_effective_bandwidth) as usize - ptr as usize }, 8usize, concat!( "Offset of field: ", stringify!(if_cellular_status_v1), "::", stringify!(ul_effective_bandwidth) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ul_max_bandwidth) as usize - ptr as usize }, 12usize, concat!( "Offset of field: ", stringify!(if_cellular_status_v1), "::", stringify!(ul_max_bandwidth) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ul_min_latency) as usize - ptr as usize }, 16usize, concat!( "Offset of field: ", stringify!(if_cellular_status_v1), "::", stringify!(ul_min_latency) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ul_effective_latency) as usize - ptr as usize }, 20usize, concat!( "Offset of field: ", stringify!(if_cellular_status_v1), "::", stringify!(ul_effective_latency) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ul_max_latency) as usize - ptr as usize }, 24usize, concat!( "Offset of field: ", stringify!(if_cellular_status_v1), "::", stringify!(ul_max_latency) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ul_retxt_level) as usize - ptr as usize }, 28usize, concat!( "Offset of field: ", stringify!(if_cellular_status_v1), "::", stringify!(ul_retxt_level) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ul_bytes_lost) as usize - ptr as usize }, 32usize, concat!( "Offset of field: ", stringify!(if_cellular_status_v1), "::", stringify!(ul_bytes_lost) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ul_min_queue_size) as usize - ptr as usize }, 36usize, concat!( "Offset of field: ", stringify!(if_cellular_status_v1), "::", stringify!(ul_min_queue_size) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ul_avg_queue_size) as usize - ptr as usize }, 40usize, concat!( "Offset of field: ", stringify!(if_cellular_status_v1), "::", stringify!(ul_avg_queue_size) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ul_max_queue_size) as usize - ptr as usize }, 44usize, concat!( "Offset of field: ", stringify!(if_cellular_status_v1), "::", stringify!(ul_max_queue_size) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).dl_effective_bandwidth) as usize - ptr as usize }, 48usize, concat!( "Offset of field: ", stringify!(if_cellular_status_v1), "::", stringify!(dl_effective_bandwidth) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).dl_max_bandwidth) as usize - ptr as usize }, 52usize, concat!( "Offset of field: ", stringify!(if_cellular_status_v1), "::", stringify!(dl_max_bandwidth) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).config_inactivity_time) as usize - ptr as usize }, 56usize, concat!( "Offset of field: ", stringify!(if_cellular_status_v1), "::", stringify!(config_inactivity_time) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).config_backoff_time) as usize - ptr as usize }, 60usize, concat!( "Offset of field: ", stringify!(if_cellular_status_v1), "::", stringify!(config_backoff_time) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).mss_recommended) as usize - ptr as usize }, 64usize, concat!( "Offset of field: ", stringify!(if_cellular_status_v1), "::", stringify!(mss_recommended) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).reserved_1) as usize - ptr as usize }, 66usize, concat!( "Offset of field: ", stringify!(if_cellular_status_v1), "::", stringify!(reserved_1) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).reserved_2) as usize - ptr as usize }, 68usize, concat!( "Offset of field: ", stringify!(if_cellular_status_v1), "::", stringify!(reserved_2) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).reserved_3) as usize - ptr as usize }, 72usize, concat!( "Offset of field: ", stringify!(if_cellular_status_v1), "::", stringify!(reserved_3) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).reserved_4) as usize - ptr as usize }, 80usize, concat!( "Offset of field: ", stringify!(if_cellular_status_v1), "::", stringify!(reserved_4) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).reserved_5) as usize - ptr as usize }, 88usize, concat!( "Offset of field: ", stringify!(if_cellular_status_v1), "::", stringify!(reserved_5) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).reserved_6) as usize - ptr as usize }, 96usize, concat!( "Offset of field: ", stringify!(if_cellular_status_v1), "::", stringify!(reserved_6) ) ); } #[repr(C)] #[derive(Copy, Clone)] pub struct if_cellular_status { pub if_cell_u: if_cellular_status__bindgen_ty_1, } #[repr(C)] #[derive(Copy, Clone)] pub union if_cellular_status__bindgen_ty_1 { pub if_status_v1: if_cellular_status_v1, } #[test] fn bindgen_test_layout_if_cellular_status__bindgen_ty_1() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 104usize, concat!("Size of: ", stringify!(if_cellular_status__bindgen_ty_1)) ); assert_eq!( ::std::mem::align_of::(), 1usize, concat!("Alignment of ", stringify!(if_cellular_status__bindgen_ty_1)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).if_status_v1) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(if_cellular_status__bindgen_ty_1), "::", stringify!(if_status_v1) ) ); } #[test] fn bindgen_test_layout_if_cellular_status() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 104usize, concat!("Size of: ", stringify!(if_cellular_status)) ); assert_eq!( ::std::mem::align_of::(), 1usize, concat!("Alignment of ", stringify!(if_cellular_status)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).if_cell_u) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(if_cellular_status), "::", stringify!(if_cell_u) ) ); } #[repr(C, packed)] #[derive(Debug, Copy, Clone)] pub struct if_wifi_status_v1 { pub valid_bitmask: u_int32_t, pub link_quality_metric: u_int32_t, pub ul_effective_bandwidth: u_int32_t, pub ul_max_bandwidth: u_int32_t, pub ul_min_latency: u_int32_t, pub ul_effective_latency: u_int32_t, pub ul_max_latency: u_int32_t, pub ul_retxt_level: u_int32_t, pub ul_bytes_lost: u_int32_t, pub ul_error_rate: u_int32_t, pub dl_effective_bandwidth: u_int32_t, pub dl_max_bandwidth: u_int32_t, pub dl_min_latency: u_int32_t, pub dl_effective_latency: u_int32_t, pub dl_max_latency: u_int32_t, pub dl_error_rate: u_int32_t, pub config_frequency: u_int32_t, pub config_multicast_rate: u_int32_t, pub scan_count: u_int32_t, pub scan_duration: u_int32_t, pub reserved_1: u_int64_t, pub reserved_2: u_int64_t, pub reserved_3: u_int64_t, pub reserved_4: u_int64_t, } #[test] fn bindgen_test_layout_if_wifi_status_v1() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 112usize, concat!("Size of: ", stringify!(if_wifi_status_v1)) ); assert_eq!( ::std::mem::align_of::(), 1usize, concat!("Alignment of ", stringify!(if_wifi_status_v1)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).valid_bitmask) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(if_wifi_status_v1), "::", stringify!(valid_bitmask) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).link_quality_metric) as usize - ptr as usize }, 4usize, concat!( "Offset of field: ", stringify!(if_wifi_status_v1), "::", stringify!(link_quality_metric) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ul_effective_bandwidth) as usize - ptr as usize }, 8usize, concat!( "Offset of field: ", stringify!(if_wifi_status_v1), "::", stringify!(ul_effective_bandwidth) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ul_max_bandwidth) as usize - ptr as usize }, 12usize, concat!( "Offset of field: ", stringify!(if_wifi_status_v1), "::", stringify!(ul_max_bandwidth) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ul_min_latency) as usize - ptr as usize }, 16usize, concat!( "Offset of field: ", stringify!(if_wifi_status_v1), "::", stringify!(ul_min_latency) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ul_effective_latency) as usize - ptr as usize }, 20usize, concat!( "Offset of field: ", stringify!(if_wifi_status_v1), "::", stringify!(ul_effective_latency) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ul_max_latency) as usize - ptr as usize }, 24usize, concat!( "Offset of field: ", stringify!(if_wifi_status_v1), "::", stringify!(ul_max_latency) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ul_retxt_level) as usize - ptr as usize }, 28usize, concat!( "Offset of field: ", stringify!(if_wifi_status_v1), "::", stringify!(ul_retxt_level) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ul_bytes_lost) as usize - ptr as usize }, 32usize, concat!( "Offset of field: ", stringify!(if_wifi_status_v1), "::", stringify!(ul_bytes_lost) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ul_error_rate) as usize - ptr as usize }, 36usize, concat!( "Offset of field: ", stringify!(if_wifi_status_v1), "::", stringify!(ul_error_rate) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).dl_effective_bandwidth) as usize - ptr as usize }, 40usize, concat!( "Offset of field: ", stringify!(if_wifi_status_v1), "::", stringify!(dl_effective_bandwidth) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).dl_max_bandwidth) as usize - ptr as usize }, 44usize, concat!( "Offset of field: ", stringify!(if_wifi_status_v1), "::", stringify!(dl_max_bandwidth) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).dl_min_latency) as usize - ptr as usize }, 48usize, concat!( "Offset of field: ", stringify!(if_wifi_status_v1), "::", stringify!(dl_min_latency) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).dl_effective_latency) as usize - ptr as usize }, 52usize, concat!( "Offset of field: ", stringify!(if_wifi_status_v1), "::", stringify!(dl_effective_latency) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).dl_max_latency) as usize - ptr as usize }, 56usize, concat!( "Offset of field: ", stringify!(if_wifi_status_v1), "::", stringify!(dl_max_latency) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).dl_error_rate) as usize - ptr as usize }, 60usize, concat!( "Offset of field: ", stringify!(if_wifi_status_v1), "::", stringify!(dl_error_rate) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).config_frequency) as usize - ptr as usize }, 64usize, concat!( "Offset of field: ", stringify!(if_wifi_status_v1), "::", stringify!(config_frequency) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).config_multicast_rate) as usize - ptr as usize }, 68usize, concat!( "Offset of field: ", stringify!(if_wifi_status_v1), "::", stringify!(config_multicast_rate) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).scan_count) as usize - ptr as usize }, 72usize, concat!( "Offset of field: ", stringify!(if_wifi_status_v1), "::", stringify!(scan_count) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).scan_duration) as usize - ptr as usize }, 76usize, concat!( "Offset of field: ", stringify!(if_wifi_status_v1), "::", stringify!(scan_duration) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).reserved_1) as usize - ptr as usize }, 80usize, concat!( "Offset of field: ", stringify!(if_wifi_status_v1), "::", stringify!(reserved_1) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).reserved_2) as usize - ptr as usize }, 88usize, concat!( "Offset of field: ", stringify!(if_wifi_status_v1), "::", stringify!(reserved_2) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).reserved_3) as usize - ptr as usize }, 96usize, concat!( "Offset of field: ", stringify!(if_wifi_status_v1), "::", stringify!(reserved_3) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).reserved_4) as usize - ptr as usize }, 104usize, concat!( "Offset of field: ", stringify!(if_wifi_status_v1), "::", stringify!(reserved_4) ) ); } #[repr(C)] #[derive(Copy, Clone)] pub struct if_wifi_status { pub if_wifi_u: if_wifi_status__bindgen_ty_1, } #[repr(C)] #[derive(Copy, Clone)] pub union if_wifi_status__bindgen_ty_1 { pub if_status_v1: if_wifi_status_v1, } #[test] fn bindgen_test_layout_if_wifi_status__bindgen_ty_1() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 112usize, concat!("Size of: ", stringify!(if_wifi_status__bindgen_ty_1)) ); assert_eq!( ::std::mem::align_of::(), 1usize, concat!("Alignment of ", stringify!(if_wifi_status__bindgen_ty_1)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).if_status_v1) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(if_wifi_status__bindgen_ty_1), "::", stringify!(if_status_v1) ) ); } #[test] fn bindgen_test_layout_if_wifi_status() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 112usize, concat!("Size of: ", stringify!(if_wifi_status)) ); assert_eq!( ::std::mem::align_of::(), 1usize, concat!("Alignment of ", stringify!(if_wifi_status)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).if_wifi_u) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(if_wifi_status), "::", stringify!(if_wifi_u) ) ); } #[repr(C)] #[derive(Copy, Clone)] pub struct if_link_status { pub ifsr_version: u_int32_t, pub ifsr_len: u_int32_t, pub ifsr_u: if_link_status__bindgen_ty_1, } #[repr(C)] #[derive(Copy, Clone)] pub union if_link_status__bindgen_ty_1 { pub ifsr_cell: if_cellular_status, pub ifsr_wifi: if_wifi_status, } #[test] fn bindgen_test_layout_if_link_status__bindgen_ty_1() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 112usize, concat!("Size of: ", stringify!(if_link_status__bindgen_ty_1)) ); assert_eq!( ::std::mem::align_of::(), 1usize, concat!("Alignment of ", stringify!(if_link_status__bindgen_ty_1)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifsr_cell) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(if_link_status__bindgen_ty_1), "::", stringify!(ifsr_cell) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifsr_wifi) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(if_link_status__bindgen_ty_1), "::", stringify!(ifsr_wifi) ) ); } #[test] fn bindgen_test_layout_if_link_status() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 120usize, concat!("Size of: ", stringify!(if_link_status)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(if_link_status)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifsr_version) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(if_link_status), "::", stringify!(ifsr_version) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifsr_len) as usize - ptr as usize }, 4usize, concat!( "Offset of field: ", stringify!(if_link_status), "::", stringify!(ifsr_len) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifsr_u) as usize - ptr as usize }, 8usize, concat!( "Offset of field: ", stringify!(if_link_status), "::", stringify!(ifsr_u) ) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct if_interface_state { pub valid_bitmask: u_int8_t, pub rrc_state: u_int8_t, pub lqm_state: i8, pub interface_availability: u_int8_t, } #[test] fn bindgen_test_layout_if_interface_state() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 4usize, concat!("Size of: ", stringify!(if_interface_state)) ); assert_eq!( ::std::mem::align_of::(), 1usize, concat!("Alignment of ", stringify!(if_interface_state)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).valid_bitmask) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(if_interface_state), "::", stringify!(valid_bitmask) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rrc_state) as usize - ptr as usize }, 1usize, concat!( "Offset of field: ", stringify!(if_interface_state), "::", stringify!(rrc_state) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).lqm_state) as usize - ptr as usize }, 2usize, concat!( "Offset of field: ", stringify!(if_interface_state), "::", stringify!(lqm_state) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).interface_availability) as usize - ptr as usize }, 3usize, concat!( "Offset of field: ", stringify!(if_interface_state), "::", stringify!(interface_availability) ) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct chain_len_stats { pub cls_one: u64, pub cls_two: u64, pub cls_three: u64, pub cls_four: u64, pub cls_five_or_more: u64, } #[test] fn bindgen_test_layout_chain_len_stats() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 40usize, concat!("Size of: ", stringify!(chain_len_stats)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(chain_len_stats)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).cls_one) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(chain_len_stats), "::", stringify!(cls_one) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).cls_two) as usize - ptr as usize }, 8usize, concat!( "Offset of field: ", stringify!(chain_len_stats), "::", stringify!(cls_two) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).cls_three) as usize - ptr as usize }, 16usize, concat!( "Offset of field: ", stringify!(chain_len_stats), "::", stringify!(cls_three) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).cls_four) as usize - ptr as usize }, 24usize, concat!( "Offset of field: ", stringify!(chain_len_stats), "::", stringify!(cls_four) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).cls_five_or_more) as usize - ptr as usize }, 32usize, concat!( "Offset of field: ", stringify!(chain_len_stats), "::", stringify!(cls_five_or_more) ) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct ifnet_interface_advisory { pub version: u8, pub direction: u8, pub _reserved: u16, pub rate_trend_suggestion: i32, pub timestamp: u64, pub max_bandwidth: u64, pub total_byte_count: u64, pub average_throughput: u64, pub flushable_queue_size: u32, pub non_flushable_queue_size: u32, pub average_delay: u32, } #[test] fn bindgen_test_layout_ifnet_interface_advisory() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 56usize, concat!("Size of: ", stringify!(ifnet_interface_advisory)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(ifnet_interface_advisory)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).version) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(ifnet_interface_advisory), "::", stringify!(version) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).direction) as usize - ptr as usize }, 1usize, concat!( "Offset of field: ", stringify!(ifnet_interface_advisory), "::", stringify!(direction) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr)._reserved) as usize - ptr as usize }, 2usize, concat!( "Offset of field: ", stringify!(ifnet_interface_advisory), "::", stringify!(_reserved) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rate_trend_suggestion) as usize - ptr as usize }, 4usize, concat!( "Offset of field: ", stringify!(ifnet_interface_advisory), "::", stringify!(rate_trend_suggestion) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).timestamp) as usize - ptr as usize }, 8usize, concat!( "Offset of field: ", stringify!(ifnet_interface_advisory), "::", stringify!(timestamp) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).max_bandwidth) as usize - ptr as usize }, 16usize, concat!( "Offset of field: ", stringify!(ifnet_interface_advisory), "::", stringify!(max_bandwidth) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).total_byte_count) as usize - ptr as usize }, 24usize, concat!( "Offset of field: ", stringify!(ifnet_interface_advisory), "::", stringify!(total_byte_count) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).average_throughput) as usize - ptr as usize }, 32usize, concat!( "Offset of field: ", stringify!(ifnet_interface_advisory), "::", stringify!(average_throughput) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).flushable_queue_size) as usize - ptr as usize }, 40usize, concat!( "Offset of field: ", stringify!(ifnet_interface_advisory), "::", stringify!(flushable_queue_size) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).non_flushable_queue_size) as usize - ptr as usize }, 44usize, concat!( "Offset of field: ", stringify!(ifnet_interface_advisory), "::", stringify!(non_flushable_queue_size) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).average_delay) as usize - ptr as usize }, 48usize, concat!( "Offset of field: ", stringify!(ifnet_interface_advisory), "::", stringify!(average_delay) ) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct ifqueue { pub ifq_head: *mut ::std::os::raw::c_void, pub ifq_tail: *mut ::std::os::raw::c_void, pub ifq_len: ::std::os::raw::c_int, pub ifq_maxlen: ::std::os::raw::c_int, pub ifq_drops: ::std::os::raw::c_int, } #[test] fn bindgen_test_layout_ifqueue() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 32usize, concat!("Size of: ", stringify!(ifqueue)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(ifqueue)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifq_head) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(ifqueue), "::", stringify!(ifq_head)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifq_tail) as usize - ptr as usize }, 8usize, concat!("Offset of field: ", stringify!(ifqueue), "::", stringify!(ifq_tail)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifq_len) as usize - ptr as usize }, 16usize, concat!("Offset of field: ", stringify!(ifqueue), "::", stringify!(ifq_len)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifq_maxlen) as usize - ptr as usize }, 20usize, concat!("Offset of field: ", stringify!(ifqueue), "::", stringify!(ifq_maxlen)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifq_drops) as usize - ptr as usize }, 24usize, concat!("Offset of field: ", stringify!(ifqueue), "::", stringify!(ifq_drops)) ); } #[repr(C)] #[derive(Copy, Clone)] pub union sockaddr_union { pub sa: sockaddr, pub sin: sockaddr_in, pub sin6: sockaddr_in6, } #[test] fn bindgen_test_layout_sockaddr_union() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 28usize, concat!("Size of: ", stringify!(sockaddr_union)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(sockaddr_union)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).sa) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(sockaddr_union), "::", stringify!(sa)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).sin) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(sockaddr_union), "::", stringify!(sin)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).sin6) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(sockaddr_union), "::", stringify!(sin6)) ); } pub const PF_INOUT: _bindgen_ty_1 = 0; pub const PF_IN: _bindgen_ty_1 = 1; pub const PF_OUT: _bindgen_ty_1 = 2; pub type _bindgen_ty_1 = ::std::os::raw::c_uint; pub const PF_PASS: _bindgen_ty_2 = 0; pub const PF_DROP: _bindgen_ty_2 = 1; pub const PF_SCRUB: _bindgen_ty_2 = 2; pub const PF_NOSCRUB: _bindgen_ty_2 = 3; pub const PF_NAT: _bindgen_ty_2 = 4; pub const PF_NONAT: _bindgen_ty_2 = 5; pub const PF_BINAT: _bindgen_ty_2 = 6; pub const PF_NOBINAT: _bindgen_ty_2 = 7; pub const PF_RDR: _bindgen_ty_2 = 8; pub const PF_NORDR: _bindgen_ty_2 = 9; pub const PF_SYNPROXY_DROP: _bindgen_ty_2 = 10; pub const PF_DUMMYNET: _bindgen_ty_2 = 11; pub const PF_NODUMMYNET: _bindgen_ty_2 = 12; pub const PF_NAT64: _bindgen_ty_2 = 13; pub const PF_NONAT64: _bindgen_ty_2 = 14; pub type _bindgen_ty_2 = ::std::os::raw::c_uint; pub const PF_RULESET_SCRUB: _bindgen_ty_3 = 0; pub const PF_RULESET_FILTER: _bindgen_ty_3 = 1; pub const PF_RULESET_NAT: _bindgen_ty_3 = 2; pub const PF_RULESET_BINAT: _bindgen_ty_3 = 3; pub const PF_RULESET_RDR: _bindgen_ty_3 = 4; pub const PF_RULESET_DUMMYNET: _bindgen_ty_3 = 5; pub const PF_RULESET_MAX: _bindgen_ty_3 = 6; pub type _bindgen_ty_3 = ::std::os::raw::c_uint; pub const PF_OP_NONE: _bindgen_ty_4 = 0; pub const PF_OP_IRG: _bindgen_ty_4 = 1; pub const PF_OP_EQ: _bindgen_ty_4 = 2; pub const PF_OP_NE: _bindgen_ty_4 = 3; pub const PF_OP_LT: _bindgen_ty_4 = 4; pub const PF_OP_LE: _bindgen_ty_4 = 5; pub const PF_OP_GT: _bindgen_ty_4 = 6; pub const PF_OP_GE: _bindgen_ty_4 = 7; pub const PF_OP_XRG: _bindgen_ty_4 = 8; pub const PF_OP_RRG: _bindgen_ty_4 = 9; pub type _bindgen_ty_4 = ::std::os::raw::c_uint; pub const PF_DEBUG_NONE: _bindgen_ty_5 = 0; pub const PF_DEBUG_URGENT: _bindgen_ty_5 = 1; pub const PF_DEBUG_MISC: _bindgen_ty_5 = 2; pub const PF_DEBUG_NOISY: _bindgen_ty_5 = 3; pub type _bindgen_ty_5 = ::std::os::raw::c_uint; pub const PF_CHANGE_NONE: _bindgen_ty_6 = 0; pub const PF_CHANGE_ADD_HEAD: _bindgen_ty_6 = 1; pub const PF_CHANGE_ADD_TAIL: _bindgen_ty_6 = 2; pub const PF_CHANGE_ADD_BEFORE: _bindgen_ty_6 = 3; pub const PF_CHANGE_ADD_AFTER: _bindgen_ty_6 = 4; pub const PF_CHANGE_REMOVE: _bindgen_ty_6 = 5; pub const PF_CHANGE_GET_TICKET: _bindgen_ty_6 = 6; pub type _bindgen_ty_6 = ::std::os::raw::c_uint; pub const PF_GET_NONE: _bindgen_ty_7 = 0; pub const PF_GET_CLR_CNTR: _bindgen_ty_7 = 1; pub type _bindgen_ty_7 = ::std::os::raw::c_uint; pub const PFTM_TCP_FIRST_PACKET: _bindgen_ty_8 = 0; pub const PFTM_TCP_OPENING: _bindgen_ty_8 = 1; pub const PFTM_TCP_ESTABLISHED: _bindgen_ty_8 = 2; pub const PFTM_TCP_CLOSING: _bindgen_ty_8 = 3; pub const PFTM_TCP_FIN_WAIT: _bindgen_ty_8 = 4; pub const PFTM_TCP_CLOSED: _bindgen_ty_8 = 5; pub const PFTM_UDP_FIRST_PACKET: _bindgen_ty_8 = 6; pub const PFTM_UDP_SINGLE: _bindgen_ty_8 = 7; pub const PFTM_UDP_MULTIPLE: _bindgen_ty_8 = 8; pub const PFTM_ICMP_FIRST_PACKET: _bindgen_ty_8 = 9; pub const PFTM_ICMP_ERROR_REPLY: _bindgen_ty_8 = 10; pub const PFTM_GREv1_FIRST_PACKET: _bindgen_ty_8 = 11; pub const PFTM_GREv1_INITIATING: _bindgen_ty_8 = 12; pub const PFTM_GREv1_ESTABLISHED: _bindgen_ty_8 = 13; pub const PFTM_ESP_FIRST_PACKET: _bindgen_ty_8 = 14; pub const PFTM_ESP_INITIATING: _bindgen_ty_8 = 15; pub const PFTM_ESP_ESTABLISHED: _bindgen_ty_8 = 16; pub const PFTM_OTHER_FIRST_PACKET: _bindgen_ty_8 = 17; pub const PFTM_OTHER_SINGLE: _bindgen_ty_8 = 18; pub const PFTM_OTHER_MULTIPLE: _bindgen_ty_8 = 19; pub const PFTM_FRAG: _bindgen_ty_8 = 20; pub const PFTM_INTERVAL: _bindgen_ty_8 = 21; pub const PFTM_ADAPTIVE_START: _bindgen_ty_8 = 22; pub const PFTM_ADAPTIVE_END: _bindgen_ty_8 = 23; pub const PFTM_SRC_NODE: _bindgen_ty_8 = 24; pub const PFTM_TS_DIFF: _bindgen_ty_8 = 25; pub const PFTM_MAX: _bindgen_ty_8 = 26; pub const PFTM_PURGE: _bindgen_ty_8 = 27; pub const PFTM_UNLINKED: _bindgen_ty_8 = 28; pub type _bindgen_ty_8 = ::std::os::raw::c_uint; pub const PF_NOPFROUTE: _bindgen_ty_9 = 0; pub const PF_FASTROUTE: _bindgen_ty_9 = 1; pub const PF_ROUTETO: _bindgen_ty_9 = 2; pub const PF_DUPTO: _bindgen_ty_9 = 3; pub const PF_REPLYTO: _bindgen_ty_9 = 4; pub type _bindgen_ty_9 = ::std::os::raw::c_uint; pub const PF_LIMIT_STATES: _bindgen_ty_10 = 0; pub const PF_LIMIT_APP_STATES: _bindgen_ty_10 = 1; pub const PF_LIMIT_SRC_NODES: _bindgen_ty_10 = 2; pub const PF_LIMIT_FRAGS: _bindgen_ty_10 = 3; pub const PF_LIMIT_TABLES: _bindgen_ty_10 = 4; pub const PF_LIMIT_TABLE_ENTRIES: _bindgen_ty_10 = 5; pub const PF_LIMIT_MAX: _bindgen_ty_10 = 6; pub type _bindgen_ty_10 = ::std::os::raw::c_uint; pub const PF_POOL_NONE: _bindgen_ty_11 = 0; pub const PF_POOL_BITMASK: _bindgen_ty_11 = 1; pub const PF_POOL_RANDOM: _bindgen_ty_11 = 2; pub const PF_POOL_SRCHASH: _bindgen_ty_11 = 3; pub const PF_POOL_ROUNDROBIN: _bindgen_ty_11 = 4; pub type _bindgen_ty_11 = ::std::os::raw::c_uint; pub const PF_ADDR_ADDRMASK: _bindgen_ty_12 = 0; pub const PF_ADDR_NOROUTE: _bindgen_ty_12 = 1; pub const PF_ADDR_DYNIFTL: _bindgen_ty_12 = 2; pub const PF_ADDR_TABLE: _bindgen_ty_12 = 3; pub const PF_ADDR_RTLABEL: _bindgen_ty_12 = 4; pub const PF_ADDR_URPFFAILED: _bindgen_ty_12 = 5; pub const PF_ADDR_RANGE: _bindgen_ty_12 = 6; pub type _bindgen_ty_12 = ::std::os::raw::c_uint; #[repr(C)] #[derive(Copy, Clone)] pub struct pf_addr { pub pfa: pf_addr__bindgen_ty_1, } #[repr(C)] #[derive(Copy, Clone)] pub union pf_addr__bindgen_ty_1 { pub _v4addr: in_addr, pub _v6addr: in6_addr, pub _addr8: [u_int8_t; 16usize], pub _addr16: [u_int16_t; 8usize], pub _addr32: [u_int32_t; 4usize], } #[test] fn bindgen_test_layout_pf_addr__bindgen_ty_1() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 16usize, concat!("Size of: ", stringify!(pf_addr__bindgen_ty_1)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(pf_addr__bindgen_ty_1)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr)._v4addr) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pf_addr__bindgen_ty_1), "::", stringify!(_v4addr) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr)._v6addr) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pf_addr__bindgen_ty_1), "::", stringify!(_v6addr) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr)._addr8) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pf_addr__bindgen_ty_1), "::", stringify!(_addr8) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr)._addr16) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pf_addr__bindgen_ty_1), "::", stringify!(_addr16) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr)._addr32) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pf_addr__bindgen_ty_1), "::", stringify!(_addr32) ) ); } #[test] fn bindgen_test_layout_pf_addr() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 16usize, concat!("Size of: ", stringify!(pf_addr)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(pf_addr)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfa) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(pf_addr), "::", stringify!(pfa)) ); } #[repr(C)] #[derive(Copy, Clone)] pub struct pf_addr_wrap { pub v: pf_addr_wrap__bindgen_ty_1, pub p: pf_addr_wrap__bindgen_ty_2, pub type_: u_int8_t, pub iflags: u_int8_t, } #[repr(C)] #[derive(Copy, Clone)] pub union pf_addr_wrap__bindgen_ty_1 { pub a: pf_addr_wrap__bindgen_ty_1__bindgen_ty_1, pub ifname: [::std::os::raw::c_char; 16usize], pub tblname: [::std::os::raw::c_char; 32usize], pub rtlabelname: [::std::os::raw::c_char; 32usize], pub rtlabel: u_int32_t, } #[repr(C)] #[derive(Copy, Clone)] pub struct pf_addr_wrap__bindgen_ty_1__bindgen_ty_1 { pub addr: pf_addr, pub mask: pf_addr, } #[test] fn bindgen_test_layout_pf_addr_wrap__bindgen_ty_1__bindgen_ty_1() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 32usize, concat!("Size of: ", stringify!(pf_addr_wrap__bindgen_ty_1__bindgen_ty_1)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(pf_addr_wrap__bindgen_ty_1__bindgen_ty_1)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).addr) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pf_addr_wrap__bindgen_ty_1__bindgen_ty_1), "::", stringify!(addr) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).mask) as usize - ptr as usize }, 16usize, concat!( "Offset of field: ", stringify!(pf_addr_wrap__bindgen_ty_1__bindgen_ty_1), "::", stringify!(mask) ) ); } #[test] fn bindgen_test_layout_pf_addr_wrap__bindgen_ty_1() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 32usize, concat!("Size of: ", stringify!(pf_addr_wrap__bindgen_ty_1)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(pf_addr_wrap__bindgen_ty_1)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).a) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pf_addr_wrap__bindgen_ty_1), "::", stringify!(a) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifname) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pf_addr_wrap__bindgen_ty_1), "::", stringify!(ifname) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).tblname) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pf_addr_wrap__bindgen_ty_1), "::", stringify!(tblname) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rtlabelname) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pf_addr_wrap__bindgen_ty_1), "::", stringify!(rtlabelname) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rtlabel) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pf_addr_wrap__bindgen_ty_1), "::", stringify!(rtlabel) ) ); } #[repr(C)] #[derive(Copy, Clone)] pub union pf_addr_wrap__bindgen_ty_2 { pub dyn_: *mut ::std::os::raw::c_void, pub tbl: *mut ::std::os::raw::c_void, pub dyncnt: ::std::os::raw::c_int, pub tblcnt: ::std::os::raw::c_int, } #[test] fn bindgen_test_layout_pf_addr_wrap__bindgen_ty_2() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 8usize, concat!("Size of: ", stringify!(pf_addr_wrap__bindgen_ty_2)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pf_addr_wrap__bindgen_ty_2)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).dyn_) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pf_addr_wrap__bindgen_ty_2), "::", stringify!(dyn_) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).tbl) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pf_addr_wrap__bindgen_ty_2), "::", stringify!(tbl) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).dyncnt) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pf_addr_wrap__bindgen_ty_2), "::", stringify!(dyncnt) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).tblcnt) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pf_addr_wrap__bindgen_ty_2), "::", stringify!(tblcnt) ) ); } #[test] fn bindgen_test_layout_pf_addr_wrap() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 48usize, concat!("Size of: ", stringify!(pf_addr_wrap)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pf_addr_wrap)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).v) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(pf_addr_wrap), "::", stringify!(v)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).p) as usize - ptr as usize }, 32usize, concat!("Offset of field: ", stringify!(pf_addr_wrap), "::", stringify!(p)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).type_) as usize - ptr as usize }, 40usize, concat!("Offset of field: ", stringify!(pf_addr_wrap), "::", stringify!(type_)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).iflags) as usize - ptr as usize }, 41usize, concat!("Offset of field: ", stringify!(pf_addr_wrap), "::", stringify!(iflags)) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pf_port_range { pub port: [u_int16_t; 2usize], pub op: u_int8_t, } #[test] fn bindgen_test_layout_pf_port_range() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 6usize, concat!("Size of: ", stringify!(pf_port_range)) ); assert_eq!( ::std::mem::align_of::(), 2usize, concat!("Alignment of ", stringify!(pf_port_range)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).port) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(pf_port_range), "::", stringify!(port)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).op) as usize - ptr as usize }, 4usize, concat!("Offset of field: ", stringify!(pf_port_range), "::", stringify!(op)) ); } #[repr(C)] #[derive(Copy, Clone)] pub union pf_rule_xport { pub range: pf_port_range, pub call_id: u_int16_t, pub spi: u_int32_t, } #[test] fn bindgen_test_layout_pf_rule_xport() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 8usize, concat!("Size of: ", stringify!(pf_rule_xport)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(pf_rule_xport)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).range) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(pf_rule_xport), "::", stringify!(range)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).call_id) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pf_rule_xport), "::", stringify!(call_id) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).spi) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(pf_rule_xport), "::", stringify!(spi)) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pf_rule_uid { pub uid: [uid_t; 2usize], pub op: u_int8_t, pub _pad: [u_int8_t; 3usize], } #[test] fn bindgen_test_layout_pf_rule_uid() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 12usize, concat!("Size of: ", stringify!(pf_rule_uid)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(pf_rule_uid)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).uid) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(pf_rule_uid), "::", stringify!(uid)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).op) as usize - ptr as usize }, 8usize, concat!("Offset of field: ", stringify!(pf_rule_uid), "::", stringify!(op)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr)._pad) as usize - ptr as usize }, 9usize, concat!("Offset of field: ", stringify!(pf_rule_uid), "::", stringify!(_pad)) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pf_rule_gid { pub gid: [uid_t; 2usize], pub op: u_int8_t, pub _pad: [u_int8_t; 3usize], } #[test] fn bindgen_test_layout_pf_rule_gid() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 12usize, concat!("Size of: ", stringify!(pf_rule_gid)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(pf_rule_gid)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).gid) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(pf_rule_gid), "::", stringify!(gid)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).op) as usize - ptr as usize }, 8usize, concat!("Offset of field: ", stringify!(pf_rule_gid), "::", stringify!(op)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr)._pad) as usize - ptr as usize }, 9usize, concat!("Offset of field: ", stringify!(pf_rule_gid), "::", stringify!(_pad)) ); } #[repr(C)] #[derive(Copy, Clone)] pub struct pf_rule_addr { pub addr: pf_addr_wrap, pub xport: pf_rule_xport, pub neg: u_int8_t, } #[test] fn bindgen_test_layout_pf_rule_addr() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 64usize, concat!("Size of: ", stringify!(pf_rule_addr)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pf_rule_addr)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).addr) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(pf_rule_addr), "::", stringify!(addr)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).xport) as usize - ptr as usize }, 48usize, concat!("Offset of field: ", stringify!(pf_rule_addr), "::", stringify!(xport)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).neg) as usize - ptr as usize }, 56usize, concat!("Offset of field: ", stringify!(pf_rule_addr), "::", stringify!(neg)) ); } #[repr(C)] #[derive(Copy, Clone)] pub struct pf_pooladdr { pub addr: pf_addr_wrap, pub entries: pf_pooladdr__bindgen_ty_1, pub ifname: [::std::os::raw::c_char; 16usize], pub kif: *mut ::std::os::raw::c_void, } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pf_pooladdr__bindgen_ty_1 { pub tqe_next: *mut pf_pooladdr, pub tqe_prev: *mut *mut pf_pooladdr, } #[test] fn bindgen_test_layout_pf_pooladdr__bindgen_ty_1() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 16usize, concat!("Size of: ", stringify!(pf_pooladdr__bindgen_ty_1)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pf_pooladdr__bindgen_ty_1)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).tqe_next) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pf_pooladdr__bindgen_ty_1), "::", stringify!(tqe_next) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).tqe_prev) as usize - ptr as usize }, 8usize, concat!( "Offset of field: ", stringify!(pf_pooladdr__bindgen_ty_1), "::", stringify!(tqe_prev) ) ); } #[test] fn bindgen_test_layout_pf_pooladdr() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 88usize, concat!("Size of: ", stringify!(pf_pooladdr)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pf_pooladdr)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).addr) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(pf_pooladdr), "::", stringify!(addr)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).entries) as usize - ptr as usize }, 48usize, concat!("Offset of field: ", stringify!(pf_pooladdr), "::", stringify!(entries)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifname) as usize - ptr as usize }, 64usize, concat!("Offset of field: ", stringify!(pf_pooladdr), "::", stringify!(ifname)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).kif) as usize - ptr as usize }, 80usize, concat!("Offset of field: ", stringify!(pf_pooladdr), "::", stringify!(kif)) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pf_palist { pub tqh_first: *mut pf_pooladdr, pub tqh_last: *mut *mut pf_pooladdr, } #[test] fn bindgen_test_layout_pf_palist() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 16usize, concat!("Size of: ", stringify!(pf_palist)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pf_palist)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).tqh_first) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(pf_palist), "::", stringify!(tqh_first)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).tqh_last) as usize - ptr as usize }, 8usize, concat!("Offset of field: ", stringify!(pf_palist), "::", stringify!(tqh_last)) ); } #[repr(C)] #[derive(Copy, Clone)] pub struct pf_poolhashkey { pub pfk: pf_poolhashkey__bindgen_ty_1, } #[repr(C)] #[derive(Copy, Clone)] pub union pf_poolhashkey__bindgen_ty_1 { pub key8: [u_int8_t; 16usize], pub key16: [u_int16_t; 8usize], pub key32: [u_int32_t; 4usize], } #[test] fn bindgen_test_layout_pf_poolhashkey__bindgen_ty_1() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 16usize, concat!("Size of: ", stringify!(pf_poolhashkey__bindgen_ty_1)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(pf_poolhashkey__bindgen_ty_1)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).key8) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pf_poolhashkey__bindgen_ty_1), "::", stringify!(key8) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).key16) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pf_poolhashkey__bindgen_ty_1), "::", stringify!(key16) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).key32) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pf_poolhashkey__bindgen_ty_1), "::", stringify!(key32) ) ); } #[test] fn bindgen_test_layout_pf_poolhashkey() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 16usize, concat!("Size of: ", stringify!(pf_poolhashkey)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(pf_poolhashkey)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfk) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(pf_poolhashkey), "::", stringify!(pfk)) ); } #[repr(C)] #[derive(Copy, Clone)] pub struct pf_pool { pub list: pf_palist, pub cur: *mut ::std::os::raw::c_void, pub key: pf_poolhashkey, pub counter: pf_addr, pub tblidx: ::std::os::raw::c_int, pub proxy_port: [u_int16_t; 2usize], pub port_op: u_int8_t, pub opts: u_int8_t, pub af: sa_family_t, } #[test] fn bindgen_test_layout_pf_pool() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 72usize, concat!("Size of: ", stringify!(pf_pool)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pf_pool)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).list) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(pf_pool), "::", stringify!(list)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).cur) as usize - ptr as usize }, 16usize, concat!("Offset of field: ", stringify!(pf_pool), "::", stringify!(cur)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).key) as usize - ptr as usize }, 24usize, concat!("Offset of field: ", stringify!(pf_pool), "::", stringify!(key)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).counter) as usize - ptr as usize }, 40usize, concat!("Offset of field: ", stringify!(pf_pool), "::", stringify!(counter)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).tblidx) as usize - ptr as usize }, 56usize, concat!("Offset of field: ", stringify!(pf_pool), "::", stringify!(tblidx)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).proxy_port) as usize - ptr as usize }, 60usize, concat!("Offset of field: ", stringify!(pf_pool), "::", stringify!(proxy_port)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).port_op) as usize - ptr as usize }, 64usize, concat!("Offset of field: ", stringify!(pf_pool), "::", stringify!(port_op)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).opts) as usize - ptr as usize }, 65usize, concat!("Offset of field: ", stringify!(pf_pool), "::", stringify!(opts)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).af) as usize - ptr as usize }, 66usize, concat!("Offset of field: ", stringify!(pf_pool), "::", stringify!(af)) ); } pub type pf_osfp_t = u_int32_t; #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pf_osfp_entry { pub fp_entry: pf_osfp_entry__bindgen_ty_1, pub fp_os: pf_osfp_t, pub fp_enflags: ::std::os::raw::c_int, pub fp_class_nm: [::std::os::raw::c_char; 32usize], pub fp_version_nm: [::std::os::raw::c_char; 32usize], pub fp_subtype_nm: [::std::os::raw::c_char; 32usize], } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pf_osfp_entry__bindgen_ty_1 { pub sle_next: *mut pf_osfp_entry, } #[test] fn bindgen_test_layout_pf_osfp_entry__bindgen_ty_1() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 8usize, concat!("Size of: ", stringify!(pf_osfp_entry__bindgen_ty_1)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pf_osfp_entry__bindgen_ty_1)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).sle_next) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pf_osfp_entry__bindgen_ty_1), "::", stringify!(sle_next) ) ); } #[test] fn bindgen_test_layout_pf_osfp_entry() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 112usize, concat!("Size of: ", stringify!(pf_osfp_entry)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pf_osfp_entry)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).fp_entry) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pf_osfp_entry), "::", stringify!(fp_entry) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).fp_os) as usize - ptr as usize }, 8usize, concat!("Offset of field: ", stringify!(pf_osfp_entry), "::", stringify!(fp_os)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).fp_enflags) as usize - ptr as usize }, 12usize, concat!( "Offset of field: ", stringify!(pf_osfp_entry), "::", stringify!(fp_enflags) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).fp_class_nm) as usize - ptr as usize }, 16usize, concat!( "Offset of field: ", stringify!(pf_osfp_entry), "::", stringify!(fp_class_nm) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).fp_version_nm) as usize - ptr as usize }, 48usize, concat!( "Offset of field: ", stringify!(pf_osfp_entry), "::", stringify!(fp_version_nm) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).fp_subtype_nm) as usize - ptr as usize }, 80usize, concat!( "Offset of field: ", stringify!(pf_osfp_entry), "::", stringify!(fp_subtype_nm) ) ); } pub type pf_tcpopts_t = u_int64_t; #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pf_os_fingerprint { pub fp_oses: pf_os_fingerprint_pf_osfp_enlist, pub fp_tcpopts: pf_tcpopts_t, pub fp_wsize: u_int16_t, pub fp_psize: u_int16_t, pub fp_mss: u_int16_t, pub fp_flags: u_int16_t, pub fp_optcnt: u_int8_t, pub fp_wscale: u_int8_t, pub fp_ttl: u_int8_t, pub fp_next: pf_os_fingerprint__bindgen_ty_1, } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pf_os_fingerprint_pf_osfp_enlist { pub slh_first: *mut pf_osfp_entry, } #[test] fn bindgen_test_layout_pf_os_fingerprint_pf_osfp_enlist() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 8usize, concat!("Size of: ", stringify!(pf_os_fingerprint_pf_osfp_enlist)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pf_os_fingerprint_pf_osfp_enlist)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).slh_first) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pf_os_fingerprint_pf_osfp_enlist), "::", stringify!(slh_first) ) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pf_os_fingerprint__bindgen_ty_1 { pub sle_next: *mut pf_os_fingerprint, } #[test] fn bindgen_test_layout_pf_os_fingerprint__bindgen_ty_1() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 8usize, concat!("Size of: ", stringify!(pf_os_fingerprint__bindgen_ty_1)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pf_os_fingerprint__bindgen_ty_1)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).sle_next) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pf_os_fingerprint__bindgen_ty_1), "::", stringify!(sle_next) ) ); } #[test] fn bindgen_test_layout_pf_os_fingerprint() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 40usize, concat!("Size of: ", stringify!(pf_os_fingerprint)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pf_os_fingerprint)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).fp_oses) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pf_os_fingerprint), "::", stringify!(fp_oses) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).fp_tcpopts) as usize - ptr as usize }, 8usize, concat!( "Offset of field: ", stringify!(pf_os_fingerprint), "::", stringify!(fp_tcpopts) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).fp_wsize) as usize - ptr as usize }, 16usize, concat!( "Offset of field: ", stringify!(pf_os_fingerprint), "::", stringify!(fp_wsize) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).fp_psize) as usize - ptr as usize }, 18usize, concat!( "Offset of field: ", stringify!(pf_os_fingerprint), "::", stringify!(fp_psize) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).fp_mss) as usize - ptr as usize }, 20usize, concat!( "Offset of field: ", stringify!(pf_os_fingerprint), "::", stringify!(fp_mss) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).fp_flags) as usize - ptr as usize }, 22usize, concat!( "Offset of field: ", stringify!(pf_os_fingerprint), "::", stringify!(fp_flags) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).fp_optcnt) as usize - ptr as usize }, 24usize, concat!( "Offset of field: ", stringify!(pf_os_fingerprint), "::", stringify!(fp_optcnt) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).fp_wscale) as usize - ptr as usize }, 25usize, concat!( "Offset of field: ", stringify!(pf_os_fingerprint), "::", stringify!(fp_wscale) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).fp_ttl) as usize - ptr as usize }, 26usize, concat!( "Offset of field: ", stringify!(pf_os_fingerprint), "::", stringify!(fp_ttl) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).fp_next) as usize - ptr as usize }, 32usize, concat!( "Offset of field: ", stringify!(pf_os_fingerprint), "::", stringify!(fp_next) ) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pf_osfp_ioctl { pub fp_os: pf_osfp_entry, pub fp_tcpopts: pf_tcpopts_t, pub fp_wsize: u_int16_t, pub fp_psize: u_int16_t, pub fp_mss: u_int16_t, pub fp_flags: u_int16_t, pub fp_optcnt: u_int8_t, pub fp_wscale: u_int8_t, pub fp_ttl: u_int8_t, pub fp_getnum: ::std::os::raw::c_int, } #[test] fn bindgen_test_layout_pf_osfp_ioctl() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 136usize, concat!("Size of: ", stringify!(pf_osfp_ioctl)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pf_osfp_ioctl)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).fp_os) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(pf_osfp_ioctl), "::", stringify!(fp_os)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).fp_tcpopts) as usize - ptr as usize }, 112usize, concat!( "Offset of field: ", stringify!(pf_osfp_ioctl), "::", stringify!(fp_tcpopts) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).fp_wsize) as usize - ptr as usize }, 120usize, concat!( "Offset of field: ", stringify!(pf_osfp_ioctl), "::", stringify!(fp_wsize) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).fp_psize) as usize - ptr as usize }, 122usize, concat!( "Offset of field: ", stringify!(pf_osfp_ioctl), "::", stringify!(fp_psize) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).fp_mss) as usize - ptr as usize }, 124usize, concat!("Offset of field: ", stringify!(pf_osfp_ioctl), "::", stringify!(fp_mss)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).fp_flags) as usize - ptr as usize }, 126usize, concat!( "Offset of field: ", stringify!(pf_osfp_ioctl), "::", stringify!(fp_flags) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).fp_optcnt) as usize - ptr as usize }, 128usize, concat!( "Offset of field: ", stringify!(pf_osfp_ioctl), "::", stringify!(fp_optcnt) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).fp_wscale) as usize - ptr as usize }, 129usize, concat!( "Offset of field: ", stringify!(pf_osfp_ioctl), "::", stringify!(fp_wscale) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).fp_ttl) as usize - ptr as usize }, 130usize, concat!("Offset of field: ", stringify!(pf_osfp_ioctl), "::", stringify!(fp_ttl)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).fp_getnum) as usize - ptr as usize }, 132usize, concat!( "Offset of field: ", stringify!(pf_osfp_ioctl), "::", stringify!(fp_getnum) ) ); } #[repr(C)] #[derive(Copy, Clone)] pub union pf_rule_ptr { pub ptr: *mut pf_rule, pub nr: u_int32_t, } #[test] fn bindgen_test_layout_pf_rule_ptr() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 8usize, concat!("Size of: ", stringify!(pf_rule_ptr)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pf_rule_ptr)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ptr) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(pf_rule_ptr), "::", stringify!(ptr)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).nr) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(pf_rule_ptr), "::", stringify!(nr)) ); } #[repr(C)] #[derive(Copy, Clone)] pub struct pf_rule { pub src: pf_rule_addr, pub dst: pf_rule_addr, pub skip: [pf_rule_ptr; 8usize], pub label: [::std::os::raw::c_char; 64usize], pub ifname: [::std::os::raw::c_char; 16usize], pub qname: [::std::os::raw::c_char; 64usize], pub pqname: [::std::os::raw::c_char; 64usize], pub tagname: [::std::os::raw::c_char; 64usize], pub match_tagname: [::std::os::raw::c_char; 64usize], pub overload_tblname: [::std::os::raw::c_char; 32usize], pub entries: pf_rule__bindgen_ty_1, pub rpool: pf_pool, pub evaluations: u_int64_t, pub packets: [u_int64_t; 2usize], pub bytes: [u_int64_t; 2usize], pub ticket: u_int64_t, pub owner: [::std::os::raw::c_char; 64usize], pub priority: u_int32_t, pub kif: *mut ::std::os::raw::c_void, pub anchor: *mut pf_anchor, pub overload_tbl: *mut ::std::os::raw::c_void, pub os_fingerprint: pf_osfp_t, pub rtableid: ::std::os::raw::c_uint, pub timeout: [u_int32_t; 26usize], pub states: u_int32_t, pub max_states: u_int32_t, pub src_nodes: u_int32_t, pub max_src_nodes: u_int32_t, pub max_src_states: u_int32_t, pub max_src_conn: u_int32_t, pub max_src_conn_rate: pf_rule__bindgen_ty_2, pub qid: u_int32_t, pub pqid: u_int32_t, pub rt_listid: u_int32_t, pub nr: u_int32_t, pub prob: u_int32_t, pub cuid: uid_t, pub cpid: pid_t, pub return_icmp: u_int16_t, pub return_icmp6: u_int16_t, pub max_mss: u_int16_t, pub tag: u_int16_t, pub match_tag: u_int16_t, pub uid: pf_rule_uid, pub gid: pf_rule_gid, pub rule_flag: u_int32_t, pub action: u_int8_t, pub direction: u_int8_t, pub log: u_int8_t, pub logif: u_int8_t, pub quick: u_int8_t, pub ifnot: u_int8_t, pub match_tag_not: u_int8_t, pub natpass: u_int8_t, pub keep_state: u_int8_t, pub af: sa_family_t, pub proto: u_int8_t, pub type_: u_int8_t, pub code: u_int8_t, pub flags: u_int8_t, pub flagset: u_int8_t, pub min_ttl: u_int8_t, pub allow_opts: u_int8_t, pub rt: u_int8_t, pub return_ttl: u_int8_t, pub tos: u_int8_t, pub anchor_relative: u_int8_t, pub anchor_wildcard: u_int8_t, pub flush: u_int8_t, pub proto_variant: u_int8_t, pub extfilter: u_int8_t, pub extmap: u_int8_t, pub dnpipe: u_int32_t, pub dntype: u_int32_t, } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pf_rule__bindgen_ty_1 { pub tqe_next: *mut pf_rule, pub tqe_prev: *mut *mut pf_rule, } #[test] fn bindgen_test_layout_pf_rule__bindgen_ty_1() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 16usize, concat!("Size of: ", stringify!(pf_rule__bindgen_ty_1)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pf_rule__bindgen_ty_1)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).tqe_next) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pf_rule__bindgen_ty_1), "::", stringify!(tqe_next) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).tqe_prev) as usize - ptr as usize }, 8usize, concat!( "Offset of field: ", stringify!(pf_rule__bindgen_ty_1), "::", stringify!(tqe_prev) ) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pf_rule__bindgen_ty_2 { pub limit: u_int32_t, pub seconds: u_int32_t, } #[test] fn bindgen_test_layout_pf_rule__bindgen_ty_2() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 8usize, concat!("Size of: ", stringify!(pf_rule__bindgen_ty_2)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(pf_rule__bindgen_ty_2)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).limit) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pf_rule__bindgen_ty_2), "::", stringify!(limit) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).seconds) as usize - ptr as usize }, 4usize, concat!( "Offset of field: ", stringify!(pf_rule__bindgen_ty_2), "::", stringify!(seconds) ) ); } #[test] fn bindgen_test_layout_pf_rule() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 1040usize, concat!("Size of: ", stringify!(pf_rule)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pf_rule)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).src) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(src)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).dst) as usize - ptr as usize }, 64usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(dst)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).skip) as usize - ptr as usize }, 128usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(skip)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).label) as usize - ptr as usize }, 192usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(label)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifname) as usize - ptr as usize }, 256usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(ifname)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).qname) as usize - ptr as usize }, 272usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(qname)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pqname) as usize - ptr as usize }, 336usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(pqname)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).tagname) as usize - ptr as usize }, 400usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(tagname)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).match_tagname) as usize - ptr as usize }, 464usize, concat!( "Offset of field: ", stringify!(pf_rule), "::", stringify!(match_tagname) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).overload_tblname) as usize - ptr as usize }, 528usize, concat!( "Offset of field: ", stringify!(pf_rule), "::", stringify!(overload_tblname) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).entries) as usize - ptr as usize }, 560usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(entries)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rpool) as usize - ptr as usize }, 576usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(rpool)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).evaluations) as usize - ptr as usize }, 648usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(evaluations)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).packets) as usize - ptr as usize }, 656usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(packets)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).bytes) as usize - ptr as usize }, 672usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(bytes)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ticket) as usize - ptr as usize }, 688usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(ticket)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).owner) as usize - ptr as usize }, 696usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(owner)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).priority) as usize - ptr as usize }, 760usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(priority)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).kif) as usize - ptr as usize }, 768usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(kif)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).anchor) as usize - ptr as usize }, 776usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(anchor)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).overload_tbl) as usize - ptr as usize }, 784usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(overload_tbl)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).os_fingerprint) as usize - ptr as usize }, 792usize, concat!( "Offset of field: ", stringify!(pf_rule), "::", stringify!(os_fingerprint) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rtableid) as usize - ptr as usize }, 796usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(rtableid)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).timeout) as usize - ptr as usize }, 800usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(timeout)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).states) as usize - ptr as usize }, 904usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(states)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).max_states) as usize - ptr as usize }, 908usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(max_states)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).src_nodes) as usize - ptr as usize }, 912usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(src_nodes)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).max_src_nodes) as usize - ptr as usize }, 916usize, concat!( "Offset of field: ", stringify!(pf_rule), "::", stringify!(max_src_nodes) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).max_src_states) as usize - ptr as usize }, 920usize, concat!( "Offset of field: ", stringify!(pf_rule), "::", stringify!(max_src_states) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).max_src_conn) as usize - ptr as usize }, 924usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(max_src_conn)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).max_src_conn_rate) as usize - ptr as usize }, 928usize, concat!( "Offset of field: ", stringify!(pf_rule), "::", stringify!(max_src_conn_rate) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).qid) as usize - ptr as usize }, 936usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(qid)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pqid) as usize - ptr as usize }, 940usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(pqid)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rt_listid) as usize - ptr as usize }, 944usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(rt_listid)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).nr) as usize - ptr as usize }, 948usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(nr)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).prob) as usize - ptr as usize }, 952usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(prob)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).cuid) as usize - ptr as usize }, 956usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(cuid)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).cpid) as usize - ptr as usize }, 960usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(cpid)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).return_icmp) as usize - ptr as usize }, 964usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(return_icmp)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).return_icmp6) as usize - ptr as usize }, 966usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(return_icmp6)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).max_mss) as usize - ptr as usize }, 968usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(max_mss)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).tag) as usize - ptr as usize }, 970usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(tag)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).match_tag) as usize - ptr as usize }, 972usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(match_tag)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).uid) as usize - ptr as usize }, 976usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(uid)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).gid) as usize - ptr as usize }, 988usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(gid)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rule_flag) as usize - ptr as usize }, 1000usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(rule_flag)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).action) as usize - ptr as usize }, 1004usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(action)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).direction) as usize - ptr as usize }, 1005usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(direction)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).log) as usize - ptr as usize }, 1006usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(log)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).logif) as usize - ptr as usize }, 1007usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(logif)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).quick) as usize - ptr as usize }, 1008usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(quick)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifnot) as usize - ptr as usize }, 1009usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(ifnot)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).match_tag_not) as usize - ptr as usize }, 1010usize, concat!( "Offset of field: ", stringify!(pf_rule), "::", stringify!(match_tag_not) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).natpass) as usize - ptr as usize }, 1011usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(natpass)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).keep_state) as usize - ptr as usize }, 1012usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(keep_state)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).af) as usize - ptr as usize }, 1013usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(af)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).proto) as usize - ptr as usize }, 1014usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(proto)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).type_) as usize - ptr as usize }, 1015usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(type_)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).code) as usize - ptr as usize }, 1016usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(code)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).flags) as usize - ptr as usize }, 1017usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(flags)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).flagset) as usize - ptr as usize }, 1018usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(flagset)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).min_ttl) as usize - ptr as usize }, 1019usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(min_ttl)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).allow_opts) as usize - ptr as usize }, 1020usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(allow_opts)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rt) as usize - ptr as usize }, 1021usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(rt)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).return_ttl) as usize - ptr as usize }, 1022usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(return_ttl)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).tos) as usize - ptr as usize }, 1023usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(tos)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).anchor_relative) as usize - ptr as usize }, 1024usize, concat!( "Offset of field: ", stringify!(pf_rule), "::", stringify!(anchor_relative) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).anchor_wildcard) as usize - ptr as usize }, 1025usize, concat!( "Offset of field: ", stringify!(pf_rule), "::", stringify!(anchor_wildcard) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).flush) as usize - ptr as usize }, 1026usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(flush)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).proto_variant) as usize - ptr as usize }, 1027usize, concat!( "Offset of field: ", stringify!(pf_rule), "::", stringify!(proto_variant) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).extfilter) as usize - ptr as usize }, 1028usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(extfilter)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).extmap) as usize - ptr as usize }, 1029usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(extmap)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).dnpipe) as usize - ptr as usize }, 1032usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(dnpipe)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).dntype) as usize - ptr as usize }, 1036usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(dntype)) ); } pub const pf_extmap_PF_EXTMAP_APD: pf_extmap = 1; pub const pf_extmap_PF_EXTMAP_AD: pf_extmap = 2; pub const pf_extmap_PF_EXTMAP_EI: pf_extmap = 3; pub type pf_extmap = ::std::os::raw::c_uint; pub const pf_extfilter_PF_EXTFILTER_APD: pf_extfilter = 1; pub const pf_extfilter_PF_EXTFILTER_AD: pf_extfilter = 2; pub const pf_extfilter_PF_EXTFILTER_EI: pf_extfilter = 3; pub type pf_extfilter = ::std::os::raw::c_uint; #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pf_threshold { pub limit: u_int32_t, pub seconds: u_int32_t, pub count: u_int32_t, pub last: u_int32_t, } #[test] fn bindgen_test_layout_pf_threshold() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 16usize, concat!("Size of: ", stringify!(pf_threshold)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(pf_threshold)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).limit) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(pf_threshold), "::", stringify!(limit)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).seconds) as usize - ptr as usize }, 4usize, concat!("Offset of field: ", stringify!(pf_threshold), "::", stringify!(seconds)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).count) as usize - ptr as usize }, 8usize, concat!("Offset of field: ", stringify!(pf_threshold), "::", stringify!(count)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).last) as usize - ptr as usize }, 12usize, concat!("Offset of field: ", stringify!(pf_threshold), "::", stringify!(last)) ); } #[repr(C)] #[derive(Copy, Clone)] pub struct pf_src_node { pub entry: pf_src_node__bindgen_ty_1, pub addr: pf_addr, pub raddr: pf_addr, pub rule: pf_rule_ptr, pub kif: *mut ::std::os::raw::c_void, pub bytes: [u_int64_t; 2usize], pub packets: [u_int64_t; 2usize], pub states: u_int32_t, pub conn: u_int32_t, pub conn_rate: pf_threshold, pub creation: u_int64_t, pub expire: u_int64_t, pub af: sa_family_t, pub ruletype: u_int8_t, } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pf_src_node__bindgen_ty_1 { pub rbe_left: *mut pf_src_node, pub rbe_right: *mut pf_src_node, pub rbe_parent: *mut pf_src_node, } #[test] fn bindgen_test_layout_pf_src_node__bindgen_ty_1() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 24usize, concat!("Size of: ", stringify!(pf_src_node__bindgen_ty_1)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pf_src_node__bindgen_ty_1)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rbe_left) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pf_src_node__bindgen_ty_1), "::", stringify!(rbe_left) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rbe_right) as usize - ptr as usize }, 8usize, concat!( "Offset of field: ", stringify!(pf_src_node__bindgen_ty_1), "::", stringify!(rbe_right) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rbe_parent) as usize - ptr as usize }, 16usize, concat!( "Offset of field: ", stringify!(pf_src_node__bindgen_ty_1), "::", stringify!(rbe_parent) ) ); } #[test] fn bindgen_test_layout_pf_src_node() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 152usize, concat!("Size of: ", stringify!(pf_src_node)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pf_src_node)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).entry) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(pf_src_node), "::", stringify!(entry)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).addr) as usize - ptr as usize }, 24usize, concat!("Offset of field: ", stringify!(pf_src_node), "::", stringify!(addr)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).raddr) as usize - ptr as usize }, 40usize, concat!("Offset of field: ", stringify!(pf_src_node), "::", stringify!(raddr)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rule) as usize - ptr as usize }, 56usize, concat!("Offset of field: ", stringify!(pf_src_node), "::", stringify!(rule)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).kif) as usize - ptr as usize }, 64usize, concat!("Offset of field: ", stringify!(pf_src_node), "::", stringify!(kif)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).bytes) as usize - ptr as usize }, 72usize, concat!("Offset of field: ", stringify!(pf_src_node), "::", stringify!(bytes)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).packets) as usize - ptr as usize }, 88usize, concat!("Offset of field: ", stringify!(pf_src_node), "::", stringify!(packets)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).states) as usize - ptr as usize }, 104usize, concat!("Offset of field: ", stringify!(pf_src_node), "::", stringify!(states)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).conn) as usize - ptr as usize }, 108usize, concat!("Offset of field: ", stringify!(pf_src_node), "::", stringify!(conn)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).conn_rate) as usize - ptr as usize }, 112usize, concat!( "Offset of field: ", stringify!(pf_src_node), "::", stringify!(conn_rate) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).creation) as usize - ptr as usize }, 128usize, concat!("Offset of field: ", stringify!(pf_src_node), "::", stringify!(creation)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).expire) as usize - ptr as usize }, 136usize, concat!("Offset of field: ", stringify!(pf_src_node), "::", stringify!(expire)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).af) as usize - ptr as usize }, 144usize, concat!("Offset of field: ", stringify!(pf_src_node), "::", stringify!(af)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ruletype) as usize - ptr as usize }, 145usize, concat!("Offset of field: ", stringify!(pf_src_node), "::", stringify!(ruletype)) ); } #[repr(C)] #[derive(Copy, Clone)] pub union pf_state_xport { pub port: u_int16_t, pub call_id: u_int16_t, pub spi: u_int32_t, } #[test] fn bindgen_test_layout_pf_state_xport() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 4usize, concat!("Size of: ", stringify!(pf_state_xport)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(pf_state_xport)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).port) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(pf_state_xport), "::", stringify!(port)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).call_id) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pf_state_xport), "::", stringify!(call_id) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).spi) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(pf_state_xport), "::", stringify!(spi)) ); } #[repr(C)] #[derive(Copy, Clone)] pub struct pf_state_host { pub addr: pf_addr, pub xport: pf_state_xport, } #[test] fn bindgen_test_layout_pf_state_host() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 20usize, concat!("Size of: ", stringify!(pf_state_host)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(pf_state_host)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).addr) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(pf_state_host), "::", stringify!(addr)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).xport) as usize - ptr as usize }, 16usize, concat!("Offset of field: ", stringify!(pf_state_host), "::", stringify!(xport)) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct hook_desc { _unused: [u8; 0], } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct hook_desc_head { pub tqh_first: *mut hook_desc, pub tqh_last: *mut *mut hook_desc, } #[test] fn bindgen_test_layout_hook_desc_head() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 16usize, concat!("Size of: ", stringify!(hook_desc_head)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(hook_desc_head)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).tqh_first) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(hook_desc_head), "::", stringify!(tqh_first) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).tqh_last) as usize - ptr as usize }, 8usize, concat!( "Offset of field: ", stringify!(hook_desc_head), "::", stringify!(tqh_last) ) ); } #[repr(C, packed)] #[derive(Debug, Copy, Clone)] pub struct pfsync_state_scrub { pub pfss_flags: u_int16_t, pub pfss_ttl: u_int8_t, pub scrub_flag: u_int8_t, pub pfss_ts_mod: u_int32_t, } #[test] fn bindgen_test_layout_pfsync_state_scrub() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 8usize, concat!("Size of: ", stringify!(pfsync_state_scrub)) ); assert_eq!( ::std::mem::align_of::(), 1usize, concat!("Alignment of ", stringify!(pfsync_state_scrub)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfss_flags) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pfsync_state_scrub), "::", stringify!(pfss_flags) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfss_ttl) as usize - ptr as usize }, 2usize, concat!( "Offset of field: ", stringify!(pfsync_state_scrub), "::", stringify!(pfss_ttl) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).scrub_flag) as usize - ptr as usize }, 3usize, concat!( "Offset of field: ", stringify!(pfsync_state_scrub), "::", stringify!(scrub_flag) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfss_ts_mod) as usize - ptr as usize }, 4usize, concat!( "Offset of field: ", stringify!(pfsync_state_scrub), "::", stringify!(pfss_ts_mod) ) ); } #[repr(C, packed)] #[derive(Copy, Clone)] pub struct pfsync_state_host { pub addr: pf_addr, pub xport: pf_state_xport, pub pad: [u_int16_t; 2usize], } #[test] fn bindgen_test_layout_pfsync_state_host() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 24usize, concat!("Size of: ", stringify!(pfsync_state_host)) ); assert_eq!( ::std::mem::align_of::(), 1usize, concat!("Alignment of ", stringify!(pfsync_state_host)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).addr) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pfsync_state_host), "::", stringify!(addr) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).xport) as usize - ptr as usize }, 16usize, concat!( "Offset of field: ", stringify!(pfsync_state_host), "::", stringify!(xport) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pad) as usize - ptr as usize }, 20usize, concat!( "Offset of field: ", stringify!(pfsync_state_host), "::", stringify!(pad) ) ); } #[repr(C, packed)] #[derive(Debug, Copy, Clone)] pub struct pfsync_state_peer { pub scrub: pfsync_state_scrub, pub seqlo: u_int32_t, pub seqhi: u_int32_t, pub seqdiff: u_int32_t, pub max_win: u_int16_t, pub mss: u_int16_t, pub state: u_int8_t, pub wscale: u_int8_t, pub pad: [u_int8_t; 6usize], } #[test] fn bindgen_test_layout_pfsync_state_peer() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 32usize, concat!("Size of: ", stringify!(pfsync_state_peer)) ); assert_eq!( ::std::mem::align_of::(), 1usize, concat!("Alignment of ", stringify!(pfsync_state_peer)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).scrub) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pfsync_state_peer), "::", stringify!(scrub) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).seqlo) as usize - ptr as usize }, 8usize, concat!( "Offset of field: ", stringify!(pfsync_state_peer), "::", stringify!(seqlo) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).seqhi) as usize - ptr as usize }, 12usize, concat!( "Offset of field: ", stringify!(pfsync_state_peer), "::", stringify!(seqhi) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).seqdiff) as usize - ptr as usize }, 16usize, concat!( "Offset of field: ", stringify!(pfsync_state_peer), "::", stringify!(seqdiff) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).max_win) as usize - ptr as usize }, 20usize, concat!( "Offset of field: ", stringify!(pfsync_state_peer), "::", stringify!(max_win) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).mss) as usize - ptr as usize }, 22usize, concat!( "Offset of field: ", stringify!(pfsync_state_peer), "::", stringify!(mss) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).state) as usize - ptr as usize }, 24usize, concat!( "Offset of field: ", stringify!(pfsync_state_peer), "::", stringify!(state) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).wscale) as usize - ptr as usize }, 25usize, concat!( "Offset of field: ", stringify!(pfsync_state_peer), "::", stringify!(wscale) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pad) as usize - ptr as usize }, 26usize, concat!( "Offset of field: ", stringify!(pfsync_state_peer), "::", stringify!(pad) ) ); } #[repr(C, packed)] #[derive(Copy, Clone)] pub struct pfsync_state { pub id: [u_int32_t; 2usize], pub ifname: [::std::os::raw::c_char; 16usize], pub lan: pfsync_state_host, pub gwy: pfsync_state_host, pub ext_lan: pfsync_state_host, pub ext_gwy: pfsync_state_host, pub src: pfsync_state_peer, pub dst: pfsync_state_peer, pub rt_addr: pf_addr, pub unlink_hooks: hook_desc_head, pub rule: u_int32_t, pub anchor: u_int32_t, pub nat_rule: u_int32_t, pub creation: u_int64_t, pub expire: u_int64_t, pub packets: [[u_int32_t; 2usize]; 2usize], pub bytes: [[u_int32_t; 2usize]; 2usize], pub creatorid: u_int32_t, pub tag: u_int16_t, pub af_lan: sa_family_t, pub af_gwy: sa_family_t, pub proto: u_int8_t, pub direction: u_int8_t, pub log: u_int8_t, pub allow_opts: u_int8_t, pub timeout: u_int8_t, pub sync_flags: u_int8_t, pub updates: u_int8_t, pub proto_variant: u_int8_t, pub __pad: u_int8_t, pub flowhash: u_int32_t, } #[test] fn bindgen_test_layout_pfsync_state() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 297usize, concat!("Size of: ", stringify!(pfsync_state)) ); assert_eq!( ::std::mem::align_of::(), 1usize, concat!("Alignment of ", stringify!(pfsync_state)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).id) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(pfsync_state), "::", stringify!(id)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifname) as usize - ptr as usize }, 8usize, concat!("Offset of field: ", stringify!(pfsync_state), "::", stringify!(ifname)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).lan) as usize - ptr as usize }, 24usize, concat!("Offset of field: ", stringify!(pfsync_state), "::", stringify!(lan)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).gwy) as usize - ptr as usize }, 48usize, concat!("Offset of field: ", stringify!(pfsync_state), "::", stringify!(gwy)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ext_lan) as usize - ptr as usize }, 72usize, concat!("Offset of field: ", stringify!(pfsync_state), "::", stringify!(ext_lan)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ext_gwy) as usize - ptr as usize }, 96usize, concat!("Offset of field: ", stringify!(pfsync_state), "::", stringify!(ext_gwy)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).src) as usize - ptr as usize }, 120usize, concat!("Offset of field: ", stringify!(pfsync_state), "::", stringify!(src)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).dst) as usize - ptr as usize }, 152usize, concat!("Offset of field: ", stringify!(pfsync_state), "::", stringify!(dst)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rt_addr) as usize - ptr as usize }, 184usize, concat!("Offset of field: ", stringify!(pfsync_state), "::", stringify!(rt_addr)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).unlink_hooks) as usize - ptr as usize }, 200usize, concat!( "Offset of field: ", stringify!(pfsync_state), "::", stringify!(unlink_hooks) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rule) as usize - ptr as usize }, 216usize, concat!("Offset of field: ", stringify!(pfsync_state), "::", stringify!(rule)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).anchor) as usize - ptr as usize }, 220usize, concat!("Offset of field: ", stringify!(pfsync_state), "::", stringify!(anchor)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).nat_rule) as usize - ptr as usize }, 224usize, concat!( "Offset of field: ", stringify!(pfsync_state), "::", stringify!(nat_rule) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).creation) as usize - ptr as usize }, 228usize, concat!( "Offset of field: ", stringify!(pfsync_state), "::", stringify!(creation) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).expire) as usize - ptr as usize }, 236usize, concat!("Offset of field: ", stringify!(pfsync_state), "::", stringify!(expire)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).packets) as usize - ptr as usize }, 244usize, concat!("Offset of field: ", stringify!(pfsync_state), "::", stringify!(packets)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).bytes) as usize - ptr as usize }, 260usize, concat!("Offset of field: ", stringify!(pfsync_state), "::", stringify!(bytes)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).creatorid) as usize - ptr as usize }, 276usize, concat!( "Offset of field: ", stringify!(pfsync_state), "::", stringify!(creatorid) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).tag) as usize - ptr as usize }, 280usize, concat!("Offset of field: ", stringify!(pfsync_state), "::", stringify!(tag)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).af_lan) as usize - ptr as usize }, 282usize, concat!("Offset of field: ", stringify!(pfsync_state), "::", stringify!(af_lan)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).af_gwy) as usize - ptr as usize }, 283usize, concat!("Offset of field: ", stringify!(pfsync_state), "::", stringify!(af_gwy)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).proto) as usize - ptr as usize }, 284usize, concat!("Offset of field: ", stringify!(pfsync_state), "::", stringify!(proto)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).direction) as usize - ptr as usize }, 285usize, concat!( "Offset of field: ", stringify!(pfsync_state), "::", stringify!(direction) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).log) as usize - ptr as usize }, 286usize, concat!("Offset of field: ", stringify!(pfsync_state), "::", stringify!(log)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).allow_opts) as usize - ptr as usize }, 287usize, concat!( "Offset of field: ", stringify!(pfsync_state), "::", stringify!(allow_opts) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).timeout) as usize - ptr as usize }, 288usize, concat!("Offset of field: ", stringify!(pfsync_state), "::", stringify!(timeout)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).sync_flags) as usize - ptr as usize }, 289usize, concat!( "Offset of field: ", stringify!(pfsync_state), "::", stringify!(sync_flags) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).updates) as usize - ptr as usize }, 290usize, concat!("Offset of field: ", stringify!(pfsync_state), "::", stringify!(updates)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).proto_variant) as usize - ptr as usize }, 291usize, concat!( "Offset of field: ", stringify!(pfsync_state), "::", stringify!(proto_variant) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__pad) as usize - ptr as usize }, 292usize, concat!("Offset of field: ", stringify!(pfsync_state), "::", stringify!(__pad)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).flowhash) as usize - ptr as usize }, 293usize, concat!( "Offset of field: ", stringify!(pfsync_state), "::", stringify!(flowhash) ) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pf_rulequeue { pub tqh_first: *mut pf_rule, pub tqh_last: *mut *mut pf_rule, } #[test] fn bindgen_test_layout_pf_rulequeue() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 16usize, concat!("Size of: ", stringify!(pf_rulequeue)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pf_rulequeue)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).tqh_first) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pf_rulequeue), "::", stringify!(tqh_first) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).tqh_last) as usize - ptr as usize }, 8usize, concat!( "Offset of field: ", stringify!(pf_rulequeue), "::", stringify!(tqh_last) ) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pf_ruleset { pub rules: [pf_ruleset__bindgen_ty_1; 6usize], pub anchor: *mut pf_anchor, pub tticket: u_int32_t, pub tables: ::std::os::raw::c_int, pub topen: ::std::os::raw::c_int, } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pf_ruleset__bindgen_ty_1 { pub queues: [pf_rulequeue; 2usize], pub active: pf_ruleset__bindgen_ty_1__bindgen_ty_1, pub inactive: pf_ruleset__bindgen_ty_1__bindgen_ty_1, } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pf_ruleset__bindgen_ty_1__bindgen_ty_1 { pub ptr: *mut pf_rulequeue, pub ptr_array: *mut *mut pf_rule, pub rcount: u_int32_t, pub ticket: u_int32_t, pub open: ::std::os::raw::c_int, } #[test] fn bindgen_test_layout_pf_ruleset__bindgen_ty_1__bindgen_ty_1() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 32usize, concat!("Size of: ", stringify!(pf_ruleset__bindgen_ty_1__bindgen_ty_1)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pf_ruleset__bindgen_ty_1__bindgen_ty_1)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ptr) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pf_ruleset__bindgen_ty_1__bindgen_ty_1), "::", stringify!(ptr) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ptr_array) as usize - ptr as usize }, 8usize, concat!( "Offset of field: ", stringify!(pf_ruleset__bindgen_ty_1__bindgen_ty_1), "::", stringify!(ptr_array) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rcount) as usize - ptr as usize }, 16usize, concat!( "Offset of field: ", stringify!(pf_ruleset__bindgen_ty_1__bindgen_ty_1), "::", stringify!(rcount) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ticket) as usize - ptr as usize }, 20usize, concat!( "Offset of field: ", stringify!(pf_ruleset__bindgen_ty_1__bindgen_ty_1), "::", stringify!(ticket) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).open) as usize - ptr as usize }, 24usize, concat!( "Offset of field: ", stringify!(pf_ruleset__bindgen_ty_1__bindgen_ty_1), "::", stringify!(open) ) ); } #[test] fn bindgen_test_layout_pf_ruleset__bindgen_ty_1() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 96usize, concat!("Size of: ", stringify!(pf_ruleset__bindgen_ty_1)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pf_ruleset__bindgen_ty_1)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).queues) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pf_ruleset__bindgen_ty_1), "::", stringify!(queues) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).active) as usize - ptr as usize }, 32usize, concat!( "Offset of field: ", stringify!(pf_ruleset__bindgen_ty_1), "::", stringify!(active) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).inactive) as usize - ptr as usize }, 64usize, concat!( "Offset of field: ", stringify!(pf_ruleset__bindgen_ty_1), "::", stringify!(inactive) ) ); } #[test] fn bindgen_test_layout_pf_ruleset() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 600usize, concat!("Size of: ", stringify!(pf_ruleset)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pf_ruleset)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rules) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(pf_ruleset), "::", stringify!(rules)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).anchor) as usize - ptr as usize }, 576usize, concat!("Offset of field: ", stringify!(pf_ruleset), "::", stringify!(anchor)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).tticket) as usize - ptr as usize }, 584usize, concat!("Offset of field: ", stringify!(pf_ruleset), "::", stringify!(tticket)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).tables) as usize - ptr as usize }, 588usize, concat!("Offset of field: ", stringify!(pf_ruleset), "::", stringify!(tables)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).topen) as usize - ptr as usize }, 592usize, concat!("Offset of field: ", stringify!(pf_ruleset), "::", stringify!(topen)) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pf_anchor_global { pub rbh_root: *mut pf_anchor, } #[test] fn bindgen_test_layout_pf_anchor_global() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 8usize, concat!("Size of: ", stringify!(pf_anchor_global)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pf_anchor_global)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rbh_root) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pf_anchor_global), "::", stringify!(rbh_root) ) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pf_anchor_node { pub rbh_root: *mut pf_anchor, } #[test] fn bindgen_test_layout_pf_anchor_node() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 8usize, concat!("Size of: ", stringify!(pf_anchor_node)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pf_anchor_node)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rbh_root) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pf_anchor_node), "::", stringify!(rbh_root) ) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pf_anchor { pub entry_global: pf_anchor__bindgen_ty_1, pub entry_node: pf_anchor__bindgen_ty_2, pub parent: *mut pf_anchor, pub children: pf_anchor_node, pub name: [::std::os::raw::c_char; 64usize], pub path: [::std::os::raw::c_char; 1024usize], pub ruleset: pf_ruleset, pub refcnt: ::std::os::raw::c_int, pub match_: ::std::os::raw::c_int, pub owner: [::std::os::raw::c_char; 64usize], } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pf_anchor__bindgen_ty_1 { pub rbe_left: *mut pf_anchor, pub rbe_right: *mut pf_anchor, pub rbe_parent: *mut pf_anchor, } #[test] fn bindgen_test_layout_pf_anchor__bindgen_ty_1() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 24usize, concat!("Size of: ", stringify!(pf_anchor__bindgen_ty_1)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pf_anchor__bindgen_ty_1)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rbe_left) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pf_anchor__bindgen_ty_1), "::", stringify!(rbe_left) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rbe_right) as usize - ptr as usize }, 8usize, concat!( "Offset of field: ", stringify!(pf_anchor__bindgen_ty_1), "::", stringify!(rbe_right) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rbe_parent) as usize - ptr as usize }, 16usize, concat!( "Offset of field: ", stringify!(pf_anchor__bindgen_ty_1), "::", stringify!(rbe_parent) ) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pf_anchor__bindgen_ty_2 { pub rbe_left: *mut pf_anchor, pub rbe_right: *mut pf_anchor, pub rbe_parent: *mut pf_anchor, } #[test] fn bindgen_test_layout_pf_anchor__bindgen_ty_2() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 24usize, concat!("Size of: ", stringify!(pf_anchor__bindgen_ty_2)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pf_anchor__bindgen_ty_2)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rbe_left) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pf_anchor__bindgen_ty_2), "::", stringify!(rbe_left) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rbe_right) as usize - ptr as usize }, 8usize, concat!( "Offset of field: ", stringify!(pf_anchor__bindgen_ty_2), "::", stringify!(rbe_right) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rbe_parent) as usize - ptr as usize }, 16usize, concat!( "Offset of field: ", stringify!(pf_anchor__bindgen_ty_2), "::", stringify!(rbe_parent) ) ); } #[test] fn bindgen_test_layout_pf_anchor() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 1824usize, concat!("Size of: ", stringify!(pf_anchor)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pf_anchor)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).entry_global) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pf_anchor), "::", stringify!(entry_global) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).entry_node) as usize - ptr as usize }, 24usize, concat!("Offset of field: ", stringify!(pf_anchor), "::", stringify!(entry_node)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).parent) as usize - ptr as usize }, 48usize, concat!("Offset of field: ", stringify!(pf_anchor), "::", stringify!(parent)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).children) as usize - ptr as usize }, 56usize, concat!("Offset of field: ", stringify!(pf_anchor), "::", stringify!(children)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).name) as usize - ptr as usize }, 64usize, concat!("Offset of field: ", stringify!(pf_anchor), "::", stringify!(name)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).path) as usize - ptr as usize }, 128usize, concat!("Offset of field: ", stringify!(pf_anchor), "::", stringify!(path)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ruleset) as usize - ptr as usize }, 1152usize, concat!("Offset of field: ", stringify!(pf_anchor), "::", stringify!(ruleset)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).refcnt) as usize - ptr as usize }, 1752usize, concat!("Offset of field: ", stringify!(pf_anchor), "::", stringify!(refcnt)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).match_) as usize - ptr as usize }, 1756usize, concat!("Offset of field: ", stringify!(pf_anchor), "::", stringify!(match_)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).owner) as usize - ptr as usize }, 1760usize, concat!("Offset of field: ", stringify!(pf_anchor), "::", stringify!(owner)) ); } unsafe extern "C" { pub fn pf_anchor_global_RB_INSERT_COLOR(arg1: *mut pf_anchor_global, arg2: *mut pf_anchor); } unsafe extern "C" { pub fn pf_anchor_global_RB_REMOVE_COLOR(arg1: *mut pf_anchor_global, arg2: *mut pf_anchor, arg3: *mut pf_anchor); } unsafe extern "C" { pub fn pf_anchor_global_RB_REMOVE(arg1: *mut pf_anchor_global, arg2: *mut pf_anchor) -> *mut pf_anchor; } unsafe extern "C" { pub fn pf_anchor_global_RB_INSERT(arg1: *mut pf_anchor_global, arg2: *mut pf_anchor) -> *mut pf_anchor; } unsafe extern "C" { pub fn pf_anchor_global_RB_FIND(arg1: *mut pf_anchor_global, arg2: *mut pf_anchor) -> *mut pf_anchor; } unsafe extern "C" { pub fn pf_anchor_global_RB_NFIND(arg1: *mut pf_anchor_global, arg2: *mut pf_anchor) -> *mut pf_anchor; } unsafe extern "C" { pub fn pf_anchor_global_RB_NEXT(arg1: *mut pf_anchor) -> *mut pf_anchor; } unsafe extern "C" { pub fn pf_anchor_global_RB_MINMAX(arg1: *mut pf_anchor_global, arg2: ::std::os::raw::c_int) -> *mut pf_anchor; } unsafe extern "C" { pub fn pf_anchor_global_RB_GETPARENT(arg1: *mut pf_anchor) -> *mut pf_anchor; } unsafe extern "C" { pub fn pf_anchor_global_RB_SETPARENT(arg1: *mut pf_anchor, arg2: *mut pf_anchor) -> *mut pf_anchor; } unsafe extern "C" { pub fn pf_anchor_global_RB_GETCOLOR(arg1: *mut pf_anchor) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn pf_anchor_global_RB_SETCOLOR(arg1: *mut pf_anchor, arg2: ::std::os::raw::c_int); } unsafe extern "C" { pub fn pf_anchor_node_RB_INSERT_COLOR(arg1: *mut pf_anchor_node, arg2: *mut pf_anchor); } unsafe extern "C" { pub fn pf_anchor_node_RB_REMOVE_COLOR(arg1: *mut pf_anchor_node, arg2: *mut pf_anchor, arg3: *mut pf_anchor); } unsafe extern "C" { pub fn pf_anchor_node_RB_REMOVE(arg1: *mut pf_anchor_node, arg2: *mut pf_anchor) -> *mut pf_anchor; } unsafe extern "C" { pub fn pf_anchor_node_RB_INSERT(arg1: *mut pf_anchor_node, arg2: *mut pf_anchor) -> *mut pf_anchor; } unsafe extern "C" { pub fn pf_anchor_node_RB_FIND(arg1: *mut pf_anchor_node, arg2: *mut pf_anchor) -> *mut pf_anchor; } unsafe extern "C" { pub fn pf_anchor_node_RB_NFIND(arg1: *mut pf_anchor_node, arg2: *mut pf_anchor) -> *mut pf_anchor; } unsafe extern "C" { pub fn pf_anchor_node_RB_NEXT(arg1: *mut pf_anchor) -> *mut pf_anchor; } unsafe extern "C" { pub fn pf_anchor_node_RB_MINMAX(arg1: *mut pf_anchor_node, arg2: ::std::os::raw::c_int) -> *mut pf_anchor; } unsafe extern "C" { pub fn pf_anchor_node_RB_GETPARENT(arg1: *mut pf_anchor) -> *mut pf_anchor; } unsafe extern "C" { pub fn pf_anchor_node_RB_SETPARENT(arg1: *mut pf_anchor, arg2: *mut pf_anchor) -> *mut pf_anchor; } unsafe extern "C" { pub fn pf_anchor_node_RB_GETCOLOR(arg1: *mut pf_anchor) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn pf_anchor_node_RB_SETCOLOR(arg1: *mut pf_anchor, arg2: ::std::os::raw::c_int); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pfr_table { pub pfrt_anchor: [::std::os::raw::c_char; 1024usize], pub pfrt_name: [::std::os::raw::c_char; 32usize], pub pfrt_flags: u32, pub pfrt_fback: u8, } #[test] fn bindgen_test_layout_pfr_table() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 1064usize, concat!("Size of: ", stringify!(pfr_table)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(pfr_table)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfrt_anchor) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pfr_table), "::", stringify!(pfrt_anchor) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfrt_name) as usize - ptr as usize }, 1024usize, concat!("Offset of field: ", stringify!(pfr_table), "::", stringify!(pfrt_name)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfrt_flags) as usize - ptr as usize }, 1056usize, concat!("Offset of field: ", stringify!(pfr_table), "::", stringify!(pfrt_flags)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfrt_fback) as usize - ptr as usize }, 1060usize, concat!("Offset of field: ", stringify!(pfr_table), "::", stringify!(pfrt_fback)) ); } pub const PFR_FB_NONE: _bindgen_ty_13 = 0; pub const PFR_FB_MATCH: _bindgen_ty_13 = 1; pub const PFR_FB_ADDED: _bindgen_ty_13 = 2; pub const PFR_FB_DELETED: _bindgen_ty_13 = 3; pub const PFR_FB_CHANGED: _bindgen_ty_13 = 4; pub const PFR_FB_CLEARED: _bindgen_ty_13 = 5; pub const PFR_FB_DUPLICATE: _bindgen_ty_13 = 6; pub const PFR_FB_NOTMATCH: _bindgen_ty_13 = 7; pub const PFR_FB_CONFLICT: _bindgen_ty_13 = 8; pub const PFR_FB_MAX: _bindgen_ty_13 = 9; pub type _bindgen_ty_13 = ::std::os::raw::c_uint; #[repr(C)] #[derive(Copy, Clone)] pub struct pfr_addr { pub pfra_u: pfr_addr__bindgen_ty_1, pub pfra_af: u8, pub pfra_net: u8, pub pfra_not: u8, pub pfra_fback: u8, } #[repr(C)] #[derive(Copy, Clone)] pub union pfr_addr__bindgen_ty_1 { pub _pfra_ip4addr: in_addr, pub _pfra_ip6addr: in6_addr, } #[test] fn bindgen_test_layout_pfr_addr__bindgen_ty_1() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 16usize, concat!("Size of: ", stringify!(pfr_addr__bindgen_ty_1)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(pfr_addr__bindgen_ty_1)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr)._pfra_ip4addr) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pfr_addr__bindgen_ty_1), "::", stringify!(_pfra_ip4addr) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr)._pfra_ip6addr) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pfr_addr__bindgen_ty_1), "::", stringify!(_pfra_ip6addr) ) ); } #[test] fn bindgen_test_layout_pfr_addr() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 20usize, concat!("Size of: ", stringify!(pfr_addr)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(pfr_addr)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfra_u) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(pfr_addr), "::", stringify!(pfra_u)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfra_af) as usize - ptr as usize }, 16usize, concat!("Offset of field: ", stringify!(pfr_addr), "::", stringify!(pfra_af)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfra_net) as usize - ptr as usize }, 17usize, concat!("Offset of field: ", stringify!(pfr_addr), "::", stringify!(pfra_net)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfra_not) as usize - ptr as usize }, 18usize, concat!("Offset of field: ", stringify!(pfr_addr), "::", stringify!(pfra_not)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfra_fback) as usize - ptr as usize }, 19usize, concat!("Offset of field: ", stringify!(pfr_addr), "::", stringify!(pfra_fback)) ); } pub const PFR_DIR_IN: _bindgen_ty_14 = 0; pub const PFR_DIR_OUT: _bindgen_ty_14 = 1; pub const PFR_DIR_MAX: _bindgen_ty_14 = 2; pub type _bindgen_ty_14 = ::std::os::raw::c_uint; pub const PFR_OP_BLOCK: _bindgen_ty_15 = 0; pub const PFR_OP_PASS: _bindgen_ty_15 = 1; pub const PFR_OP_ADDR_MAX: _bindgen_ty_15 = 2; pub const PFR_OP_TABLE_MAX: _bindgen_ty_15 = 3; pub type _bindgen_ty_15 = ::std::os::raw::c_uint; #[repr(C)] #[derive(Copy, Clone)] pub struct pfr_astats { pub pfras_a: pfr_addr, pub pfras_packets: [[u64; 2usize]; 2usize], pub pfras_bytes: [[u64; 2usize]; 2usize], pub pfras_tzero: u64, } #[test] fn bindgen_test_layout_pfr_astats() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 96usize, concat!("Size of: ", stringify!(pfr_astats)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pfr_astats)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfras_a) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(pfr_astats), "::", stringify!(pfras_a)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfras_packets) as usize - ptr as usize }, 24usize, concat!( "Offset of field: ", stringify!(pfr_astats), "::", stringify!(pfras_packets) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfras_bytes) as usize - ptr as usize }, 56usize, concat!( "Offset of field: ", stringify!(pfr_astats), "::", stringify!(pfras_bytes) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfras_tzero) as usize - ptr as usize }, 88usize, concat!( "Offset of field: ", stringify!(pfr_astats), "::", stringify!(pfras_tzero) ) ); } pub const PFR_REFCNT_RULE: _bindgen_ty_16 = 0; pub const PFR_REFCNT_ANCHOR: _bindgen_ty_16 = 1; pub const PFR_REFCNT_MAX: _bindgen_ty_16 = 2; pub type _bindgen_ty_16 = ::std::os::raw::c_uint; #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pfr_tstats { pub pfrts_t: pfr_table, pub pfrts_packets: [[u_int64_t; 3usize]; 2usize], pub pfrts_bytes: [[u_int64_t; 3usize]; 2usize], pub pfrts_match: u_int64_t, pub pfrts_nomatch: u_int64_t, pub pfrts_tzero: u_int64_t, pub pfrts_cnt: ::std::os::raw::c_int, pub pfrts_refcnt: [::std::os::raw::c_int; 2usize], } #[test] fn bindgen_test_layout_pfr_tstats() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 1200usize, concat!("Size of: ", stringify!(pfr_tstats)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pfr_tstats)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfrts_t) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(pfr_tstats), "::", stringify!(pfrts_t)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfrts_packets) as usize - ptr as usize }, 1064usize, concat!( "Offset of field: ", stringify!(pfr_tstats), "::", stringify!(pfrts_packets) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfrts_bytes) as usize - ptr as usize }, 1112usize, concat!( "Offset of field: ", stringify!(pfr_tstats), "::", stringify!(pfrts_bytes) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfrts_match) as usize - ptr as usize }, 1160usize, concat!( "Offset of field: ", stringify!(pfr_tstats), "::", stringify!(pfrts_match) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfrts_nomatch) as usize - ptr as usize }, 1168usize, concat!( "Offset of field: ", stringify!(pfr_tstats), "::", stringify!(pfrts_nomatch) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfrts_tzero) as usize - ptr as usize }, 1176usize, concat!( "Offset of field: ", stringify!(pfr_tstats), "::", stringify!(pfrts_tzero) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfrts_cnt) as usize - ptr as usize }, 1184usize, concat!("Offset of field: ", stringify!(pfr_tstats), "::", stringify!(pfrts_cnt)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfrts_refcnt) as usize - ptr as usize }, 1188usize, concat!( "Offset of field: ", stringify!(pfr_tstats), "::", stringify!(pfrts_refcnt) ) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pfi_kif { pub pfik_name: [::std::os::raw::c_char; 16usize], pub pfik_packets: [[[u_int64_t; 2usize]; 2usize]; 2usize], pub pfik_bytes: [[[u_int64_t; 2usize]; 2usize]; 2usize], pub pfik_tzero: u_int64_t, pub pfik_flags: ::std::os::raw::c_int, pub pfik_states: ::std::os::raw::c_int, pub pfik_rules: ::std::os::raw::c_int, } #[test] fn bindgen_test_layout_pfi_kif() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 168usize, concat!("Size of: ", stringify!(pfi_kif)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pfi_kif)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfik_name) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(pfi_kif), "::", stringify!(pfik_name)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfik_packets) as usize - ptr as usize }, 16usize, concat!("Offset of field: ", stringify!(pfi_kif), "::", stringify!(pfik_packets)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfik_bytes) as usize - ptr as usize }, 80usize, concat!("Offset of field: ", stringify!(pfi_kif), "::", stringify!(pfik_bytes)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfik_tzero) as usize - ptr as usize }, 144usize, concat!("Offset of field: ", stringify!(pfi_kif), "::", stringify!(pfik_tzero)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfik_flags) as usize - ptr as usize }, 152usize, concat!("Offset of field: ", stringify!(pfi_kif), "::", stringify!(pfik_flags)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfik_states) as usize - ptr as usize }, 156usize, concat!("Offset of field: ", stringify!(pfi_kif), "::", stringify!(pfik_states)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfik_rules) as usize - ptr as usize }, 160usize, concat!("Offset of field: ", stringify!(pfi_kif), "::", stringify!(pfik_rules)) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pf_status { pub counters: [u_int64_t; 16usize], pub lcounters: [u_int64_t; 7usize], pub fcounters: [u_int64_t; 3usize], pub scounters: [u_int64_t; 3usize], pub pcounters: [[[u_int64_t; 3usize]; 2usize]; 2usize], pub bcounters: [[u_int64_t; 2usize]; 2usize], pub stateid: u_int64_t, pub running: u_int32_t, pub states: u_int32_t, pub src_nodes: u_int32_t, pub since: u_int64_t, pub debug: u_int32_t, pub hostid: u_int32_t, pub ifname: [::std::os::raw::c_char; 16usize], pub pf_chksum: [u_int8_t; 16usize], } #[test] fn bindgen_test_layout_pf_status() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 432usize, concat!("Size of: ", stringify!(pf_status)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pf_status)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).counters) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(pf_status), "::", stringify!(counters)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).lcounters) as usize - ptr as usize }, 128usize, concat!("Offset of field: ", stringify!(pf_status), "::", stringify!(lcounters)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).fcounters) as usize - ptr as usize }, 184usize, concat!("Offset of field: ", stringify!(pf_status), "::", stringify!(fcounters)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).scounters) as usize - ptr as usize }, 208usize, concat!("Offset of field: ", stringify!(pf_status), "::", stringify!(scounters)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pcounters) as usize - ptr as usize }, 232usize, concat!("Offset of field: ", stringify!(pf_status), "::", stringify!(pcounters)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).bcounters) as usize - ptr as usize }, 328usize, concat!("Offset of field: ", stringify!(pf_status), "::", stringify!(bcounters)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).stateid) as usize - ptr as usize }, 360usize, concat!("Offset of field: ", stringify!(pf_status), "::", stringify!(stateid)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).running) as usize - ptr as usize }, 368usize, concat!("Offset of field: ", stringify!(pf_status), "::", stringify!(running)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).states) as usize - ptr as usize }, 372usize, concat!("Offset of field: ", stringify!(pf_status), "::", stringify!(states)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).src_nodes) as usize - ptr as usize }, 376usize, concat!("Offset of field: ", stringify!(pf_status), "::", stringify!(src_nodes)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).since) as usize - ptr as usize }, 384usize, concat!("Offset of field: ", stringify!(pf_status), "::", stringify!(since)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).debug) as usize - ptr as usize }, 392usize, concat!("Offset of field: ", stringify!(pf_status), "::", stringify!(debug)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).hostid) as usize - ptr as usize }, 396usize, concat!("Offset of field: ", stringify!(pf_status), "::", stringify!(hostid)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifname) as usize - ptr as usize }, 400usize, concat!("Offset of field: ", stringify!(pf_status), "::", stringify!(ifname)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pf_chksum) as usize - ptr as usize }, 416usize, concat!("Offset of field: ", stringify!(pf_status), "::", stringify!(pf_chksum)) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct cbq_opts { pub minburst: u_int32_t, pub maxburst: u_int32_t, pub pktsize: u_int32_t, pub maxpktsize: u_int32_t, pub ns_per_byte: u_int32_t, pub maxidle: u_int32_t, pub minidle: i32, pub offtime: u_int32_t, pub flags: u_int32_t, } #[test] fn bindgen_test_layout_cbq_opts() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 36usize, concat!("Size of: ", stringify!(cbq_opts)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(cbq_opts)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).minburst) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(cbq_opts), "::", stringify!(minburst)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).maxburst) as usize - ptr as usize }, 4usize, concat!("Offset of field: ", stringify!(cbq_opts), "::", stringify!(maxburst)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pktsize) as usize - ptr as usize }, 8usize, concat!("Offset of field: ", stringify!(cbq_opts), "::", stringify!(pktsize)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).maxpktsize) as usize - ptr as usize }, 12usize, concat!("Offset of field: ", stringify!(cbq_opts), "::", stringify!(maxpktsize)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ns_per_byte) as usize - ptr as usize }, 16usize, concat!("Offset of field: ", stringify!(cbq_opts), "::", stringify!(ns_per_byte)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).maxidle) as usize - ptr as usize }, 20usize, concat!("Offset of field: ", stringify!(cbq_opts), "::", stringify!(maxidle)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).minidle) as usize - ptr as usize }, 24usize, concat!("Offset of field: ", stringify!(cbq_opts), "::", stringify!(minidle)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).offtime) as usize - ptr as usize }, 28usize, concat!("Offset of field: ", stringify!(cbq_opts), "::", stringify!(offtime)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).flags) as usize - ptr as usize }, 32usize, concat!("Offset of field: ", stringify!(cbq_opts), "::", stringify!(flags)) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct priq_opts { pub flags: u_int32_t, } #[test] fn bindgen_test_layout_priq_opts() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 4usize, concat!("Size of: ", stringify!(priq_opts)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(priq_opts)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).flags) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(priq_opts), "::", stringify!(flags)) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct hfsc_opts { pub rtsc_m1: u_int64_t, pub rtsc_d: u_int64_t, pub rtsc_m2: u_int64_t, pub rtsc_fl: u_int32_t, pub lssc_m1: u_int64_t, pub lssc_d: u_int64_t, pub lssc_m2: u_int64_t, pub lssc_fl: u_int32_t, pub ulsc_m1: u_int64_t, pub ulsc_d: u_int64_t, pub ulsc_m2: u_int64_t, pub ulsc_fl: u_int32_t, pub flags: u_int32_t, } #[test] fn bindgen_test_layout_hfsc_opts() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 96usize, concat!("Size of: ", stringify!(hfsc_opts)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(hfsc_opts)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rtsc_m1) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(hfsc_opts), "::", stringify!(rtsc_m1)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rtsc_d) as usize - ptr as usize }, 8usize, concat!("Offset of field: ", stringify!(hfsc_opts), "::", stringify!(rtsc_d)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rtsc_m2) as usize - ptr as usize }, 16usize, concat!("Offset of field: ", stringify!(hfsc_opts), "::", stringify!(rtsc_m2)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rtsc_fl) as usize - ptr as usize }, 24usize, concat!("Offset of field: ", stringify!(hfsc_opts), "::", stringify!(rtsc_fl)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).lssc_m1) as usize - ptr as usize }, 32usize, concat!("Offset of field: ", stringify!(hfsc_opts), "::", stringify!(lssc_m1)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).lssc_d) as usize - ptr as usize }, 40usize, concat!("Offset of field: ", stringify!(hfsc_opts), "::", stringify!(lssc_d)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).lssc_m2) as usize - ptr as usize }, 48usize, concat!("Offset of field: ", stringify!(hfsc_opts), "::", stringify!(lssc_m2)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).lssc_fl) as usize - ptr as usize }, 56usize, concat!("Offset of field: ", stringify!(hfsc_opts), "::", stringify!(lssc_fl)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ulsc_m1) as usize - ptr as usize }, 64usize, concat!("Offset of field: ", stringify!(hfsc_opts), "::", stringify!(ulsc_m1)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ulsc_d) as usize - ptr as usize }, 72usize, concat!("Offset of field: ", stringify!(hfsc_opts), "::", stringify!(ulsc_d)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ulsc_m2) as usize - ptr as usize }, 80usize, concat!("Offset of field: ", stringify!(hfsc_opts), "::", stringify!(ulsc_m2)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ulsc_fl) as usize - ptr as usize }, 88usize, concat!("Offset of field: ", stringify!(hfsc_opts), "::", stringify!(ulsc_fl)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).flags) as usize - ptr as usize }, 92usize, concat!("Offset of field: ", stringify!(hfsc_opts), "::", stringify!(flags)) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct fairq_opts { pub nbuckets: u_int32_t, pub flags: u_int32_t, pub hogs_m1: u_int64_t, pub lssc_m1: u_int64_t, pub lssc_d: u_int64_t, pub lssc_m2: u_int64_t, } #[test] fn bindgen_test_layout_fairq_opts() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 40usize, concat!("Size of: ", stringify!(fairq_opts)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(fairq_opts)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).nbuckets) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(fairq_opts), "::", stringify!(nbuckets)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).flags) as usize - ptr as usize }, 4usize, concat!("Offset of field: ", stringify!(fairq_opts), "::", stringify!(flags)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).hogs_m1) as usize - ptr as usize }, 8usize, concat!("Offset of field: ", stringify!(fairq_opts), "::", stringify!(hogs_m1)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).lssc_m1) as usize - ptr as usize }, 16usize, concat!("Offset of field: ", stringify!(fairq_opts), "::", stringify!(lssc_m1)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).lssc_d) as usize - ptr as usize }, 24usize, concat!("Offset of field: ", stringify!(fairq_opts), "::", stringify!(lssc_d)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).lssc_m2) as usize - ptr as usize }, 32usize, concat!("Offset of field: ", stringify!(fairq_opts), "::", stringify!(lssc_m2)) ); } #[repr(C)] #[derive(Copy, Clone)] pub struct pf_altq { pub ifname: [::std::os::raw::c_char; 16usize], pub altq_disc: *mut ::std::os::raw::c_void, pub entries: pf_altq__bindgen_ty_1, pub aflags: u_int32_t, pub bwtype: u_int32_t, pub scheduler: u_int32_t, pub tbrsize: u_int32_t, pub ifbandwidth: u_int64_t, pub qname: [::std::os::raw::c_char; 64usize], pub parent: [::std::os::raw::c_char; 64usize], pub parent_qid: u_int32_t, pub qrflags: u_int32_t, pub __bindgen_anon_1: pf_altq__bindgen_ty_2, pub qlimit: u_int32_t, pub flags: u_int32_t, pub bandwidth: u_int64_t, pub pq_u: pf_altq__bindgen_ty_3, pub qid: u_int32_t, } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pf_altq__bindgen_ty_1 { pub tqe_next: *mut pf_altq, pub tqe_prev: *mut *mut pf_altq, } #[test] fn bindgen_test_layout_pf_altq__bindgen_ty_1() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 16usize, concat!("Size of: ", stringify!(pf_altq__bindgen_ty_1)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pf_altq__bindgen_ty_1)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).tqe_next) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pf_altq__bindgen_ty_1), "::", stringify!(tqe_next) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).tqe_prev) as usize - ptr as usize }, 8usize, concat!( "Offset of field: ", stringify!(pf_altq__bindgen_ty_1), "::", stringify!(tqe_prev) ) ); } #[repr(C)] #[derive(Copy, Clone)] pub union pf_altq__bindgen_ty_2 { pub priority: u_int32_t, pub weight: u_int32_t, } #[test] fn bindgen_test_layout_pf_altq__bindgen_ty_2() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 4usize, concat!("Size of: ", stringify!(pf_altq__bindgen_ty_2)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(pf_altq__bindgen_ty_2)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).priority) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pf_altq__bindgen_ty_2), "::", stringify!(priority) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).weight) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pf_altq__bindgen_ty_2), "::", stringify!(weight) ) ); } #[repr(C)] #[derive(Copy, Clone)] pub union pf_altq__bindgen_ty_3 { pub cbq_opts: cbq_opts, pub priq_opts: priq_opts, pub hfsc_opts: hfsc_opts, pub fairq_opts: fairq_opts, } #[test] fn bindgen_test_layout_pf_altq__bindgen_ty_3() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 96usize, concat!("Size of: ", stringify!(pf_altq__bindgen_ty_3)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pf_altq__bindgen_ty_3)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).cbq_opts) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pf_altq__bindgen_ty_3), "::", stringify!(cbq_opts) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).priq_opts) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pf_altq__bindgen_ty_3), "::", stringify!(priq_opts) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).hfsc_opts) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pf_altq__bindgen_ty_3), "::", stringify!(hfsc_opts) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).fairq_opts) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pf_altq__bindgen_ty_3), "::", stringify!(fairq_opts) ) ); } #[test] fn bindgen_test_layout_pf_altq() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 328usize, concat!("Size of: ", stringify!(pf_altq)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pf_altq)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifname) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(pf_altq), "::", stringify!(ifname)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).altq_disc) as usize - ptr as usize }, 16usize, concat!("Offset of field: ", stringify!(pf_altq), "::", stringify!(altq_disc)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).entries) as usize - ptr as usize }, 24usize, concat!("Offset of field: ", stringify!(pf_altq), "::", stringify!(entries)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).aflags) as usize - ptr as usize }, 40usize, concat!("Offset of field: ", stringify!(pf_altq), "::", stringify!(aflags)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).bwtype) as usize - ptr as usize }, 44usize, concat!("Offset of field: ", stringify!(pf_altq), "::", stringify!(bwtype)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).scheduler) as usize - ptr as usize }, 48usize, concat!("Offset of field: ", stringify!(pf_altq), "::", stringify!(scheduler)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).tbrsize) as usize - ptr as usize }, 52usize, concat!("Offset of field: ", stringify!(pf_altq), "::", stringify!(tbrsize)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifbandwidth) as usize - ptr as usize }, 56usize, concat!("Offset of field: ", stringify!(pf_altq), "::", stringify!(ifbandwidth)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).qname) as usize - ptr as usize }, 64usize, concat!("Offset of field: ", stringify!(pf_altq), "::", stringify!(qname)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).parent) as usize - ptr as usize }, 128usize, concat!("Offset of field: ", stringify!(pf_altq), "::", stringify!(parent)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).parent_qid) as usize - ptr as usize }, 192usize, concat!("Offset of field: ", stringify!(pf_altq), "::", stringify!(parent_qid)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).qrflags) as usize - ptr as usize }, 196usize, concat!("Offset of field: ", stringify!(pf_altq), "::", stringify!(qrflags)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).qlimit) as usize - ptr as usize }, 204usize, concat!("Offset of field: ", stringify!(pf_altq), "::", stringify!(qlimit)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).flags) as usize - ptr as usize }, 208usize, concat!("Offset of field: ", stringify!(pf_altq), "::", stringify!(flags)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).bandwidth) as usize - ptr as usize }, 216usize, concat!("Offset of field: ", stringify!(pf_altq), "::", stringify!(bandwidth)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pq_u) as usize - ptr as usize }, 224usize, concat!("Offset of field: ", stringify!(pf_altq), "::", stringify!(pq_u)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).qid) as usize - ptr as usize }, 320usize, concat!("Offset of field: ", stringify!(pf_altq), "::", stringify!(qid)) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pf_tagname { pub entries: pf_tagname__bindgen_ty_1, pub name: [::std::os::raw::c_char; 64usize], pub tag: u_int16_t, pub ref_: ::std::os::raw::c_int, } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pf_tagname__bindgen_ty_1 { pub tqe_next: *mut pf_tagname, pub tqe_prev: *mut *mut pf_tagname, } #[test] fn bindgen_test_layout_pf_tagname__bindgen_ty_1() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 16usize, concat!("Size of: ", stringify!(pf_tagname__bindgen_ty_1)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pf_tagname__bindgen_ty_1)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).tqe_next) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pf_tagname__bindgen_ty_1), "::", stringify!(tqe_next) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).tqe_prev) as usize - ptr as usize }, 8usize, concat!( "Offset of field: ", stringify!(pf_tagname__bindgen_ty_1), "::", stringify!(tqe_prev) ) ); } #[test] fn bindgen_test_layout_pf_tagname() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 88usize, concat!("Size of: ", stringify!(pf_tagname)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pf_tagname)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).entries) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(pf_tagname), "::", stringify!(entries)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).name) as usize - ptr as usize }, 16usize, concat!("Offset of field: ", stringify!(pf_tagname), "::", stringify!(name)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).tag) as usize - ptr as usize }, 80usize, concat!("Offset of field: ", stringify!(pf_tagname), "::", stringify!(tag)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ref_) as usize - ptr as usize }, 84usize, concat!("Offset of field: ", stringify!(pf_tagname), "::", stringify!(ref_)) ); } #[repr(C)] #[derive(Copy, Clone)] pub struct pfioc_pooladdr { pub action: u_int32_t, pub ticket: u_int32_t, pub nr: u_int32_t, pub r_num: u_int32_t, pub r_action: u_int8_t, pub r_last: u_int8_t, pub af: u_int8_t, pub anchor: [::std::os::raw::c_char; 1024usize], pub addr: pf_pooladdr, } #[test] fn bindgen_test_layout_pfioc_pooladdr() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 1136usize, concat!("Size of: ", stringify!(pfioc_pooladdr)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pfioc_pooladdr)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).action) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pfioc_pooladdr), "::", stringify!(action) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ticket) as usize - ptr as usize }, 4usize, concat!( "Offset of field: ", stringify!(pfioc_pooladdr), "::", stringify!(ticket) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).nr) as usize - ptr as usize }, 8usize, concat!("Offset of field: ", stringify!(pfioc_pooladdr), "::", stringify!(nr)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).r_num) as usize - ptr as usize }, 12usize, concat!("Offset of field: ", stringify!(pfioc_pooladdr), "::", stringify!(r_num)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).r_action) as usize - ptr as usize }, 16usize, concat!( "Offset of field: ", stringify!(pfioc_pooladdr), "::", stringify!(r_action) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).r_last) as usize - ptr as usize }, 17usize, concat!( "Offset of field: ", stringify!(pfioc_pooladdr), "::", stringify!(r_last) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).af) as usize - ptr as usize }, 18usize, concat!("Offset of field: ", stringify!(pfioc_pooladdr), "::", stringify!(af)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).anchor) as usize - ptr as usize }, 19usize, concat!( "Offset of field: ", stringify!(pfioc_pooladdr), "::", stringify!(anchor) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).addr) as usize - ptr as usize }, 1048usize, concat!("Offset of field: ", stringify!(pfioc_pooladdr), "::", stringify!(addr)) ); } #[repr(C)] #[derive(Copy, Clone)] pub struct pfioc_rule { pub action: u_int32_t, pub ticket: u_int32_t, pub pool_ticket: u_int32_t, pub nr: u_int32_t, pub anchor: [::std::os::raw::c_char; 1024usize], pub anchor_call: [::std::os::raw::c_char; 1024usize], pub rule: pf_rule, } #[test] fn bindgen_test_layout_pfioc_rule() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 3104usize, concat!("Size of: ", stringify!(pfioc_rule)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pfioc_rule)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).action) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(pfioc_rule), "::", stringify!(action)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ticket) as usize - ptr as usize }, 4usize, concat!("Offset of field: ", stringify!(pfioc_rule), "::", stringify!(ticket)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pool_ticket) as usize - ptr as usize }, 8usize, concat!( "Offset of field: ", stringify!(pfioc_rule), "::", stringify!(pool_ticket) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).nr) as usize - ptr as usize }, 12usize, concat!("Offset of field: ", stringify!(pfioc_rule), "::", stringify!(nr)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).anchor) as usize - ptr as usize }, 16usize, concat!("Offset of field: ", stringify!(pfioc_rule), "::", stringify!(anchor)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).anchor_call) as usize - ptr as usize }, 1040usize, concat!( "Offset of field: ", stringify!(pfioc_rule), "::", stringify!(anchor_call) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rule) as usize - ptr as usize }, 2064usize, concat!("Offset of field: ", stringify!(pfioc_rule), "::", stringify!(rule)) ); } #[repr(C)] #[derive(Copy, Clone)] pub struct pfioc_natlook { pub saddr: pf_addr, pub daddr: pf_addr, pub rsaddr: pf_addr, pub rdaddr: pf_addr, pub sxport: pf_state_xport, pub dxport: pf_state_xport, pub rsxport: pf_state_xport, pub rdxport: pf_state_xport, pub af: sa_family_t, pub proto: u_int8_t, pub proto_variant: u_int8_t, pub direction: u_int8_t, } #[test] fn bindgen_test_layout_pfioc_natlook() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 84usize, concat!("Size of: ", stringify!(pfioc_natlook)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(pfioc_natlook)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).saddr) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(pfioc_natlook), "::", stringify!(saddr)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).daddr) as usize - ptr as usize }, 16usize, concat!("Offset of field: ", stringify!(pfioc_natlook), "::", stringify!(daddr)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rsaddr) as usize - ptr as usize }, 32usize, concat!("Offset of field: ", stringify!(pfioc_natlook), "::", stringify!(rsaddr)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rdaddr) as usize - ptr as usize }, 48usize, concat!("Offset of field: ", stringify!(pfioc_natlook), "::", stringify!(rdaddr)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).sxport) as usize - ptr as usize }, 64usize, concat!("Offset of field: ", stringify!(pfioc_natlook), "::", stringify!(sxport)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).dxport) as usize - ptr as usize }, 68usize, concat!("Offset of field: ", stringify!(pfioc_natlook), "::", stringify!(dxport)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rsxport) as usize - ptr as usize }, 72usize, concat!( "Offset of field: ", stringify!(pfioc_natlook), "::", stringify!(rsxport) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rdxport) as usize - ptr as usize }, 76usize, concat!( "Offset of field: ", stringify!(pfioc_natlook), "::", stringify!(rdxport) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).af) as usize - ptr as usize }, 80usize, concat!("Offset of field: ", stringify!(pfioc_natlook), "::", stringify!(af)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).proto) as usize - ptr as usize }, 81usize, concat!("Offset of field: ", stringify!(pfioc_natlook), "::", stringify!(proto)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).proto_variant) as usize - ptr as usize }, 82usize, concat!( "Offset of field: ", stringify!(pfioc_natlook), "::", stringify!(proto_variant) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).direction) as usize - ptr as usize }, 83usize, concat!( "Offset of field: ", stringify!(pfioc_natlook), "::", stringify!(direction) ) ); } #[repr(C)] #[derive(Copy, Clone)] pub struct pfioc_state { pub state: pfsync_state, } #[test] fn bindgen_test_layout_pfioc_state() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 297usize, concat!("Size of: ", stringify!(pfioc_state)) ); assert_eq!( ::std::mem::align_of::(), 1usize, concat!("Alignment of ", stringify!(pfioc_state)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).state) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(pfioc_state), "::", stringify!(state)) ); } #[repr(C)] #[derive(Copy, Clone)] pub struct pfioc_src_node_kill { pub psnk_af: sa_family_t, pub psnk_src: pf_rule_addr, pub psnk_dst: pf_rule_addr, } #[test] fn bindgen_test_layout_pfioc_src_node_kill() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 136usize, concat!("Size of: ", stringify!(pfioc_src_node_kill)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pfioc_src_node_kill)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).psnk_af) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pfioc_src_node_kill), "::", stringify!(psnk_af) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).psnk_src) as usize - ptr as usize }, 8usize, concat!( "Offset of field: ", stringify!(pfioc_src_node_kill), "::", stringify!(psnk_src) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).psnk_dst) as usize - ptr as usize }, 72usize, concat!( "Offset of field: ", stringify!(pfioc_src_node_kill), "::", stringify!(psnk_dst) ) ); } #[repr(C)] #[derive(Copy, Clone)] pub struct pfioc_state_addr_kill { pub addr: pf_addr_wrap, pub reserved_: [u_int8_t; 3usize], pub neg: u_int8_t, pub xport: pf_rule_xport, } #[test] fn bindgen_test_layout_pfioc_state_addr_kill() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 64usize, concat!("Size of: ", stringify!(pfioc_state_addr_kill)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pfioc_state_addr_kill)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).addr) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pfioc_state_addr_kill), "::", stringify!(addr) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).reserved_) as usize - ptr as usize }, 48usize, concat!( "Offset of field: ", stringify!(pfioc_state_addr_kill), "::", stringify!(reserved_) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).neg) as usize - ptr as usize }, 51usize, concat!( "Offset of field: ", stringify!(pfioc_state_addr_kill), "::", stringify!(neg) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).xport) as usize - ptr as usize }, 52usize, concat!( "Offset of field: ", stringify!(pfioc_state_addr_kill), "::", stringify!(xport) ) ); } #[repr(C)] #[derive(Copy, Clone)] pub struct pfioc_state_kill { pub psk_af: sa_family_t, pub psk_proto: u_int8_t, pub psk_proto_variant: u_int8_t, pub _pad: u_int8_t, pub psk_src: pfioc_state_addr_kill, pub psk_dst: pfioc_state_addr_kill, pub psk_ifname: [::std::os::raw::c_char; 16usize], pub psk_ownername: [::std::os::raw::c_char; 64usize], } #[test] fn bindgen_test_layout_pfioc_state_kill() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 216usize, concat!("Size of: ", stringify!(pfioc_state_kill)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pfioc_state_kill)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).psk_af) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pfioc_state_kill), "::", stringify!(psk_af) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).psk_proto) as usize - ptr as usize }, 1usize, concat!( "Offset of field: ", stringify!(pfioc_state_kill), "::", stringify!(psk_proto) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).psk_proto_variant) as usize - ptr as usize }, 2usize, concat!( "Offset of field: ", stringify!(pfioc_state_kill), "::", stringify!(psk_proto_variant) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr)._pad) as usize - ptr as usize }, 3usize, concat!( "Offset of field: ", stringify!(pfioc_state_kill), "::", stringify!(_pad) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).psk_src) as usize - ptr as usize }, 8usize, concat!( "Offset of field: ", stringify!(pfioc_state_kill), "::", stringify!(psk_src) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).psk_dst) as usize - ptr as usize }, 72usize, concat!( "Offset of field: ", stringify!(pfioc_state_kill), "::", stringify!(psk_dst) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).psk_ifname) as usize - ptr as usize }, 136usize, concat!( "Offset of field: ", stringify!(pfioc_state_kill), "::", stringify!(psk_ifname) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).psk_ownername) as usize - ptr as usize }, 152usize, concat!( "Offset of field: ", stringify!(pfioc_state_kill), "::", stringify!(psk_ownername) ) ); } #[repr(C)] #[derive(Copy, Clone)] pub struct pfioc_states { pub ps_len: ::std::os::raw::c_int, pub ps_u: pfioc_states__bindgen_ty_1, } #[repr(C)] #[derive(Copy, Clone)] pub union pfioc_states__bindgen_ty_1 { pub psu_buf: caddr_t, pub psu_states: *mut pfsync_state, } #[test] fn bindgen_test_layout_pfioc_states__bindgen_ty_1() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 8usize, concat!("Size of: ", stringify!(pfioc_states__bindgen_ty_1)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pfioc_states__bindgen_ty_1)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).psu_buf) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pfioc_states__bindgen_ty_1), "::", stringify!(psu_buf) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).psu_states) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pfioc_states__bindgen_ty_1), "::", stringify!(psu_states) ) ); } #[test] fn bindgen_test_layout_pfioc_states() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 16usize, concat!("Size of: ", stringify!(pfioc_states)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pfioc_states)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ps_len) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(pfioc_states), "::", stringify!(ps_len)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ps_u) as usize - ptr as usize }, 8usize, concat!("Offset of field: ", stringify!(pfioc_states), "::", stringify!(ps_u)) ); } #[repr(C, packed)] #[derive(Debug, Copy, Clone)] pub struct pfioc_token { pub token_value: u_int64_t, pub timestamp: u_int64_t, pub pid: pid_t, pub proc_name: [::std::os::raw::c_char; 64usize], } #[test] fn bindgen_test_layout_pfioc_token() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 84usize, concat!("Size of: ", stringify!(pfioc_token)) ); assert_eq!( ::std::mem::align_of::(), 1usize, concat!("Alignment of ", stringify!(pfioc_token)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).token_value) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pfioc_token), "::", stringify!(token_value) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).timestamp) as usize - ptr as usize }, 8usize, concat!( "Offset of field: ", stringify!(pfioc_token), "::", stringify!(timestamp) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pid) as usize - ptr as usize }, 16usize, concat!("Offset of field: ", stringify!(pfioc_token), "::", stringify!(pid)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).proc_name) as usize - ptr as usize }, 20usize, concat!( "Offset of field: ", stringify!(pfioc_token), "::", stringify!(proc_name) ) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pfioc_kernel_token { pub next: pfioc_kernel_token__bindgen_ty_1, pub token: pfioc_token, } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pfioc_kernel_token__bindgen_ty_1 { pub sle_next: *mut pfioc_kernel_token, } #[test] fn bindgen_test_layout_pfioc_kernel_token__bindgen_ty_1() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 8usize, concat!("Size of: ", stringify!(pfioc_kernel_token__bindgen_ty_1)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pfioc_kernel_token__bindgen_ty_1)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).sle_next) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pfioc_kernel_token__bindgen_ty_1), "::", stringify!(sle_next) ) ); } #[test] fn bindgen_test_layout_pfioc_kernel_token() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 96usize, concat!("Size of: ", stringify!(pfioc_kernel_token)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pfioc_kernel_token)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).next) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pfioc_kernel_token), "::", stringify!(next) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).token) as usize - ptr as usize }, 8usize, concat!( "Offset of field: ", stringify!(pfioc_kernel_token), "::", stringify!(token) ) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pfioc_remove_token { pub token_value: u_int64_t, pub refcount: u_int64_t, } #[test] fn bindgen_test_layout_pfioc_remove_token() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 16usize, concat!("Size of: ", stringify!(pfioc_remove_token)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pfioc_remove_token)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).token_value) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pfioc_remove_token), "::", stringify!(token_value) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).refcount) as usize - ptr as usize }, 8usize, concat!( "Offset of field: ", stringify!(pfioc_remove_token), "::", stringify!(refcount) ) ); } #[repr(C)] #[derive(Copy, Clone)] pub struct pfioc_tokens { pub size: ::std::os::raw::c_int, pub pgt_u: pfioc_tokens__bindgen_ty_1, } #[repr(C)] #[derive(Copy, Clone)] pub union pfioc_tokens__bindgen_ty_1 { pub pgtu_buf: caddr_t, pub pgtu_tokens: *mut pfioc_token, } #[test] fn bindgen_test_layout_pfioc_tokens__bindgen_ty_1() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 8usize, concat!("Size of: ", stringify!(pfioc_tokens__bindgen_ty_1)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pfioc_tokens__bindgen_ty_1)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pgtu_buf) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pfioc_tokens__bindgen_ty_1), "::", stringify!(pgtu_buf) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pgtu_tokens) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pfioc_tokens__bindgen_ty_1), "::", stringify!(pgtu_tokens) ) ); } #[test] fn bindgen_test_layout_pfioc_tokens() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 16usize, concat!("Size of: ", stringify!(pfioc_tokens)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pfioc_tokens)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).size) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(pfioc_tokens), "::", stringify!(size)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pgt_u) as usize - ptr as usize }, 8usize, concat!("Offset of field: ", stringify!(pfioc_tokens), "::", stringify!(pgt_u)) ); } #[repr(C)] #[derive(Copy, Clone)] pub struct pfioc_src_nodes { pub psn_len: ::std::os::raw::c_int, pub psn_u: pfioc_src_nodes__bindgen_ty_1, } #[repr(C)] #[derive(Copy, Clone)] pub union pfioc_src_nodes__bindgen_ty_1 { pub psu_buf: caddr_t, pub psu_src_nodes: *mut pf_src_node, } #[test] fn bindgen_test_layout_pfioc_src_nodes__bindgen_ty_1() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 8usize, concat!("Size of: ", stringify!(pfioc_src_nodes__bindgen_ty_1)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pfioc_src_nodes__bindgen_ty_1)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).psu_buf) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pfioc_src_nodes__bindgen_ty_1), "::", stringify!(psu_buf) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).psu_src_nodes) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pfioc_src_nodes__bindgen_ty_1), "::", stringify!(psu_src_nodes) ) ); } #[test] fn bindgen_test_layout_pfioc_src_nodes() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 16usize, concat!("Size of: ", stringify!(pfioc_src_nodes)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pfioc_src_nodes)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).psn_len) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pfioc_src_nodes), "::", stringify!(psn_len) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).psn_u) as usize - ptr as usize }, 8usize, concat!( "Offset of field: ", stringify!(pfioc_src_nodes), "::", stringify!(psn_u) ) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pfioc_if { pub ifname: [::std::os::raw::c_char; 16usize], } #[test] fn bindgen_test_layout_pfioc_if() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 16usize, concat!("Size of: ", stringify!(pfioc_if)) ); assert_eq!( ::std::mem::align_of::(), 1usize, concat!("Alignment of ", stringify!(pfioc_if)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifname) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(pfioc_if), "::", stringify!(ifname)) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pfioc_tm { pub timeout: ::std::os::raw::c_int, pub seconds: ::std::os::raw::c_int, } #[test] fn bindgen_test_layout_pfioc_tm() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 8usize, concat!("Size of: ", stringify!(pfioc_tm)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(pfioc_tm)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).timeout) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(pfioc_tm), "::", stringify!(timeout)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).seconds) as usize - ptr as usize }, 4usize, concat!("Offset of field: ", stringify!(pfioc_tm), "::", stringify!(seconds)) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pfioc_limit { pub index: ::std::os::raw::c_int, pub limit: ::std::os::raw::c_uint, } #[test] fn bindgen_test_layout_pfioc_limit() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 8usize, concat!("Size of: ", stringify!(pfioc_limit)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(pfioc_limit)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).index) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(pfioc_limit), "::", stringify!(index)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).limit) as usize - ptr as usize }, 4usize, concat!("Offset of field: ", stringify!(pfioc_limit), "::", stringify!(limit)) ); } #[repr(C)] #[derive(Copy, Clone)] pub struct pfioc_altq { pub action: u_int32_t, pub ticket: u_int32_t, pub nr: u_int32_t, pub altq: pf_altq, } #[test] fn bindgen_test_layout_pfioc_altq() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 344usize, concat!("Size of: ", stringify!(pfioc_altq)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pfioc_altq)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).action) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(pfioc_altq), "::", stringify!(action)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ticket) as usize - ptr as usize }, 4usize, concat!("Offset of field: ", stringify!(pfioc_altq), "::", stringify!(ticket)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).nr) as usize - ptr as usize }, 8usize, concat!("Offset of field: ", stringify!(pfioc_altq), "::", stringify!(nr)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).altq) as usize - ptr as usize }, 16usize, concat!("Offset of field: ", stringify!(pfioc_altq), "::", stringify!(altq)) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pfioc_qstats { pub ticket: u_int32_t, pub nr: u_int32_t, pub buf: *mut ::std::os::raw::c_void, pub nbytes: ::std::os::raw::c_int, pub scheduler: u_int8_t, } #[test] fn bindgen_test_layout_pfioc_qstats() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 24usize, concat!("Size of: ", stringify!(pfioc_qstats)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pfioc_qstats)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ticket) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(pfioc_qstats), "::", stringify!(ticket)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).nr) as usize - ptr as usize }, 4usize, concat!("Offset of field: ", stringify!(pfioc_qstats), "::", stringify!(nr)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).buf) as usize - ptr as usize }, 8usize, concat!("Offset of field: ", stringify!(pfioc_qstats), "::", stringify!(buf)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).nbytes) as usize - ptr as usize }, 16usize, concat!("Offset of field: ", stringify!(pfioc_qstats), "::", stringify!(nbytes)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).scheduler) as usize - ptr as usize }, 20usize, concat!( "Offset of field: ", stringify!(pfioc_qstats), "::", stringify!(scheduler) ) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pfioc_ruleset { pub nr: u_int32_t, pub path: [::std::os::raw::c_char; 1024usize], pub name: [::std::os::raw::c_char; 64usize], } #[test] fn bindgen_test_layout_pfioc_ruleset() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 1092usize, concat!("Size of: ", stringify!(pfioc_ruleset)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(pfioc_ruleset)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).nr) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(pfioc_ruleset), "::", stringify!(nr)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).path) as usize - ptr as usize }, 4usize, concat!("Offset of field: ", stringify!(pfioc_ruleset), "::", stringify!(path)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).name) as usize - ptr as usize }, 1028usize, concat!("Offset of field: ", stringify!(pfioc_ruleset), "::", stringify!(name)) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pfioc_trans { pub size: ::std::os::raw::c_int, pub esize: ::std::os::raw::c_int, pub array: *mut pfioc_trans_pfioc_trans_e, } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pfioc_trans_pfioc_trans_e { pub rs_num: ::std::os::raw::c_int, pub anchor: [::std::os::raw::c_char; 1024usize], pub ticket: u_int32_t, } #[test] fn bindgen_test_layout_pfioc_trans_pfioc_trans_e() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 1032usize, concat!("Size of: ", stringify!(pfioc_trans_pfioc_trans_e)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(pfioc_trans_pfioc_trans_e)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rs_num) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pfioc_trans_pfioc_trans_e), "::", stringify!(rs_num) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).anchor) as usize - ptr as usize }, 4usize, concat!( "Offset of field: ", stringify!(pfioc_trans_pfioc_trans_e), "::", stringify!(anchor) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ticket) as usize - ptr as usize }, 1028usize, concat!( "Offset of field: ", stringify!(pfioc_trans_pfioc_trans_e), "::", stringify!(ticket) ) ); } #[test] fn bindgen_test_layout_pfioc_trans() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 16usize, concat!("Size of: ", stringify!(pfioc_trans)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pfioc_trans)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).size) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(pfioc_trans), "::", stringify!(size)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).esize) as usize - ptr as usize }, 4usize, concat!("Offset of field: ", stringify!(pfioc_trans), "::", stringify!(esize)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).array) as usize - ptr as usize }, 8usize, concat!("Offset of field: ", stringify!(pfioc_trans), "::", stringify!(array)) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pfioc_table { pub pfrio_table: pfr_table, pub pfrio_buffer: *mut ::std::os::raw::c_void, pub pfrio_esize: ::std::os::raw::c_int, pub pfrio_size: ::std::os::raw::c_int, pub pfrio_size2: ::std::os::raw::c_int, pub pfrio_nadd: ::std::os::raw::c_int, pub pfrio_ndel: ::std::os::raw::c_int, pub pfrio_nchange: ::std::os::raw::c_int, pub pfrio_flags: ::std::os::raw::c_int, pub pfrio_ticket: u_int32_t, } #[test] fn bindgen_test_layout_pfioc_table() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 1104usize, concat!("Size of: ", stringify!(pfioc_table)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pfioc_table)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfrio_table) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pfioc_table), "::", stringify!(pfrio_table) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfrio_buffer) as usize - ptr as usize }, 1064usize, concat!( "Offset of field: ", stringify!(pfioc_table), "::", stringify!(pfrio_buffer) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfrio_esize) as usize - ptr as usize }, 1072usize, concat!( "Offset of field: ", stringify!(pfioc_table), "::", stringify!(pfrio_esize) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfrio_size) as usize - ptr as usize }, 1076usize, concat!( "Offset of field: ", stringify!(pfioc_table), "::", stringify!(pfrio_size) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfrio_size2) as usize - ptr as usize }, 1080usize, concat!( "Offset of field: ", stringify!(pfioc_table), "::", stringify!(pfrio_size2) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfrio_nadd) as usize - ptr as usize }, 1084usize, concat!( "Offset of field: ", stringify!(pfioc_table), "::", stringify!(pfrio_nadd) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfrio_ndel) as usize - ptr as usize }, 1088usize, concat!( "Offset of field: ", stringify!(pfioc_table), "::", stringify!(pfrio_ndel) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfrio_nchange) as usize - ptr as usize }, 1092usize, concat!( "Offset of field: ", stringify!(pfioc_table), "::", stringify!(pfrio_nchange) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfrio_flags) as usize - ptr as usize }, 1096usize, concat!( "Offset of field: ", stringify!(pfioc_table), "::", stringify!(pfrio_flags) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfrio_ticket) as usize - ptr as usize }, 1100usize, concat!( "Offset of field: ", stringify!(pfioc_table), "::", stringify!(pfrio_ticket) ) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pfioc_iface { pub pfiio_name: [::std::os::raw::c_char; 16usize], pub pfiio_buffer: *mut ::std::os::raw::c_void, pub pfiio_esize: ::std::os::raw::c_int, pub pfiio_size: ::std::os::raw::c_int, pub pfiio_nzero: ::std::os::raw::c_int, pub pfiio_flags: ::std::os::raw::c_int, } #[test] fn bindgen_test_layout_pfioc_iface() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 40usize, concat!("Size of: ", stringify!(pfioc_iface)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pfioc_iface)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfiio_name) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pfioc_iface), "::", stringify!(pfiio_name) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfiio_buffer) as usize - ptr as usize }, 16usize, concat!( "Offset of field: ", stringify!(pfioc_iface), "::", stringify!(pfiio_buffer) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfiio_esize) as usize - ptr as usize }, 24usize, concat!( "Offset of field: ", stringify!(pfioc_iface), "::", stringify!(pfiio_esize) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfiio_size) as usize - ptr as usize }, 28usize, concat!( "Offset of field: ", stringify!(pfioc_iface), "::", stringify!(pfiio_size) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfiio_nzero) as usize - ptr as usize }, 32usize, concat!( "Offset of field: ", stringify!(pfioc_iface), "::", stringify!(pfiio_nzero) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfiio_flags) as usize - ptr as usize }, 36usize, concat!( "Offset of field: ", stringify!(pfioc_iface), "::", stringify!(pfiio_flags) ) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pf_ifspeed { pub ifname: [::std::os::raw::c_char; 16usize], pub baudrate: u_int64_t, } #[test] fn bindgen_test_layout_pf_ifspeed() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 24usize, concat!("Size of: ", stringify!(pf_ifspeed)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pf_ifspeed)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifname) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(pf_ifspeed), "::", stringify!(ifname)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).baudrate) as usize - ptr as usize }, 16usize, concat!("Offset of field: ", stringify!(pf_ifspeed), "::", stringify!(baudrate)) ); } unsafe extern "C" { pub static mut pf_anchors: pf_anchor_global; } unsafe extern "C" { pub static mut pf_main_anchor: pf_anchor; } unsafe extern "C" { pub fn pf_get_ruleset_number(arg1: u_int8_t) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn pf_init_ruleset(arg1: *mut pf_ruleset); } unsafe extern "C" { pub fn pf_anchor_setup( arg1: *mut pf_rule, arg2: *const pf_ruleset, arg3: *const ::std::os::raw::c_char, ) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn pf_anchor_copyout( arg1: *const pf_ruleset, arg2: *const pf_rule, arg3: *mut pfioc_rule, ) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn pf_anchor_remove(arg1: *mut pf_rule); } unsafe extern "C" { pub fn pf_remove_if_empty_ruleset(arg1: *mut pf_ruleset); } unsafe extern "C" { pub fn pf_find_anchor(arg1: *const ::std::os::raw::c_char) -> *mut pf_anchor; } unsafe extern "C" { pub fn pf_find_ruleset(arg1: *const ::std::os::raw::c_char) -> *mut pf_ruleset; } unsafe extern "C" { pub fn pf_find_ruleset_with_owner( arg1: *const ::std::os::raw::c_char, arg2: *const ::std::os::raw::c_char, arg3: ::std::os::raw::c_int, arg4: *mut ::std::os::raw::c_int, ) -> *mut pf_ruleset; } unsafe extern "C" { pub fn pf_find_or_create_ruleset(arg1: *const ::std::os::raw::c_char) -> *mut pf_ruleset; } unsafe extern "C" { pub fn pf_rs_initialize(); } pub type __builtin_va_list = [__va_list_tag; 1usize]; #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct __va_list_tag { pub gp_offset: ::std::os::raw::c_uint, pub fp_offset: ::std::os::raw::c_uint, pub overflow_arg_area: *mut ::std::os::raw::c_void, pub reg_save_area: *mut ::std::os::raw::c_void, } #[test] fn bindgen_test_layout___va_list_tag() { const UNINIT: ::std::mem::MaybeUninit<__va_list_tag> = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::<__va_list_tag>(), 24usize, concat!("Size of: ", stringify!(__va_list_tag)) ); assert_eq!( ::std::mem::align_of::<__va_list_tag>(), 8usize, concat!("Alignment of ", stringify!(__va_list_tag)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).gp_offset) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(__va_list_tag), "::", stringify!(gp_offset) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).fp_offset) as usize - ptr as usize }, 4usize, concat!( "Offset of field: ", stringify!(__va_list_tag), "::", stringify!(fp_offset) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).overflow_arg_area) as usize - ptr as usize }, 8usize, concat!( "Offset of field: ", stringify!(__va_list_tag), "::", stringify!(overflow_arg_area) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).reg_save_area) as usize - ptr as usize }, 16usize, concat!( "Offset of field: ", stringify!(__va_list_tag), "::", stringify!(reg_save_area) ) ); } ================================================ FILE: crates/shadowsocks-service/src/local/redir/sys/unix/pfvar_bindgen_openbsd.rs ================================================ // automatically generated by rust-bindgen 0.69.4 pub const __ISO_C_VISIBLE: u32 = 2011; pub const __XPG_VISIBLE: u32 = 700; pub const __POSIX_VISIBLE: u32 = 200809; pub const __BSD_VISIBLE: u32 = 1; pub const _STACKALIGNBYTES: u32 = 15; pub const _MAX_PAGE_SHIFT: u32 = 12; pub const INT8_MIN: i32 = -128; pub const INT16_MIN: i32 = -32768; pub const INT32_MIN: i32 = -2147483648; pub const INT64_MIN: i64 = -9223372036854775808; pub const INT8_MAX: u32 = 127; pub const INT16_MAX: u32 = 32767; pub const INT32_MAX: u32 = 2147483647; pub const INT64_MAX: u64 = 9223372036854775807; pub const UINT8_MAX: u32 = 255; pub const UINT16_MAX: u32 = 65535; pub const UINT32_MAX: u32 = 4294967295; pub const UINT64_MAX: i32 = -1; pub const INT_LEAST8_MIN: i32 = -128; pub const INT_LEAST16_MIN: i32 = -32768; pub const INT_LEAST32_MIN: i32 = -2147483648; pub const INT_LEAST64_MIN: i64 = -9223372036854775808; pub const INT_LEAST8_MAX: u32 = 127; pub const INT_LEAST16_MAX: u32 = 32767; pub const INT_LEAST32_MAX: u32 = 2147483647; pub const INT_LEAST64_MAX: u64 = 9223372036854775807; pub const UINT_LEAST8_MAX: u32 = 255; pub const UINT_LEAST16_MAX: u32 = 65535; pub const UINT_LEAST32_MAX: u32 = 4294967295; pub const UINT_LEAST64_MAX: i32 = -1; pub const INTPTR_MIN: i64 = -9223372036854775808; pub const INTPTR_MAX: u64 = 9223372036854775807; pub const UINTPTR_MAX: i32 = -1; pub const INTMAX_MIN: i64 = -9223372036854775808; pub const INTMAX_MAX: u64 = 9223372036854775807; pub const UINTMAX_MAX: i32 = -1; pub const PTRDIFF_MIN: i64 = -9223372036854775808; pub const PTRDIFF_MAX: u64 = 9223372036854775807; pub const SIG_ATOMIC_MIN: i32 = -2147483648; pub const SIG_ATOMIC_MAX: u32 = 2147483647; pub const SIZE_MAX: i32 = -1; pub const WCHAR_MIN: i32 = -2147483648; pub const WCHAR_MAX: u32 = 2147483647; pub const WINT_MIN: i32 = -2147483648; pub const WINT_MAX: u32 = 2147483647; pub const UIO_MAXIOV: u32 = 1024; pub const _LITTLE_ENDIAN: u32 = 1234; pub const _BIG_ENDIAN: u32 = 4321; pub const _PDP_ENDIAN: u32 = 3412; pub const _QUAD_HIGHWORD: u32 = 1; pub const _QUAD_LOWWORD: u32 = 0; pub const LITTLE_ENDIAN: u32 = 1234; pub const BIG_ENDIAN: u32 = 4321; pub const PDP_ENDIAN: u32 = 3412; pub const SOCK_STREAM: u32 = 1; pub const SOCK_DGRAM: u32 = 2; pub const SOCK_RAW: u32 = 3; pub const SOCK_RDM: u32 = 4; pub const SOCK_SEQPACKET: u32 = 5; pub const SOCK_CLOEXEC: u32 = 32768; pub const SOCK_NONBLOCK: u32 = 16384; pub const SOCK_DNS: u32 = 4096; pub const SO_DEBUG: u32 = 1; pub const SO_ACCEPTCONN: u32 = 2; pub const SO_REUSEADDR: u32 = 4; pub const SO_KEEPALIVE: u32 = 8; pub const SO_DONTROUTE: u32 = 16; pub const SO_BROADCAST: u32 = 32; pub const SO_USELOOPBACK: u32 = 64; pub const SO_LINGER: u32 = 128; pub const SO_OOBINLINE: u32 = 256; pub const SO_REUSEPORT: u32 = 512; pub const SO_TIMESTAMP: u32 = 2048; pub const SO_BINDANY: u32 = 4096; pub const SO_ZEROIZE: u32 = 8192; pub const SO_SNDBUF: u32 = 4097; pub const SO_RCVBUF: u32 = 4098; pub const SO_SNDLOWAT: u32 = 4099; pub const SO_RCVLOWAT: u32 = 4100; pub const SO_SNDTIMEO: u32 = 4101; pub const SO_RCVTIMEO: u32 = 4102; pub const SO_ERROR: u32 = 4103; pub const SO_TYPE: u32 = 4104; pub const SO_NETPROC: u32 = 4128; pub const SO_RTABLE: u32 = 4129; pub const SO_PEERCRED: u32 = 4130; pub const SO_SPLICE: u32 = 4131; pub const SO_DOMAIN: u32 = 4132; pub const SO_PROTOCOL: u32 = 4133; pub const RT_TABLEID_MAX: u32 = 255; pub const RT_TABLEID_BITS: u32 = 8; pub const RT_TABLEID_MASK: u32 = 255; pub const SOL_SOCKET: u32 = 65535; pub const AF_UNSPEC: u32 = 0; pub const AF_UNIX: u32 = 1; pub const AF_LOCAL: u32 = 1; pub const AF_INET: u32 = 2; pub const AF_IMPLINK: u32 = 3; pub const AF_PUP: u32 = 4; pub const AF_CHAOS: u32 = 5; pub const AF_NS: u32 = 6; pub const AF_ISO: u32 = 7; pub const AF_OSI: u32 = 7; pub const AF_ECMA: u32 = 8; pub const AF_DATAKIT: u32 = 9; pub const AF_CCITT: u32 = 10; pub const AF_SNA: u32 = 11; pub const AF_DECnet: u32 = 12; pub const AF_DLI: u32 = 13; pub const AF_LAT: u32 = 14; pub const AF_HYLINK: u32 = 15; pub const AF_APPLETALK: u32 = 16; pub const AF_ROUTE: u32 = 17; pub const AF_LINK: u32 = 18; pub const pseudo_AF_XTP: u32 = 19; pub const AF_COIP: u32 = 20; pub const AF_CNT: u32 = 21; pub const pseudo_AF_RTIP: u32 = 22; pub const AF_IPX: u32 = 23; pub const AF_INET6: u32 = 24; pub const pseudo_AF_PIP: u32 = 25; pub const AF_ISDN: u32 = 26; pub const AF_E164: u32 = 26; pub const AF_NATM: u32 = 27; pub const AF_ENCAP: u32 = 28; pub const AF_SIP: u32 = 29; pub const AF_KEY: u32 = 30; pub const pseudo_AF_HDRCMPLT: u32 = 31; pub const AF_BLUETOOTH: u32 = 32; pub const AF_MPLS: u32 = 33; pub const pseudo_AF_PFLOW: u32 = 34; pub const pseudo_AF_PIPEX: u32 = 35; pub const AF_MAX: u32 = 36; pub const PF_UNSPEC: u32 = 0; pub const PF_LOCAL: u32 = 1; pub const PF_UNIX: u32 = 1; pub const PF_INET: u32 = 2; pub const PF_IMPLINK: u32 = 3; pub const PF_PUP: u32 = 4; pub const PF_CHAOS: u32 = 5; pub const PF_NS: u32 = 6; pub const PF_ISO: u32 = 7; pub const PF_OSI: u32 = 7; pub const PF_ECMA: u32 = 8; pub const PF_DATAKIT: u32 = 9; pub const PF_CCITT: u32 = 10; pub const PF_SNA: u32 = 11; pub const PF_DECnet: u32 = 12; pub const PF_DLI: u32 = 13; pub const PF_LAT: u32 = 14; pub const PF_HYLINK: u32 = 15; pub const PF_APPLETALK: u32 = 16; pub const PF_ROUTE: u32 = 17; pub const PF_LINK: u32 = 18; pub const PF_XTP: u32 = 19; pub const PF_COIP: u32 = 20; pub const PF_CNT: u32 = 21; pub const PF_IPX: u32 = 23; pub const PF_INET6: u32 = 24; pub const PF_RTIP: u32 = 22; pub const PF_PIP: u32 = 25; pub const PF_ISDN: u32 = 26; pub const PF_NATM: u32 = 27; pub const PF_ENCAP: u32 = 28; pub const PF_SIP: u32 = 29; pub const PF_KEY: u32 = 30; pub const PF_BPF: u32 = 31; pub const PF_BLUETOOTH: u32 = 32; pub const PF_MPLS: u32 = 33; pub const PF_PFLOW: u32 = 34; pub const PF_PIPEX: u32 = 35; pub const PF_MAX: u32 = 36; pub const SHUT_RD: u32 = 0; pub const SHUT_WR: u32 = 1; pub const SHUT_RDWR: u32 = 2; pub const NET_MAXID: u32 = 36; pub const NET_RT_DUMP: u32 = 1; pub const NET_RT_FLAGS: u32 = 2; pub const NET_RT_IFLIST: u32 = 3; pub const NET_RT_STATS: u32 = 4; pub const NET_RT_TABLE: u32 = 5; pub const NET_RT_IFNAMES: u32 = 6; pub const NET_RT_SOURCE: u32 = 7; pub const NET_RT_MAXID: u32 = 8; pub const NET_UNIX_INFLIGHT: u32 = 6; pub const NET_UNIX_DEFERRED: u32 = 7; pub const NET_UNIX_MAXID: u32 = 8; pub const UNPCTL_RECVSPACE: u32 = 1; pub const UNPCTL_SENDSPACE: u32 = 2; pub const NET_UNIX_PROTO_MAXID: u32 = 3; pub const NET_LINK_IFRXQ: u32 = 1; pub const NET_LINK_MAXID: u32 = 2; pub const NET_LINK_IFRXQ_PRESSURE_RETURN: u32 = 1; pub const NET_LINK_IFRXQ_PRESSURE_DROP: u32 = 2; pub const NET_LINK_IFRXQ_MAXID: u32 = 3; pub const NET_KEY_SADB_DUMP: u32 = 1; pub const NET_KEY_SPD_DUMP: u32 = 2; pub const NET_KEY_MAXID: u32 = 3; pub const NET_BPF_BUFSIZE: u32 = 1; pub const NET_BPF_MAXBUFSIZE: u32 = 2; pub const NET_BPF_MAXID: u32 = 3; pub const NET_PFLOW_STATS: u32 = 1; pub const NET_PFLOW_MAXID: u32 = 2; pub const SOMAXCONN: u32 = 128; pub const MSG_OOB: u32 = 1; pub const MSG_PEEK: u32 = 2; pub const MSG_DONTROUTE: u32 = 4; pub const MSG_EOR: u32 = 8; pub const MSG_TRUNC: u32 = 16; pub const MSG_CTRUNC: u32 = 32; pub const MSG_WAITALL: u32 = 64; pub const MSG_DONTWAIT: u32 = 128; pub const MSG_BCAST: u32 = 256; pub const MSG_MCAST: u32 = 512; pub const MSG_NOSIGNAL: u32 = 1024; pub const MSG_CMSG_CLOEXEC: u32 = 2048; pub const MSG_WAITFORONE: u32 = 4096; pub const SCM_RIGHTS: u32 = 1; pub const SCM_TIMESTAMP: u32 = 4; pub const IF_NAMESIZE: u32 = 16; pub const FD_SETSIZE: u32 = 1024; pub const __NBBY: u32 = 8; pub const NBBY: u32 = 8; pub const DST_NONE: u32 = 0; pub const DST_USA: u32 = 1; pub const DST_AUST: u32 = 2; pub const DST_WET: u32 = 3; pub const DST_MET: u32 = 4; pub const DST_EET: u32 = 5; pub const DST_CAN: u32 = 6; pub const ITIMER_REAL: u32 = 0; pub const ITIMER_VIRTUAL: u32 = 1; pub const ITIMER_PROF: u32 = 2; pub const CLOCKS_PER_SEC: u32 = 100; pub const CLOCK_REALTIME: u32 = 0; pub const CLOCK_PROCESS_CPUTIME_ID: u32 = 2; pub const CLOCK_MONOTONIC: u32 = 3; pub const CLOCK_THREAD_CPUTIME_ID: u32 = 4; pub const CLOCK_UPTIME: u32 = 5; pub const CLOCK_BOOTTIME: u32 = 6; pub const TIMER_RELTIME: u32 = 0; pub const TIMER_ABSTIME: u32 = 1; pub const CLK_TCK: u32 = 100; pub const TIME_UTC: u32 = 1; pub const MCLPOOLS: u32 = 8; pub const IFQ_NQUEUES: u32 = 8; pub const IFQ_MINPRIO: u32 = 0; pub const IFQ_MAXPRIO: u32 = 7; pub const IFQ_DEFPRIO: u32 = 3; pub const LINK_STATE_UNKNOWN: u32 = 0; pub const LINK_STATE_INVALID: u32 = 1; pub const LINK_STATE_DOWN: u32 = 2; pub const LINK_STATE_KALIVE_DOWN: u32 = 3; pub const LINK_STATE_UP: u32 = 4; pub const LINK_STATE_HALF_DUPLEX: u32 = 5; pub const LINK_STATE_FULL_DUPLEX: u32 = 6; pub const IFNAMSIZ: u32 = 16; pub const IFDESCRSIZE: u32 = 64; pub const IFF_UP: u32 = 1; pub const IFF_BROADCAST: u32 = 2; pub const IFF_DEBUG: u32 = 4; pub const IFF_LOOPBACK: u32 = 8; pub const IFF_POINTOPOINT: u32 = 16; pub const IFF_STATICARP: u32 = 32; pub const IFF_RUNNING: u32 = 64; pub const IFF_NOARP: u32 = 128; pub const IFF_PROMISC: u32 = 256; pub const IFF_ALLMULTI: u32 = 512; pub const IFF_OACTIVE: u32 = 1024; pub const IFF_SIMPLEX: u32 = 2048; pub const IFF_LINK0: u32 = 4096; pub const IFF_LINK1: u32 = 8192; pub const IFF_LINK2: u32 = 16384; pub const IFF_MULTICAST: u32 = 32768; pub const IFF_CANTCHANGE: u32 = 36434; pub const IFXF_MPSAFE: u32 = 1; pub const IFXF_CLONED: u32 = 2; pub const IFXF_AUTOCONF6TEMP: u32 = 4; pub const IFXF_MPLS: u32 = 8; pub const IFXF_WOL: u32 = 16; pub const IFXF_AUTOCONF6: u32 = 32; pub const IFXF_INET6_NOSOII: u32 = 64; pub const IFXF_AUTOCONF4: u32 = 128; pub const IFXF_MONITOR: u32 = 256; pub const IFXF_LRO: u32 = 512; pub const IFXF_CANTCHANGE: u32 = 3; pub const IFCAP_CSUM_IPv4: u32 = 1; pub const IFCAP_CSUM_TCPv4: u32 = 2; pub const IFCAP_CSUM_UDPv4: u32 = 4; pub const IFCAP_VLAN_MTU: u32 = 16; pub const IFCAP_VLAN_HWTAGGING: u32 = 32; pub const IFCAP_CSUM_TCPv6: u32 = 128; pub const IFCAP_CSUM_UDPv6: u32 = 256; pub const IFCAP_TSOv4: u32 = 4096; pub const IFCAP_TSOv6: u32 = 8192; pub const IFCAP_LRO: u32 = 16384; pub const IFCAP_WOL: u32 = 32768; pub const IFCAP_CSUM_MASK: u32 = 391; pub const IFQCTL_LEN: u32 = 1; pub const IFQCTL_MAXLEN: u32 = 2; pub const IFQCTL_DROPS: u32 = 3; pub const IFQCTL_CONGESTION: u32 = 4; pub const IFQCTL_MAXID: u32 = 5; pub const IFAN_ARRIVAL: u32 = 0; pub const IFAN_DEPARTURE: u32 = 1; pub const IFG_ALL: &[u8; 4] = b"all\0"; pub const IFG_EGRESS: &[u8; 7] = b"egress\0"; pub const IF_HDRPRIO_MIN: u32 = 0; pub const IF_HDRPRIO_MAX: u32 = 7; pub const IF_HDRPRIO_PACKET: i32 = -1; pub const IF_HDRPRIO_PAYLOAD: i32 = -2; pub const IF_HDRPRIO_OUTER: i32 = -3; pub const IF_PWE3_ETHERNET: u32 = 1; pub const IF_PWE3_IP: u32 = 2; pub const IFLR_PREFIX: u32 = 32768; pub const IFSFF_ADDR_EEPROM: u32 = 160; pub const IFSFF_ADDR_DDM: u32 = 162; pub const IFSFF_DATA_LEN: u32 = 256; pub const ARPHRD_ETHER: u32 = 1; pub const ARPHRD_IEEE802: u32 = 6; pub const ARPHRD_FRELAY: u32 = 15; pub const ARPHRD_IEEE1394: u32 = 24; pub const ARPOP_REQUEST: u32 = 1; pub const ARPOP_REPLY: u32 = 2; pub const ARPOP_REVREQUEST: u32 = 3; pub const ARPOP_REVREPLY: u32 = 4; pub const ARPOP_INVREQUEST: u32 = 8; pub const ARPOP_INVREPLY: u32 = 9; pub const ATF_INUSE: u32 = 1; pub const ATF_COM: u32 = 2; pub const ATF_PERM: u32 = 4; pub const ATF_PUBL: u32 = 8; pub const ATF_USETRAILERS: u32 = 16; pub const SPLAY_NEGINF: i32 = -1; pub const SPLAY_INF: u32 = 1; pub const RB_BLACK: u32 = 0; pub const RB_RED: u32 = 1; pub const RB_NEGINF: i32 = -1; pub const RB_INF: u32 = 1; pub const LO_CLASSFLAGS: u32 = 65535; pub const LO_INITIALIZED: u32 = 65536; pub const LO_WITNESS: u32 = 131072; pub const LO_QUIET: u32 = 262144; pub const LO_RECURSABLE: u32 = 524288; pub const LO_SLEEPABLE: u32 = 1048576; pub const LO_UPGRADABLE: u32 = 2097152; pub const LO_DUPOK: u32 = 4194304; pub const LO_IS_VNODE: u32 = 8388608; pub const LO_CLASSMASK: u32 = 251658240; pub const LO_NOPROFILE: u32 = 268435456; pub const LO_NEW: u32 = 536870912; pub const LO_CLASSSHIFT: u32 = 24; pub const RWL_DUPOK: u32 = 1; pub const RWL_NOWITNESS: u32 = 2; pub const RWL_IS_VNODE: u32 = 4; pub const RWLOCK_WAIT: u32 = 1; pub const RWLOCK_WRWANT: u32 = 2; pub const RWLOCK_WRLOCK: u32 = 4; pub const RWLOCK_MASK: u32 = 7; pub const RWLOCK_READER_SHIFT: u32 = 3; pub const RWLOCK_READ_INCR: u32 = 8; pub const RW_WRITE: u32 = 1; pub const RW_READ: u32 = 2; pub const RW_DOWNGRADE: u32 = 4; pub const RW_OPMASK: u32 = 7; pub const RW_INTR: u32 = 16; pub const RW_SLEEPFAIL: u32 = 32; pub const RW_NOSLEEP: u32 = 64; pub const RW_RECURSEFAIL: u32 = 128; pub const RW_DUPOK: u32 = 256; pub const RW_WRITE_OTHER: u32 = 256; pub const ARG_MAX: u32 = 524288; pub const CHILD_MAX: u32 = 80; pub const LINK_MAX: u32 = 32767; pub const MAX_CANON: u32 = 255; pub const MAX_INPUT: u32 = 255; pub const NAME_MAX: u32 = 255; pub const NGROUPS_MAX: u32 = 16; pub const OPEN_MAX: u32 = 64; pub const PATH_MAX: u32 = 1024; pub const PIPE_BUF: u32 = 512; pub const SYMLINK_MAX: u32 = 1024; pub const SYMLOOP_MAX: u32 = 32; pub const BC_DIM_MAX: u32 = 65535; pub const COLL_WEIGHTS_MAX: u32 = 2; pub const EXPR_NEST_MAX: u32 = 32; pub const LINE_MAX: u32 = 2048; pub const RE_DUP_MAX: u32 = 255; pub const IOV_MAX: u32 = 1024; pub const NZERO: u32 = 20; pub const TTY_NAME_MAX: u32 = 260; pub const LOGIN_NAME_MAX: u32 = 32; pub const HOST_NAME_MAX: u32 = 255; pub const _MAXCOMLEN: u32 = 24; pub const TIMEOUT_PROC: u32 = 1; pub const TIMEOUT_ONQUEUE: u32 = 2; pub const TIMEOUT_INITIALIZED: u32 = 4; pub const TIMEOUT_TRIGGERED: u32 = 8; pub const TIMEOUT_MPSAFE: u32 = 16; pub const IPPROTO_IP: u32 = 0; pub const IPPROTO_HOPOPTS: u32 = 0; pub const IPPROTO_ICMP: u32 = 1; pub const IPPROTO_IGMP: u32 = 2; pub const IPPROTO_GGP: u32 = 3; pub const IPPROTO_IPIP: u32 = 4; pub const IPPROTO_IPV4: u32 = 4; pub const IPPROTO_TCP: u32 = 6; pub const IPPROTO_EGP: u32 = 8; pub const IPPROTO_PUP: u32 = 12; pub const IPPROTO_UDP: u32 = 17; pub const IPPROTO_IDP: u32 = 22; pub const IPPROTO_TP: u32 = 29; pub const IPPROTO_IPV6: u32 = 41; pub const IPPROTO_ROUTING: u32 = 43; pub const IPPROTO_FRAGMENT: u32 = 44; pub const IPPROTO_RSVP: u32 = 46; pub const IPPROTO_GRE: u32 = 47; pub const IPPROTO_ESP: u32 = 50; pub const IPPROTO_AH: u32 = 51; pub const IPPROTO_MOBILE: u32 = 55; pub const IPPROTO_ICMPV6: u32 = 58; pub const IPPROTO_NONE: u32 = 59; pub const IPPROTO_DSTOPTS: u32 = 60; pub const IPPROTO_EON: u32 = 80; pub const IPPROTO_ETHERIP: u32 = 97; pub const IPPROTO_ENCAP: u32 = 98; pub const IPPROTO_PIM: u32 = 103; pub const IPPROTO_IPCOMP: u32 = 108; pub const IPPROTO_CARP: u32 = 112; pub const IPPROTO_SCTP: u32 = 132; pub const IPPROTO_UDPLITE: u32 = 136; pub const IPPROTO_MPLS: u32 = 137; pub const IPPROTO_PFSYNC: u32 = 240; pub const IPPROTO_RAW: u32 = 255; pub const IPPROTO_MAX: u32 = 256; pub const IPPROTO_DIVERT: u32 = 258; pub const IPPORT_RESERVED: u32 = 1024; pub const IPPORT_USERRESERVED: u32 = 49151; pub const IPPORT_HIFIRSTAUTO: u32 = 49152; pub const IPPORT_HILASTAUTO: u32 = 65535; pub const IPPROTO_DONE: u32 = 257; pub const IN_CLASSA_NSHIFT: u32 = 24; pub const IN_CLASSA_MAX: u32 = 128; pub const IN_CLASSB_NSHIFT: u32 = 16; pub const IN_CLASSB_MAX: u32 = 65536; pub const IN_CLASSC_NSHIFT: u32 = 8; pub const IN_CLASSD_NSHIFT: u32 = 28; pub const IN_RFC3021_NSHIFT: u32 = 31; pub const IN_LOOPBACKNET: u32 = 127; pub const IP_OPTIONS: u32 = 1; pub const IP_HDRINCL: u32 = 2; pub const IP_TOS: u32 = 3; pub const IP_TTL: u32 = 4; pub const IP_RECVOPTS: u32 = 5; pub const IP_RECVRETOPTS: u32 = 6; pub const IP_RECVDSTADDR: u32 = 7; pub const IP_RETOPTS: u32 = 8; pub const IP_MULTICAST_IF: u32 = 9; pub const IP_MULTICAST_TTL: u32 = 10; pub const IP_MULTICAST_LOOP: u32 = 11; pub const IP_ADD_MEMBERSHIP: u32 = 12; pub const IP_DROP_MEMBERSHIP: u32 = 13; pub const IP_PORTRANGE: u32 = 19; pub const IP_AUTH_LEVEL: u32 = 20; pub const IP_ESP_TRANS_LEVEL: u32 = 21; pub const IP_ESP_NETWORK_LEVEL: u32 = 22; pub const IP_IPSEC_LOCAL_ID: u32 = 23; pub const IP_IPSEC_REMOTE_ID: u32 = 24; pub const IP_IPSEC_LOCAL_CRED: u32 = 25; pub const IP_IPSEC_REMOTE_CRED: u32 = 26; pub const IP_IPSEC_LOCAL_AUTH: u32 = 27; pub const IP_IPSEC_REMOTE_AUTH: u32 = 28; pub const IP_IPCOMP_LEVEL: u32 = 29; pub const IP_RECVIF: u32 = 30; pub const IP_RECVTTL: u32 = 31; pub const IP_MINTTL: u32 = 32; pub const IP_RECVDSTPORT: u32 = 33; pub const IP_PIPEX: u32 = 34; pub const IP_RECVRTABLE: u32 = 35; pub const IP_IPSECFLOWINFO: u32 = 36; pub const IP_IPDEFTTL: u32 = 37; pub const IP_SENDSRCADDR: u32 = 7; pub const IP_RTABLE: u32 = 4129; pub const IPSEC_LEVEL_BYPASS: u32 = 0; pub const IPSEC_LEVEL_NONE: u32 = 0; pub const IPSEC_LEVEL_AVAIL: u32 = 1; pub const IPSEC_LEVEL_USE: u32 = 2; pub const IPSEC_LEVEL_REQUIRE: u32 = 3; pub const IPSEC_LEVEL_UNIQUE: u32 = 4; pub const IPSEC_LEVEL_DEFAULT: u32 = 1; pub const IPSEC_AUTH_LEVEL_DEFAULT: u32 = 1; pub const IPSEC_ESP_TRANS_LEVEL_DEFAULT: u32 = 1; pub const IPSEC_ESP_NETWORK_LEVEL_DEFAULT: u32 = 1; pub const IPSEC_IPCOMP_LEVEL_DEFAULT: u32 = 1; pub const IP_DEFAULT_MULTICAST_TTL: u32 = 1; pub const IP_DEFAULT_MULTICAST_LOOP: u32 = 1; pub const IP_MIN_MEMBERSHIPS: u32 = 15; pub const IP_MAX_MEMBERSHIPS: u32 = 4095; pub const IP_PORTRANGE_DEFAULT: u32 = 0; pub const IP_PORTRANGE_HIGH: u32 = 1; pub const IP_PORTRANGE_LOW: u32 = 2; pub const INET_ADDRSTRLEN: u32 = 16; pub const IPPROTO_MAXID: u32 = 259; pub const IPCTL_FORWARDING: u32 = 1; pub const IPCTL_SENDREDIRECTS: u32 = 2; pub const IPCTL_DEFTTL: u32 = 3; pub const IPCTL_SOURCEROUTE: u32 = 5; pub const IPCTL_DIRECTEDBCAST: u32 = 6; pub const IPCTL_IPPORT_FIRSTAUTO: u32 = 7; pub const IPCTL_IPPORT_LASTAUTO: u32 = 8; pub const IPCTL_IPPORT_HIFIRSTAUTO: u32 = 9; pub const IPCTL_IPPORT_HILASTAUTO: u32 = 10; pub const IPCTL_IPPORT_MAXQUEUE: u32 = 11; pub const IPCTL_ENCDEBUG: u32 = 12; pub const IPCTL_IPSEC_STATS: u32 = 13; pub const IPCTL_IPSEC_EXPIRE_ACQUIRE: u32 = 14; pub const IPCTL_IPSEC_EMBRYONIC_SA_TIMEOUT: u32 = 15; pub const IPCTL_IPSEC_REQUIRE_PFS: u32 = 16; pub const IPCTL_IPSEC_SOFT_ALLOCATIONS: u32 = 17; pub const IPCTL_IPSEC_ALLOCATIONS: u32 = 18; pub const IPCTL_IPSEC_SOFT_BYTES: u32 = 19; pub const IPCTL_IPSEC_BYTES: u32 = 20; pub const IPCTL_IPSEC_TIMEOUT: u32 = 21; pub const IPCTL_IPSEC_SOFT_TIMEOUT: u32 = 22; pub const IPCTL_IPSEC_SOFT_FIRSTUSE: u32 = 23; pub const IPCTL_IPSEC_FIRSTUSE: u32 = 24; pub const IPCTL_IPSEC_ENC_ALGORITHM: u32 = 25; pub const IPCTL_IPSEC_AUTH_ALGORITHM: u32 = 26; pub const IPCTL_MTUDISC: u32 = 27; pub const IPCTL_MTUDISCTIMEOUT: u32 = 28; pub const IPCTL_IPSEC_IPCOMP_ALGORITHM: u32 = 29; pub const IPCTL_IFQUEUE: u32 = 30; pub const IPCTL_MFORWARDING: u32 = 31; pub const IPCTL_MULTIPATH: u32 = 32; pub const IPCTL_STATS: u32 = 33; pub const IPCTL_MRTPROTO: u32 = 34; pub const IPCTL_MRTSTATS: u32 = 35; pub const IPCTL_ARPQUEUED: u32 = 36; pub const IPCTL_MRTMFC: u32 = 37; pub const IPCTL_MRTVIF: u32 = 38; pub const IPCTL_ARPTIMEOUT: u32 = 39; pub const IPCTL_ARPDOWN: u32 = 40; pub const IPCTL_ARPQUEUE: u32 = 41; pub const IPCTL_MAXID: u32 = 42; pub const INET6_ADDRSTRLEN: u32 = 46; pub const __IPV6_ADDR_SCOPE_NODELOCAL: u32 = 1; pub const __IPV6_ADDR_SCOPE_INTFACELOCAL: u32 = 1; pub const __IPV6_ADDR_SCOPE_LINKLOCAL: u32 = 2; pub const __IPV6_ADDR_SCOPE_SITELOCAL: u32 = 5; pub const __IPV6_ADDR_SCOPE_ORGLOCAL: u32 = 8; pub const __IPV6_ADDR_SCOPE_GLOBAL: u32 = 14; pub const IPV6_UNICAST_HOPS: u32 = 4; pub const IPV6_MULTICAST_IF: u32 = 9; pub const IPV6_MULTICAST_HOPS: u32 = 10; pub const IPV6_MULTICAST_LOOP: u32 = 11; pub const IPV6_JOIN_GROUP: u32 = 12; pub const IPV6_LEAVE_GROUP: u32 = 13; pub const IPV6_PORTRANGE: u32 = 14; pub const ICMP6_FILTER: u32 = 18; pub const IPV6_CHECKSUM: u32 = 26; pub const IPV6_V6ONLY: u32 = 27; pub const IPV6_RTHDRDSTOPTS: u32 = 35; pub const IPV6_RECVPKTINFO: u32 = 36; pub const IPV6_RECVHOPLIMIT: u32 = 37; pub const IPV6_RECVRTHDR: u32 = 38; pub const IPV6_RECVHOPOPTS: u32 = 39; pub const IPV6_RECVDSTOPTS: u32 = 40; pub const IPV6_USE_MIN_MTU: u32 = 42; pub const IPV6_RECVPATHMTU: u32 = 43; pub const IPV6_PATHMTU: u32 = 44; pub const IPV6_PKTINFO: u32 = 46; pub const IPV6_HOPLIMIT: u32 = 47; pub const IPV6_NEXTHOP: u32 = 48; pub const IPV6_HOPOPTS: u32 = 49; pub const IPV6_DSTOPTS: u32 = 50; pub const IPV6_RTHDR: u32 = 51; pub const IPV6_AUTH_LEVEL: u32 = 53; pub const IPV6_ESP_TRANS_LEVEL: u32 = 54; pub const IPV6_ESP_NETWORK_LEVEL: u32 = 55; pub const IPSEC6_OUTSA: u32 = 56; pub const IPV6_RECVTCLASS: u32 = 57; pub const IPV6_AUTOFLOWLABEL: u32 = 59; pub const IPV6_IPCOMP_LEVEL: u32 = 60; pub const IPV6_TCLASS: u32 = 61; pub const IPV6_DONTFRAG: u32 = 62; pub const IPV6_PIPEX: u32 = 63; pub const IPV6_RECVDSTPORT: u32 = 64; pub const IPV6_MINHOPCOUNT: u32 = 65; pub const IPV6_RTABLE: u32 = 4129; pub const IPV6_RTHDR_LOOSE: u32 = 0; pub const IPV6_RTHDR_TYPE_0: u32 = 0; pub const IPV6_DEFAULT_MULTICAST_HOPS: u32 = 1; pub const IPV6_DEFAULT_MULTICAST_LOOP: u32 = 1; pub const IPV6_PORTRANGE_DEFAULT: u32 = 0; pub const IPV6_PORTRANGE_HIGH: u32 = 1; pub const IPV6_PORTRANGE_LOW: u32 = 2; pub const IPV6PROTO_MAXID: u32 = 259; pub const IPV6CTL_FORWARDING: u32 = 1; pub const IPV6CTL_SENDREDIRECTS: u32 = 2; pub const IPV6CTL_DEFHLIM: u32 = 3; pub const IPV6CTL_FORWSRCRT: u32 = 5; pub const IPV6CTL_STATS: u32 = 6; pub const IPV6CTL_MRTSTATS: u32 = 7; pub const IPV6CTL_MRTPROTO: u32 = 8; pub const IPV6CTL_MAXFRAGPACKETS: u32 = 9; pub const IPV6CTL_SOURCECHECK: u32 = 10; pub const IPV6CTL_SOURCECHECK_LOGINT: u32 = 11; pub const IPV6CTL_ACCEPT_RTADV: u32 = 12; pub const IPV6CTL_LOG_INTERVAL: u32 = 14; pub const IPV6CTL_HDRNESTLIMIT: u32 = 15; pub const IPV6CTL_DAD_COUNT: u32 = 16; pub const IPV6CTL_AUTO_FLOWLABEL: u32 = 17; pub const IPV6CTL_DEFMCASTHLIM: u32 = 18; pub const IPV6CTL_USE_DEPRECATED: u32 = 21; pub const IPV6CTL_MAXFRAGS: u32 = 41; pub const IPV6CTL_MFORWARDING: u32 = 42; pub const IPV6CTL_MULTIPATH: u32 = 43; pub const IPV6CTL_MCAST_PMTU: u32 = 44; pub const IPV6CTL_NEIGHBORGCTHRESH: u32 = 45; pub const IPV6CTL_MAXDYNROUTES: u32 = 48; pub const IPV6CTL_DAD_PENDING: u32 = 49; pub const IPV6CTL_MTUDISCTIMEOUT: u32 = 50; pub const IPV6CTL_IFQUEUE: u32 = 51; pub const IPV6CTL_MRTMIF: u32 = 52; pub const IPV6CTL_MRTMFC: u32 = 53; pub const IPV6CTL_SOIIKEY: u32 = 54; pub const IPV6CTL_MAXID: u32 = 55; pub const RNF_NORMAL: u32 = 1; pub const RNF_ROOT: u32 = 2; pub const RNF_ACTIVE: u32 = 4; pub const RTF_UP: u32 = 1; pub const RTF_GATEWAY: u32 = 2; pub const RTF_HOST: u32 = 4; pub const RTF_REJECT: u32 = 8; pub const RTF_DYNAMIC: u32 = 16; pub const RTF_MODIFIED: u32 = 32; pub const RTF_DONE: u32 = 64; pub const RTF_CLONING: u32 = 256; pub const RTF_MULTICAST: u32 = 512; pub const RTF_LLINFO: u32 = 1024; pub const RTF_STATIC: u32 = 2048; pub const RTF_BLACKHOLE: u32 = 4096; pub const RTF_PROTO3: u32 = 8192; pub const RTF_PROTO2: u32 = 16384; pub const RTF_ANNOUNCE: u32 = 16384; pub const RTF_PROTO1: u32 = 32768; pub const RTF_CLONED: u32 = 65536; pub const RTF_CACHED: u32 = 131072; pub const RTF_MPATH: u32 = 262144; pub const RTF_MPLS: u32 = 1048576; pub const RTF_LOCAL: u32 = 2097152; pub const RTF_BROADCAST: u32 = 4194304; pub const RTF_CONNECTED: u32 = 8388608; pub const RTF_BFD: u32 = 16777216; pub const RTF_FMASK: u32 = 17890312; pub const RTP_NONE: u32 = 0; pub const RTP_LOCAL: u32 = 1; pub const RTP_CONNECTED: u32 = 4; pub const RTP_STATIC: u32 = 8; pub const RTP_EIGRP: u32 = 28; pub const RTP_OSPF: u32 = 32; pub const RTP_ISIS: u32 = 36; pub const RTP_RIP: u32 = 40; pub const RTP_BGP: u32 = 48; pub const RTP_DEFAULT: u32 = 56; pub const RTP_PROPOSAL_STATIC: u32 = 57; pub const RTP_PROPOSAL_DHCLIENT: u32 = 58; pub const RTP_PROPOSAL_SLAAC: u32 = 59; pub const RTP_PROPOSAL_UMB: u32 = 60; pub const RTP_PROPOSAL_PPP: u32 = 61; pub const RTP_PROPOSAL_SOLICIT: u32 = 62; pub const RTP_MAX: u32 = 63; pub const RTP_ANY: u32 = 64; pub const RTP_MASK: u32 = 127; pub const RTP_DOWN: u32 = 128; pub const RTM_VERSION: u32 = 5; pub const RTM_MAXSIZE: u32 = 2048; pub const RTM_ADD: u32 = 1; pub const RTM_DELETE: u32 = 2; pub const RTM_CHANGE: u32 = 3; pub const RTM_GET: u32 = 4; pub const RTM_LOSING: u32 = 5; pub const RTM_REDIRECT: u32 = 6; pub const RTM_MISS: u32 = 7; pub const RTM_RESOLVE: u32 = 11; pub const RTM_NEWADDR: u32 = 12; pub const RTM_DELADDR: u32 = 13; pub const RTM_IFINFO: u32 = 14; pub const RTM_IFANNOUNCE: u32 = 15; pub const RTM_DESYNC: u32 = 16; pub const RTM_INVALIDATE: u32 = 17; pub const RTM_BFD: u32 = 18; pub const RTM_PROPOSAL: u32 = 19; pub const RTM_CHGADDRATTR: u32 = 20; pub const RTM_80211INFO: u32 = 21; pub const RTM_SOURCE: u32 = 22; pub const RTV_MTU: u32 = 1; pub const RTV_HOPCOUNT: u32 = 2; pub const RTV_EXPIRE: u32 = 4; pub const RTV_RPIPE: u32 = 8; pub const RTV_SPIPE: u32 = 16; pub const RTV_SSTHRESH: u32 = 32; pub const RTV_RTT: u32 = 64; pub const RTV_RTTVAR: u32 = 128; pub const RTA_DST: u32 = 1; pub const RTA_GATEWAY: u32 = 2; pub const RTA_NETMASK: u32 = 4; pub const RTA_GENMASK: u32 = 8; pub const RTA_IFP: u32 = 16; pub const RTA_IFA: u32 = 32; pub const RTA_AUTHOR: u32 = 64; pub const RTA_BRD: u32 = 128; pub const RTA_SRC: u32 = 256; pub const RTA_SRCMASK: u32 = 512; pub const RTA_LABEL: u32 = 1024; pub const RTA_BFD: u32 = 2048; pub const RTA_DNS: u32 = 4096; pub const RTA_STATIC: u32 = 8192; pub const RTA_SEARCH: u32 = 16384; pub const RTAX_DST: u32 = 0; pub const RTAX_GATEWAY: u32 = 1; pub const RTAX_NETMASK: u32 = 2; pub const RTAX_GENMASK: u32 = 3; pub const RTAX_IFP: u32 = 4; pub const RTAX_IFA: u32 = 5; pub const RTAX_AUTHOR: u32 = 6; pub const RTAX_BRD: u32 = 7; pub const RTAX_SRC: u32 = 8; pub const RTAX_SRCMASK: u32 = 9; pub const RTAX_LABEL: u32 = 10; pub const RTAX_BFD: u32 = 11; pub const RTAX_DNS: u32 = 12; pub const RTAX_STATIC: u32 = 13; pub const RTAX_SEARCH: u32 = 14; pub const RTAX_MAX: u32 = 15; pub const ROUTE_MSGFILTER: u32 = 1; pub const ROUTE_TABLEFILTER: u32 = 2; pub const ROUTE_PRIOFILTER: u32 = 3; pub const ROUTE_FLAGFILTER: u32 = 4; pub const RTABLE_ANY: u32 = 4294967295; pub const RTLABEL_LEN: u32 = 32; pub const RTDNS_LEN: u32 = 128; pub const RTSTATIC_LEN: u32 = 128; pub const RTSEARCH_LEN: u32 = 128; pub const PF_MD5_DIGEST_LENGTH: u32 = 16; pub const PFTM_TCP_FIRST_PACKET_VAL: u32 = 120; pub const PFTM_TCP_OPENING_VAL: u32 = 30; pub const PFTM_TCP_ESTABLISHED_VAL: u32 = 86400; pub const PFTM_TCP_CLOSING_VAL: u32 = 900; pub const PFTM_TCP_FIN_WAIT_VAL: u32 = 45; pub const PFTM_TCP_CLOSED_VAL: u32 = 90; pub const PFTM_UDP_FIRST_PACKET_VAL: u32 = 60; pub const PFTM_UDP_SINGLE_VAL: u32 = 30; pub const PFTM_UDP_MULTIPLE_VAL: u32 = 60; pub const PFTM_ICMP_FIRST_PACKET_VAL: u32 = 20; pub const PFTM_ICMP_ERROR_REPLY_VAL: u32 = 10; pub const PFTM_OTHER_FIRST_PACKET_VAL: u32 = 60; pub const PFTM_OTHER_SINGLE_VAL: u32 = 30; pub const PFTM_OTHER_MULTIPLE_VAL: u32 = 60; pub const PFTM_FRAG_VAL: u32 = 60; pub const PFTM_INTERVAL_VAL: u32 = 10; pub const PFTM_SRC_NODE_VAL: u32 = 0; pub const PFTM_TS_DIFF_VAL: u32 = 30; pub const PF_FRAG_STALE: u32 = 200; pub const PF_FRAG_ENTRY_POINTS: u32 = 16; pub const PF_FRAG_ENTRY_LIMIT: u32 = 64; pub const PF_POOL_IDMASK: u32 = 15; pub const PF_POOL_TYPEMASK: u32 = 15; pub const PF_POOL_STICKYADDR: u32 = 32; pub const PF_WSCALE_FLAG: u32 = 128; pub const PF_WSCALE_MASK: u32 = 15; pub const PF_LOG: u32 = 1; pub const PF_LOG_ALL: u32 = 2; pub const PF_LOG_USER: u32 = 4; pub const PF_LOG_FORCE: u32 = 8; pub const PF_LOG_MATCHES: u32 = 16; pub const PF_TABLE_NAME_SIZE: u32 = 32; pub const PFI_AFLAG_NETWORK: u32 = 1; pub const PFI_AFLAG_BROADCAST: u32 = 2; pub const PFI_AFLAG_PEER: u32 = 4; pub const PFI_AFLAG_MODEMASK: u32 = 7; pub const PFI_AFLAG_NOALIAS: u32 = 8; pub const PF_DEBUGNAME: &[u8; 5] = b"pf: \0"; pub const PF_THRESHOLD_MULT: u32 = 1000; pub const PF_THRESHOLD_MAX: u32 = 4294967; pub const PF_OSFP_EXPANDED: u32 = 1; pub const PF_OSFP_GENERIC: u32 = 2; pub const PF_OSFP_NODETAIL: u32 = 4; pub const PF_OSFP_LEN: u32 = 32; pub const _FP_RESERVED_BIT: u32 = 1; pub const _FP_UNUSED_BITS: u32 = 1; pub const _FP_CLASS_BITS: u32 = 10; pub const _FP_VERSION_BITS: u32 = 10; pub const _FP_SUBTYPE_BITS: u32 = 10; pub const PF_OSFP_WSIZE_MOD: u32 = 1; pub const PF_OSFP_WSIZE_DC: u32 = 2; pub const PF_OSFP_WSIZE_MSS: u32 = 4; pub const PF_OSFP_WSIZE_MTU: u32 = 8; pub const PF_OSFP_PSIZE_MOD: u32 = 16; pub const PF_OSFP_PSIZE_DC: u32 = 32; pub const PF_OSFP_WSCALE: u32 = 64; pub const PF_OSFP_WSCALE_MOD: u32 = 128; pub const PF_OSFP_WSCALE_DC: u32 = 256; pub const PF_OSFP_MSS: u32 = 512; pub const PF_OSFP_MSS_MOD: u32 = 1024; pub const PF_OSFP_MSS_DC: u32 = 2048; pub const PF_OSFP_DF: u32 = 4096; pub const PF_OSFP_TS0: u32 = 8192; pub const PF_OSFP_INET6: u32 = 16384; pub const PF_OSFP_MAXTTL_OFFSET: u32 = 40; pub const PF_OSFP_TCPOPT_NOP: u32 = 0; pub const PF_OSFP_TCPOPT_WSCALE: u32 = 1; pub const PF_OSFP_TCPOPT_MSS: u32 = 2; pub const PF_OSFP_TCPOPT_SACK: u32 = 3; pub const PF_OSFP_TCPOPT_TS: u32 = 4; pub const PF_OSFP_TCPOPT_BITS: u32 = 3; pub const PF_ANCHOR_STACK_MAX: u32 = 64; pub const PF_ANCHOR_NAME_SIZE: u32 = 64; pub const PF_ANCHOR_MAXPATH: u32 = 959; pub const PF_ANCHOR_HIWAT: u32 = 512; pub const PF_OPTIMIZER_TABLE_PFX: &[u8; 13] = b"__automatic_\0"; pub const PF_SKIP_IFP: u32 = 0; pub const PF_SKIP_DIR: u32 = 1; pub const PF_SKIP_RDOM: u32 = 2; pub const PF_SKIP_AF: u32 = 3; pub const PF_SKIP_PROTO: u32 = 4; pub const PF_SKIP_SRC_ADDR: u32 = 5; pub const PF_SKIP_DST_ADDR: u32 = 6; pub const PF_SKIP_SRC_PORT: u32 = 7; pub const PF_SKIP_DST_PORT: u32 = 8; pub const PF_SKIP_COUNT: u32 = 9; pub const PF_RULE_LABEL_SIZE: u32 = 64; pub const PF_QNAME_SIZE: u32 = 64; pub const PF_TAG_NAME_SIZE: u32 = 64; pub const PF_STATE_NORMAL: u32 = 1; pub const PF_STATE_MODULATE: u32 = 2; pub const PF_STATE_SYNPROXY: u32 = 3; pub const PF_FLUSH: u32 = 1; pub const PF_FLUSH_GLOBAL: u32 = 2; pub const PFRULE_DROP: u32 = 0; pub const PFRULE_RETURNRST: u32 = 1; pub const PFRULE_FRAGMENT: u32 = 2; pub const PFRULE_RETURNICMP: u32 = 4; pub const PFRULE_RETURN: u32 = 8; pub const PFRULE_NOSYNC: u32 = 16; pub const PFRULE_SRCTRACK: u32 = 32; pub const PFRULE_RULESRCTRACK: u32 = 64; pub const PFRULE_SETDELAY: u32 = 128; pub const PFRULE_IFBOUND: u32 = 65536; pub const PFRULE_STATESLOPPY: u32 = 131072; pub const PFRULE_PFLOW: u32 = 262144; pub const PFRULE_ONCE: u32 = 1048576; pub const PFRULE_AFTO: u32 = 2097152; pub const PFRULE_EXPIRED: u32 = 4194304; pub const PFSTATE_HIWAT: u32 = 100000; pub const PFSTATE_ADAPT_START: u32 = 60000; pub const PFSTATE_ADAPT_END: u32 = 120000; pub const PF_PKTDELAY_MAXPKTS: u32 = 10000; pub const PFSNODE_HIWAT: u32 = 10000; pub const PFSS_TIMESTAMP: u32 = 1; pub const PFSS_PAWS: u32 = 16; pub const PFSS_PAWS_IDLED: u32 = 32; pub const PFSS_DATA_TS: u32 = 64; pub const PFSS_DATA_NOTS: u32 = 128; pub const PFSTATE_ALLOWOPTS: u32 = 1; pub const PFSTATE_SLOPPY: u32 = 2; pub const PFSTATE_PFLOW: u32 = 4; pub const PFSTATE_NOSYNC: u32 = 8; pub const PFSTATE_ACK: u32 = 16; pub const PFSTATE_NODF: u32 = 32; pub const PFSTATE_SETTOS: u32 = 64; pub const PFSTATE_RANDOMID: u32 = 128; pub const PFSTATE_SCRUB_TCP: u32 = 256; pub const PFSTATE_SETPRIO: u32 = 512; pub const PFSTATE_INP_UNLINKED: u32 = 1024; pub const PFSTATE_SCRUBMASK: u32 = 416; pub const PFSTATE_SETMASK: u32 = 576; pub const PFSYNC_SCRUB_FLAG_VALID: u32 = 1; pub const PFSYNC_FLAG_SRCNODE: u32 = 4; pub const PFSYNC_FLAG_NATSRCNODE: u32 = 8; pub const PF_RESERVED_ANCHOR: &[u8; 4] = b"_pf\0"; pub const PFR_TFLAG_PERSIST: u32 = 1; pub const PFR_TFLAG_CONST: u32 = 2; pub const PFR_TFLAG_ACTIVE: u32 = 4; pub const PFR_TFLAG_INACTIVE: u32 = 8; pub const PFR_TFLAG_REFERENCED: u32 = 16; pub const PFR_TFLAG_REFDANCHOR: u32 = 32; pub const PFR_TFLAG_COUNTERS: u32 = 64; pub const PFR_TFLAG_USRMASK: u32 = 67; pub const PFR_TFLAG_SETMASK: u32 = 60; pub const PFR_TFLAG_ALLMASK: u32 = 127; pub const PFRKE_FLAG_NOT: u32 = 1; pub const PFRKE_FLAG_MARK: u32 = 2; pub const PFI_IFLAG_SKIP: u32 = 256; pub const PFI_IFLAG_ANY: u32 = 512; pub const PF_DPORT_RANGE: u32 = 1; pub const PF_RPORT_RANGE: u32 = 2; pub const PFRES_MATCH: u32 = 0; pub const PFRES_BADOFF: u32 = 1; pub const PFRES_FRAG: u32 = 2; pub const PFRES_SHORT: u32 = 3; pub const PFRES_NORM: u32 = 4; pub const PFRES_MEMORY: u32 = 5; pub const PFRES_TS: u32 = 6; pub const PFRES_CONGEST: u32 = 7; pub const PFRES_IPOPTIONS: u32 = 8; pub const PFRES_PROTCKSUM: u32 = 9; pub const PFRES_BADSTATE: u32 = 10; pub const PFRES_STATEINS: u32 = 11; pub const PFRES_MAXSTATES: u32 = 12; pub const PFRES_SRCLIMIT: u32 = 13; pub const PFRES_SYNPROXY: u32 = 14; pub const PFRES_TRANSLATE: u32 = 15; pub const PFRES_NOROUTE: u32 = 16; pub const PFRES_MAX: u32 = 17; pub const LCNT_STATES: u32 = 0; pub const LCNT_SRCSTATES: u32 = 1; pub const LCNT_SRCNODES: u32 = 2; pub const LCNT_SRCCONN: u32 = 3; pub const LCNT_SRCCONNRATE: u32 = 4; pub const LCNT_OVERLOAD_TABLE: u32 = 5; pub const LCNT_OVERLOAD_FLUSH: u32 = 6; pub const LCNT_SYNFLOODS: u32 = 7; pub const LCNT_SYNCOOKIES_SENT: u32 = 8; pub const LCNT_SYNCOOKIES_VALID: u32 = 9; pub const LCNT_MAX: u32 = 10; pub const PFUDPS_NO_TRAFFIC: u32 = 0; pub const PFUDPS_SINGLE: u32 = 1; pub const PFUDPS_MULTIPLE: u32 = 2; pub const PFUDPS_NSTATES: u32 = 3; pub const PFOTHERS_NO_TRAFFIC: u32 = 0; pub const PFOTHERS_SINGLE: u32 = 1; pub const PFOTHERS_MULTIPLE: u32 = 2; pub const PFOTHERS_NSTATES: u32 = 3; pub const FCNT_STATE_SEARCH: u32 = 0; pub const FCNT_STATE_INSERT: u32 = 1; pub const FCNT_STATE_REMOVALS: u32 = 2; pub const FCNT_MAX: u32 = 3; pub const SCNT_SRC_NODE_SEARCH: u32 = 0; pub const SCNT_SRC_NODE_INSERT: u32 = 1; pub const SCNT_SRC_NODE_REMOVALS: u32 = 2; pub const SCNT_MAX: u32 = 3; pub const PF_REASS_ENABLED: u32 = 1; pub const PF_REASS_NODF: u32 = 2; pub const PF_SYNCOOKIES_NEVER: u32 = 0; pub const PF_SYNCOOKIES_ALWAYS: u32 = 1; pub const PF_SYNCOOKIES_ADAPTIVE: u32 = 2; pub const PF_SYNCOOKIES_MODE_MAX: u32 = 2; pub const PF_SYNCOOKIES_HIWATPCT: u32 = 25; pub const PF_SYNCOOKIES_LOWATPCT: u32 = 12; pub const PF_PRIO_ZERO: u32 = 255; pub const PFQS_FLOWQUEUE: u32 = 1; pub const PFQS_ROOTCLASS: u32 = 2; pub const PFQS_DEFAULT: u32 = 4096; pub const PFR_KTABLE_HIWAT: u32 = 1000; pub const PFR_KENTRY_HIWAT: u32 = 200000; pub const PFR_KENTRY_HIWAT_SMALL: u32 = 100000; pub const PFR_FLAG_DUMMY: u32 = 2; pub const PFR_FLAG_FEEDBACK: u32 = 4; pub const PFR_FLAG_CLSTATS: u32 = 8; pub const PFR_FLAG_ADDRSTOO: u32 = 16; pub const PFR_FLAG_REPLACE: u32 = 32; pub const PFR_FLAG_ALLRSETS: u32 = 64; pub const PFR_FLAG_ALLMASK: u32 = 127; pub type __int8_t = ::std::os::raw::c_schar; pub type __uint8_t = ::std::os::raw::c_uchar; pub type __int16_t = ::std::os::raw::c_short; pub type __uint16_t = ::std::os::raw::c_ushort; pub type __int32_t = ::std::os::raw::c_int; pub type __uint32_t = ::std::os::raw::c_uint; pub type __int64_t = ::std::os::raw::c_longlong; pub type __uint64_t = ::std::os::raw::c_ulonglong; pub type __int_least8_t = __int8_t; pub type __uint_least8_t = __uint8_t; pub type __int_least16_t = __int16_t; pub type __uint_least16_t = __uint16_t; pub type __int_least32_t = __int32_t; pub type __uint_least32_t = __uint32_t; pub type __int_least64_t = __int64_t; pub type __uint_least64_t = __uint64_t; pub type __int_fast8_t = __int32_t; pub type __uint_fast8_t = __uint32_t; pub type __int_fast16_t = __int32_t; pub type __uint_fast16_t = __uint32_t; pub type __int_fast32_t = __int32_t; pub type __uint_fast32_t = __uint32_t; pub type __int_fast64_t = __int64_t; pub type __uint_fast64_t = __uint64_t; pub type __intptr_t = ::std::os::raw::c_long; pub type __uintptr_t = ::std::os::raw::c_ulong; pub type __intmax_t = __int64_t; pub type __uintmax_t = __uint64_t; pub type __register_t = ::std::os::raw::c_long; pub type __vaddr_t = ::std::os::raw::c_ulong; pub type __paddr_t = ::std::os::raw::c_ulong; pub type __vsize_t = ::std::os::raw::c_ulong; pub type __psize_t = ::std::os::raw::c_ulong; pub type __double_t = f64; pub type __float_t = f32; pub type __ptrdiff_t = ::std::os::raw::c_long; pub type __size_t = ::std::os::raw::c_ulong; pub type __ssize_t = ::std::os::raw::c_long; pub type __va_list = __builtin_va_list; pub type __wchar_t = ::std::os::raw::c_int; pub type __wint_t = ::std::os::raw::c_int; pub type __rune_t = ::std::os::raw::c_int; pub type __wctrans_t = *mut ::std::os::raw::c_void; pub type __wctype_t = *mut ::std::os::raw::c_void; pub type int_least8_t = __int_least8_t; pub type uint_least8_t = __uint_least8_t; pub type int_least16_t = __int_least16_t; pub type uint_least16_t = __uint_least16_t; pub type int_least32_t = __int_least32_t; pub type uint_least32_t = __uint_least32_t; pub type int_least64_t = __int_least64_t; pub type uint_least64_t = __uint_least64_t; pub type int_fast8_t = __int_fast8_t; pub type uint_fast8_t = __uint_fast8_t; pub type int_fast16_t = __int_fast16_t; pub type uint_fast16_t = __uint_fast16_t; pub type int_fast32_t = __int_fast32_t; pub type uint_fast32_t = __uint_fast32_t; pub type int_fast64_t = __int_fast64_t; pub type uint_fast64_t = __uint_fast64_t; pub type intmax_t = __intmax_t; pub type uintmax_t = __uintmax_t; pub type __blkcnt_t = __int64_t; pub type __blksize_t = __int32_t; pub type __clock_t = __int64_t; pub type __clockid_t = __int32_t; pub type __cpuid_t = ::std::os::raw::c_ulong; pub type __dev_t = __int32_t; pub type __fixpt_t = __uint32_t; pub type __fsblkcnt_t = __uint64_t; pub type __fsfilcnt_t = __uint64_t; pub type __gid_t = __uint32_t; pub type __id_t = __uint32_t; pub type __in_addr_t = __uint32_t; pub type __in_port_t = __uint16_t; pub type __ino_t = __uint64_t; pub type __key_t = ::std::os::raw::c_long; pub type __mode_t = __uint32_t; pub type __nlink_t = __uint32_t; pub type __off_t = __int64_t; pub type __pid_t = __int32_t; pub type __rlim_t = __uint64_t; pub type __sa_family_t = __uint8_t; pub type __segsz_t = __int32_t; pub type __socklen_t = __uint32_t; pub type __suseconds_t = ::std::os::raw::c_long; pub type __time_t = __int64_t; pub type __timer_t = __int32_t; pub type __uid_t = __uint32_t; pub type __useconds_t = __uint32_t; #[repr(C)] #[derive(Copy, Clone)] pub union __mbstate_t { pub __mbstate8: [::std::os::raw::c_char; 128usize], pub __mbstateL: __int64_t, } #[test] fn bindgen_test_layout___mbstate_t() { const UNINIT: ::std::mem::MaybeUninit<__mbstate_t> = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::<__mbstate_t>(), 128usize, concat!("Size of: ", stringify!(__mbstate_t)) ); assert_eq!( ::std::mem::align_of::<__mbstate_t>(), 8usize, concat!("Alignment of ", stringify!(__mbstate_t)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__mbstate8) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(__mbstate_t), "::", stringify!(__mbstate8) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__mbstateL) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(__mbstate_t), "::", stringify!(__mbstateL) ) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct iovec { pub iov_base: *mut ::std::os::raw::c_void, pub iov_len: usize, } #[test] fn bindgen_test_layout_iovec() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 16usize, concat!("Size of: ", stringify!(iovec)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(iovec)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).iov_base) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(iovec), "::", stringify!(iov_base)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).iov_len) as usize - ptr as usize }, 8usize, concat!("Offset of field: ", stringify!(iovec), "::", stringify!(iov_len)) ); } pub const uio_rw_UIO_READ: uio_rw = 0; pub const uio_rw_UIO_WRITE: uio_rw = 1; pub type uio_rw = ::std::os::raw::c_uint; pub const uio_seg_UIO_USERSPACE: uio_seg = 0; pub const uio_seg_UIO_SYSSPACE: uio_seg = 1; pub type uio_seg = ::std::os::raw::c_uint; unsafe extern "C" { pub fn preadv(arg1: ::std::os::raw::c_int, arg2: *const iovec, arg3: ::std::os::raw::c_int, arg4: __off_t) -> isize; } unsafe extern "C" { pub fn pwritev( arg1: ::std::os::raw::c_int, arg2: *const iovec, arg3: ::std::os::raw::c_int, arg4: __off_t, ) -> isize; } unsafe extern "C" { pub fn readv(arg1: ::std::os::raw::c_int, arg2: *const iovec, arg3: ::std::os::raw::c_int) -> isize; } unsafe extern "C" { pub fn writev(arg1: ::std::os::raw::c_int, arg2: *const iovec, arg3: ::std::os::raw::c_int) -> isize; } pub type u_char = ::std::os::raw::c_uchar; pub type u_short = ::std::os::raw::c_ushort; pub type u_int = ::std::os::raw::c_uint; pub type u_long = ::std::os::raw::c_ulong; pub type unchar = ::std::os::raw::c_uchar; pub type ushort = ::std::os::raw::c_ushort; pub type uint = ::std::os::raw::c_uint; pub type ulong = ::std::os::raw::c_ulong; pub type cpuid_t = __cpuid_t; pub type register_t = __register_t; pub type u_int8_t = __uint8_t; pub type u_int16_t = __uint16_t; pub type u_int32_t = __uint32_t; pub type u_int64_t = __uint64_t; pub type quad_t = __int64_t; pub type u_quad_t = __uint64_t; pub type vaddr_t = __vaddr_t; pub type paddr_t = __paddr_t; pub type vsize_t = __vsize_t; pub type psize_t = __psize_t; pub type blkcnt_t = __blkcnt_t; pub type blksize_t = __blksize_t; pub type caddr_t = *mut ::std::os::raw::c_char; pub type daddr32_t = __int32_t; pub type daddr_t = __int64_t; pub type dev_t = __dev_t; pub type fixpt_t = __fixpt_t; pub type gid_t = __gid_t; pub type id_t = __id_t; pub type ino_t = __ino_t; pub type key_t = __key_t; pub type mode_t = __mode_t; pub type nlink_t = __nlink_t; pub type rlim_t = __rlim_t; pub type segsz_t = __segsz_t; pub type uid_t = __uid_t; pub type useconds_t = __useconds_t; pub type suseconds_t = __suseconds_t; pub type fsblkcnt_t = __fsblkcnt_t; pub type fsfilcnt_t = __fsfilcnt_t; pub type clock_t = __clock_t; pub type clockid_t = __clockid_t; pub type pid_t = __pid_t; pub type time_t = __time_t; pub type timer_t = __timer_t; pub type off_t = __off_t; unsafe extern "C" { pub fn lseek(arg1: ::std::os::raw::c_int, arg2: off_t, arg3: ::std::os::raw::c_int) -> off_t; } unsafe extern "C" { pub fn ftruncate(arg1: ::std::os::raw::c_int, arg2: off_t) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn truncate(arg1: *const ::std::os::raw::c_char, arg2: off_t) -> ::std::os::raw::c_int; } pub type socklen_t = __socklen_t; pub type sa_family_t = __sa_family_t; #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct linger { pub l_onoff: ::std::os::raw::c_int, pub l_linger: ::std::os::raw::c_int, } #[test] fn bindgen_test_layout_linger() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 8usize, concat!("Size of: ", stringify!(linger)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(linger)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).l_onoff) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(linger), "::", stringify!(l_onoff)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).l_linger) as usize - ptr as usize }, 4usize, concat!("Offset of field: ", stringify!(linger), "::", stringify!(l_linger)) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct timeval { pub tv_sec: time_t, pub tv_usec: suseconds_t, } #[test] fn bindgen_test_layout_timeval() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 16usize, concat!("Size of: ", stringify!(timeval)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(timeval)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).tv_sec) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(timeval), "::", stringify!(tv_sec)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).tv_usec) as usize - ptr as usize }, 8usize, concat!("Offset of field: ", stringify!(timeval), "::", stringify!(tv_usec)) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct splice { pub sp_fd: ::std::os::raw::c_int, pub sp_max: off_t, pub sp_idle: timeval, } #[test] fn bindgen_test_layout_splice() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 32usize, concat!("Size of: ", stringify!(splice)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(splice)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).sp_fd) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(splice), "::", stringify!(sp_fd)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).sp_max) as usize - ptr as usize }, 8usize, concat!("Offset of field: ", stringify!(splice), "::", stringify!(sp_max)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).sp_idle) as usize - ptr as usize }, 16usize, concat!("Offset of field: ", stringify!(splice), "::", stringify!(sp_idle)) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct sockaddr { pub sa_len: __uint8_t, pub sa_family: sa_family_t, pub sa_data: [::std::os::raw::c_char; 14usize], } #[test] fn bindgen_test_layout_sockaddr() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 16usize, concat!("Size of: ", stringify!(sockaddr)) ); assert_eq!( ::std::mem::align_of::(), 1usize, concat!("Alignment of ", stringify!(sockaddr)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).sa_len) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(sockaddr), "::", stringify!(sa_len)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).sa_family) as usize - ptr as usize }, 1usize, concat!("Offset of field: ", stringify!(sockaddr), "::", stringify!(sa_family)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).sa_data) as usize - ptr as usize }, 2usize, concat!("Offset of field: ", stringify!(sockaddr), "::", stringify!(sa_data)) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct sockaddr_storage { pub ss_len: __uint8_t, pub ss_family: sa_family_t, pub __ss_pad1: [::std::os::raw::c_uchar; 6usize], pub __ss_pad2: __uint64_t, pub __ss_pad3: [::std::os::raw::c_uchar; 240usize], } #[test] fn bindgen_test_layout_sockaddr_storage() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 256usize, concat!("Size of: ", stringify!(sockaddr_storage)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(sockaddr_storage)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ss_len) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(sockaddr_storage), "::", stringify!(ss_len) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ss_family) as usize - ptr as usize }, 1usize, concat!( "Offset of field: ", stringify!(sockaddr_storage), "::", stringify!(ss_family) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__ss_pad1) as usize - ptr as usize }, 2usize, concat!( "Offset of field: ", stringify!(sockaddr_storage), "::", stringify!(__ss_pad1) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__ss_pad2) as usize - ptr as usize }, 8usize, concat!( "Offset of field: ", stringify!(sockaddr_storage), "::", stringify!(__ss_pad2) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__ss_pad3) as usize - ptr as usize }, 16usize, concat!( "Offset of field: ", stringify!(sockaddr_storage), "::", stringify!(__ss_pad3) ) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct sockpeercred { pub uid: uid_t, pub gid: gid_t, pub pid: pid_t, } #[test] fn bindgen_test_layout_sockpeercred() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 12usize, concat!("Size of: ", stringify!(sockpeercred)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(sockpeercred)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).uid) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(sockpeercred), "::", stringify!(uid)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).gid) as usize - ptr as usize }, 4usize, concat!("Offset of field: ", stringify!(sockpeercred), "::", stringify!(gid)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pid) as usize - ptr as usize }, 8usize, concat!("Offset of field: ", stringify!(sockpeercred), "::", stringify!(pid)) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct msghdr { pub msg_name: *mut ::std::os::raw::c_void, pub msg_namelen: socklen_t, pub msg_iov: *mut iovec, pub msg_iovlen: ::std::os::raw::c_uint, pub msg_control: *mut ::std::os::raw::c_void, pub msg_controllen: socklen_t, pub msg_flags: ::std::os::raw::c_int, } #[test] fn bindgen_test_layout_msghdr() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 48usize, concat!("Size of: ", stringify!(msghdr)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(msghdr)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).msg_name) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(msghdr), "::", stringify!(msg_name)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).msg_namelen) as usize - ptr as usize }, 8usize, concat!("Offset of field: ", stringify!(msghdr), "::", stringify!(msg_namelen)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).msg_iov) as usize - ptr as usize }, 16usize, concat!("Offset of field: ", stringify!(msghdr), "::", stringify!(msg_iov)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).msg_iovlen) as usize - ptr as usize }, 24usize, concat!("Offset of field: ", stringify!(msghdr), "::", stringify!(msg_iovlen)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).msg_control) as usize - ptr as usize }, 32usize, concat!("Offset of field: ", stringify!(msghdr), "::", stringify!(msg_control)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).msg_controllen) as usize - ptr as usize }, 40usize, concat!( "Offset of field: ", stringify!(msghdr), "::", stringify!(msg_controllen) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).msg_flags) as usize - ptr as usize }, 44usize, concat!("Offset of field: ", stringify!(msghdr), "::", stringify!(msg_flags)) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct mmsghdr { pub msg_hdr: msghdr, pub msg_len: ::std::os::raw::c_uint, } #[test] fn bindgen_test_layout_mmsghdr() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 56usize, concat!("Size of: ", stringify!(mmsghdr)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(mmsghdr)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).msg_hdr) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(mmsghdr), "::", stringify!(msg_hdr)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).msg_len) as usize - ptr as usize }, 48usize, concat!("Offset of field: ", stringify!(mmsghdr), "::", stringify!(msg_len)) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct cmsghdr { pub cmsg_len: socklen_t, pub cmsg_level: ::std::os::raw::c_int, pub cmsg_type: ::std::os::raw::c_int, } #[test] fn bindgen_test_layout_cmsghdr() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 12usize, concat!("Size of: ", stringify!(cmsghdr)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(cmsghdr)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).cmsg_len) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(cmsghdr), "::", stringify!(cmsg_len)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).cmsg_level) as usize - ptr as usize }, 4usize, concat!("Offset of field: ", stringify!(cmsghdr), "::", stringify!(cmsg_level)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).cmsg_type) as usize - ptr as usize }, 8usize, concat!("Offset of field: ", stringify!(cmsghdr), "::", stringify!(cmsg_type)) ); } unsafe extern "C" { pub fn accept(arg1: ::std::os::raw::c_int, arg2: *mut sockaddr, arg3: *mut socklen_t) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn bind(arg1: ::std::os::raw::c_int, arg2: *const sockaddr, arg3: socklen_t) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn connect(arg1: ::std::os::raw::c_int, arg2: *const sockaddr, arg3: socklen_t) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn getpeername(arg1: ::std::os::raw::c_int, arg2: *mut sockaddr, arg3: *mut socklen_t) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn getsockname(arg1: ::std::os::raw::c_int, arg2: *mut sockaddr, arg3: *mut socklen_t) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn getsockopt( arg1: ::std::os::raw::c_int, arg2: ::std::os::raw::c_int, arg3: ::std::os::raw::c_int, arg4: *mut ::std::os::raw::c_void, arg5: *mut socklen_t, ) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn listen(arg1: ::std::os::raw::c_int, arg2: ::std::os::raw::c_int) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn recv( arg1: ::std::os::raw::c_int, arg2: *mut ::std::os::raw::c_void, arg3: usize, arg4: ::std::os::raw::c_int, ) -> isize; } unsafe extern "C" { pub fn recvfrom( arg1: ::std::os::raw::c_int, arg2: *mut ::std::os::raw::c_void, arg3: usize, arg4: ::std::os::raw::c_int, arg5: *mut sockaddr, arg6: *mut socklen_t, ) -> isize; } unsafe extern "C" { pub fn recvmsg(arg1: ::std::os::raw::c_int, arg2: *mut msghdr, arg3: ::std::os::raw::c_int) -> isize; } unsafe extern "C" { pub fn recvmmsg( arg1: ::std::os::raw::c_int, arg2: *mut mmsghdr, arg3: ::std::os::raw::c_uint, arg4: ::std::os::raw::c_int, arg5: *mut timespec, ) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn send( arg1: ::std::os::raw::c_int, arg2: *const ::std::os::raw::c_void, arg3: usize, arg4: ::std::os::raw::c_int, ) -> isize; } unsafe extern "C" { pub fn sendto( arg1: ::std::os::raw::c_int, arg2: *const ::std::os::raw::c_void, arg3: usize, arg4: ::std::os::raw::c_int, arg5: *const sockaddr, arg6: socklen_t, ) -> isize; } unsafe extern "C" { pub fn sendmsg(arg1: ::std::os::raw::c_int, arg2: *const msghdr, arg3: ::std::os::raw::c_int) -> isize; } unsafe extern "C" { pub fn sendmmsg( arg1: ::std::os::raw::c_int, arg2: *mut mmsghdr, arg3: ::std::os::raw::c_uint, arg4: ::std::os::raw::c_int, ) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn setsockopt( arg1: ::std::os::raw::c_int, arg2: ::std::os::raw::c_int, arg3: ::std::os::raw::c_int, arg4: *const ::std::os::raw::c_void, arg5: socklen_t, ) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn shutdown(arg1: ::std::os::raw::c_int, arg2: ::std::os::raw::c_int) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn sockatmark(arg1: ::std::os::raw::c_int) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn socket( arg1: ::std::os::raw::c_int, arg2: ::std::os::raw::c_int, arg3: ::std::os::raw::c_int, ) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn socketpair( arg1: ::std::os::raw::c_int, arg2: ::std::os::raw::c_int, arg3: ::std::os::raw::c_int, arg4: *mut ::std::os::raw::c_int, ) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn accept4( arg1: ::std::os::raw::c_int, arg2: *mut sockaddr, arg3: *mut socklen_t, arg4: ::std::os::raw::c_int, ) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn getpeereid(arg1: ::std::os::raw::c_int, arg2: *mut uid_t, arg3: *mut gid_t) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn getrtable() -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn setrtable(arg1: ::std::os::raw::c_int) -> ::std::os::raw::c_int; } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct if_nameindex { pub if_index: ::std::os::raw::c_uint, pub if_name: *mut ::std::os::raw::c_char, } #[test] fn bindgen_test_layout_if_nameindex() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 16usize, concat!("Size of: ", stringify!(if_nameindex)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(if_nameindex)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).if_index) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(if_nameindex), "::", stringify!(if_index) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).if_name) as usize - ptr as usize }, 8usize, concat!("Offset of field: ", stringify!(if_nameindex), "::", stringify!(if_name)) ); } unsafe extern "C" { pub fn if_nametoindex(arg1: *const ::std::os::raw::c_char) -> ::std::os::raw::c_uint; } unsafe extern "C" { pub fn if_indextoname( arg1: ::std::os::raw::c_uint, arg2: *mut ::std::os::raw::c_char, ) -> *mut ::std::os::raw::c_char; } unsafe extern "C" { pub fn if_nameindex() -> *mut if_nameindex; } unsafe extern "C" { pub fn if_freenameindex(arg1: *mut if_nameindex); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct timespec { pub tv_sec: time_t, pub tv_nsec: ::std::os::raw::c_long, } #[test] fn bindgen_test_layout_timespec() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 16usize, concat!("Size of: ", stringify!(timespec)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(timespec)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).tv_sec) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(timespec), "::", stringify!(tv_sec)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).tv_nsec) as usize - ptr as usize }, 8usize, concat!("Offset of field: ", stringify!(timespec), "::", stringify!(tv_nsec)) ); } pub type __fd_mask = u32; #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct fd_set { pub fds_bits: [__fd_mask; 32usize], } #[test] fn bindgen_test_layout_fd_set() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 128usize, concat!("Size of: ", stringify!(fd_set)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(fd_set)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).fds_bits) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(fd_set), "::", stringify!(fds_bits)) ); } pub type sigset_t = ::std::os::raw::c_uint; unsafe extern "C" { pub fn select( arg1: ::std::os::raw::c_int, arg2: *mut fd_set, arg3: *mut fd_set, arg4: *mut fd_set, arg5: *mut timeval, ) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn pselect( arg1: ::std::os::raw::c_int, arg2: *mut fd_set, arg3: *mut fd_set, arg4: *mut fd_set, arg5: *const timespec, arg6: *const sigset_t, ) -> ::std::os::raw::c_int; } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct timezone { pub tz_minuteswest: ::std::os::raw::c_int, pub tz_dsttime: ::std::os::raw::c_int, } #[test] fn bindgen_test_layout_timezone() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 8usize, concat!("Size of: ", stringify!(timezone)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(timezone)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).tz_minuteswest) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(timezone), "::", stringify!(tz_minuteswest) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).tz_dsttime) as usize - ptr as usize }, 4usize, concat!("Offset of field: ", stringify!(timezone), "::", stringify!(tz_dsttime)) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct itimerval { pub it_interval: timeval, pub it_value: timeval, } #[test] fn bindgen_test_layout_itimerval() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 32usize, concat!("Size of: ", stringify!(itimerval)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(itimerval)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).it_interval) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(itimerval), "::", stringify!(it_interval) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).it_value) as usize - ptr as usize }, 16usize, concat!("Offset of field: ", stringify!(itimerval), "::", stringify!(it_value)) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct clockinfo { pub hz: ::std::os::raw::c_int, pub tick: ::std::os::raw::c_int, pub stathz: ::std::os::raw::c_int, pub profhz: ::std::os::raw::c_int, } #[test] fn bindgen_test_layout_clockinfo() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 16usize, concat!("Size of: ", stringify!(clockinfo)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(clockinfo)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).hz) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(clockinfo), "::", stringify!(hz)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).tick) as usize - ptr as usize }, 4usize, concat!("Offset of field: ", stringify!(clockinfo), "::", stringify!(tick)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).stathz) as usize - ptr as usize }, 8usize, concat!("Offset of field: ", stringify!(clockinfo), "::", stringify!(stathz)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).profhz) as usize - ptr as usize }, 12usize, concat!("Offset of field: ", stringify!(clockinfo), "::", stringify!(profhz)) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct itimerspec { pub it_interval: timespec, pub it_value: timespec, } #[test] fn bindgen_test_layout_itimerspec() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 32usize, concat!("Size of: ", stringify!(itimerspec)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(itimerspec)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).it_interval) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(itimerspec), "::", stringify!(it_interval) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).it_value) as usize - ptr as usize }, 16usize, concat!("Offset of field: ", stringify!(itimerspec), "::", stringify!(it_value)) ); } pub type locale_t = *mut ::std::os::raw::c_void; #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct tm { pub tm_sec: ::std::os::raw::c_int, pub tm_min: ::std::os::raw::c_int, pub tm_hour: ::std::os::raw::c_int, pub tm_mday: ::std::os::raw::c_int, pub tm_mon: ::std::os::raw::c_int, pub tm_year: ::std::os::raw::c_int, pub tm_wday: ::std::os::raw::c_int, pub tm_yday: ::std::os::raw::c_int, pub tm_isdst: ::std::os::raw::c_int, pub tm_gmtoff: ::std::os::raw::c_long, pub tm_zone: *mut ::std::os::raw::c_char, } #[test] fn bindgen_test_layout_tm() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 56usize, concat!("Size of: ", stringify!(tm)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(tm)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).tm_sec) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(tm), "::", stringify!(tm_sec)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).tm_min) as usize - ptr as usize }, 4usize, concat!("Offset of field: ", stringify!(tm), "::", stringify!(tm_min)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).tm_hour) as usize - ptr as usize }, 8usize, concat!("Offset of field: ", stringify!(tm), "::", stringify!(tm_hour)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).tm_mday) as usize - ptr as usize }, 12usize, concat!("Offset of field: ", stringify!(tm), "::", stringify!(tm_mday)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).tm_mon) as usize - ptr as usize }, 16usize, concat!("Offset of field: ", stringify!(tm), "::", stringify!(tm_mon)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).tm_year) as usize - ptr as usize }, 20usize, concat!("Offset of field: ", stringify!(tm), "::", stringify!(tm_year)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).tm_wday) as usize - ptr as usize }, 24usize, concat!("Offset of field: ", stringify!(tm), "::", stringify!(tm_wday)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).tm_yday) as usize - ptr as usize }, 28usize, concat!("Offset of field: ", stringify!(tm), "::", stringify!(tm_yday)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).tm_isdst) as usize - ptr as usize }, 32usize, concat!("Offset of field: ", stringify!(tm), "::", stringify!(tm_isdst)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).tm_gmtoff) as usize - ptr as usize }, 40usize, concat!("Offset of field: ", stringify!(tm), "::", stringify!(tm_gmtoff)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).tm_zone) as usize - ptr as usize }, 48usize, concat!("Offset of field: ", stringify!(tm), "::", stringify!(tm_zone)) ); } unsafe extern "C" { pub fn asctime(arg1: *const tm) -> *mut ::std::os::raw::c_char; } unsafe extern "C" { pub fn clock() -> clock_t; } unsafe extern "C" { pub fn ctime(arg1: *const time_t) -> *mut ::std::os::raw::c_char; } unsafe extern "C" { pub fn difftime(arg1: time_t, arg2: time_t) -> f64; } unsafe extern "C" { pub fn gmtime(arg1: *const time_t) -> *mut tm; } unsafe extern "C" { pub fn localtime(arg1: *const time_t) -> *mut tm; } unsafe extern "C" { pub fn mktime(arg1: *mut tm) -> time_t; } unsafe extern "C" { pub fn strftime( arg1: *mut ::std::os::raw::c_char, arg2: usize, arg3: *const ::std::os::raw::c_char, arg4: *const tm, ) -> usize; } unsafe extern "C" { pub fn time(arg1: *mut time_t) -> time_t; } unsafe extern "C" { pub static mut daylight: ::std::os::raw::c_int; } unsafe extern "C" { pub static mut timezone: ::std::os::raw::c_long; } unsafe extern "C" { pub fn strptime( arg1: *const ::std::os::raw::c_char, arg2: *const ::std::os::raw::c_char, arg3: *mut tm, ) -> *mut ::std::os::raw::c_char; } unsafe extern "C" { pub fn asctime_r(arg1: *const tm, arg2: *mut ::std::os::raw::c_char) -> *mut ::std::os::raw::c_char; } unsafe extern "C" { pub fn ctime_r(arg1: *const time_t, arg2: *mut ::std::os::raw::c_char) -> *mut ::std::os::raw::c_char; } unsafe extern "C" { pub fn gmtime_r(arg1: *const time_t, arg2: *mut tm) -> *mut tm; } unsafe extern "C" { pub fn localtime_r(arg1: *const time_t, arg2: *mut tm) -> *mut tm; } unsafe extern "C" { pub static mut tzname: [*mut ::std::os::raw::c_char; 2usize]; } unsafe extern "C" { pub fn tzset(); } unsafe extern "C" { pub fn clock_getres(arg1: clockid_t, arg2: *mut timespec) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn clock_gettime(arg1: clockid_t, arg2: *mut timespec) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn clock_settime(arg1: clockid_t, arg2: *const timespec) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn nanosleep(arg1: *const timespec, arg2: *mut timespec) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn clock_getcpuclockid(arg1: pid_t, arg2: *mut clockid_t) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn strftime_l( arg1: *mut ::std::os::raw::c_char, arg2: usize, arg3: *const ::std::os::raw::c_char, arg4: *const tm, arg5: locale_t, ) -> usize; } unsafe extern "C" { pub fn timespec_get(_ts: *mut timespec, _base: ::std::os::raw::c_int) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn tzsetwall(); } unsafe extern "C" { pub fn timelocal(arg1: *mut tm) -> time_t; } unsafe extern "C" { pub fn timegm(arg1: *mut tm) -> time_t; } unsafe extern "C" { pub fn timeoff(arg1: *mut tm, arg2: ::std::os::raw::c_long) -> time_t; } unsafe extern "C" { pub fn adjtime(arg1: *const timeval, arg2: *mut timeval) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn adjfreq(arg1: *const i64, arg2: *mut i64) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn futimes(arg1: ::std::os::raw::c_int, arg2: *const timeval) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn getitimer(arg1: ::std::os::raw::c_int, arg2: *mut itimerval) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn gettimeofday(arg1: *mut timeval, arg2: *mut timezone) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn setitimer( arg1: ::std::os::raw::c_int, arg2: *const itimerval, arg3: *mut itimerval, ) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn settimeofday(arg1: *const timeval, arg2: *const timezone) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn utimes(arg1: *const ::std::os::raw::c_char, arg2: *const timeval) -> ::std::os::raw::c_int; } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct if_clonereq { pub ifcr_total: ::std::os::raw::c_int, pub ifcr_count: ::std::os::raw::c_int, pub ifcr_buffer: *mut ::std::os::raw::c_char, } #[test] fn bindgen_test_layout_if_clonereq() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 16usize, concat!("Size of: ", stringify!(if_clonereq)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(if_clonereq)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifcr_total) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(if_clonereq), "::", stringify!(ifcr_total) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifcr_count) as usize - ptr as usize }, 4usize, concat!( "Offset of field: ", stringify!(if_clonereq), "::", stringify!(ifcr_count) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifcr_buffer) as usize - ptr as usize }, 8usize, concat!( "Offset of field: ", stringify!(if_clonereq), "::", stringify!(ifcr_buffer) ) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct if_rxring { pub rxr_adjusted: ::std::os::raw::c_int, pub rxr_alive: u_int, pub rxr_cwm: u_int, pub rxr_lwm: u_int, pub rxr_hwm: u_int, } #[test] fn bindgen_test_layout_if_rxring() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 20usize, concat!("Size of: ", stringify!(if_rxring)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(if_rxring)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rxr_adjusted) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(if_rxring), "::", stringify!(rxr_adjusted) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rxr_alive) as usize - ptr as usize }, 4usize, concat!("Offset of field: ", stringify!(if_rxring), "::", stringify!(rxr_alive)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rxr_cwm) as usize - ptr as usize }, 8usize, concat!("Offset of field: ", stringify!(if_rxring), "::", stringify!(rxr_cwm)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rxr_lwm) as usize - ptr as usize }, 12usize, concat!("Offset of field: ", stringify!(if_rxring), "::", stringify!(rxr_lwm)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rxr_hwm) as usize - ptr as usize }, 16usize, concat!("Offset of field: ", stringify!(if_rxring), "::", stringify!(rxr_hwm)) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct if_rxring_info { pub ifr_name: [::std::os::raw::c_char; 16usize], pub ifr_size: u_int, pub ifr_info: if_rxring, } #[test] fn bindgen_test_layout_if_rxring_info() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 40usize, concat!("Size of: ", stringify!(if_rxring_info)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(if_rxring_info)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifr_name) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(if_rxring_info), "::", stringify!(ifr_name) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifr_size) as usize - ptr as usize }, 16usize, concat!( "Offset of field: ", stringify!(if_rxring_info), "::", stringify!(ifr_size) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifr_info) as usize - ptr as usize }, 20usize, concat!( "Offset of field: ", stringify!(if_rxring_info), "::", stringify!(ifr_info) ) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct if_rxrinfo { pub ifri_total: u_int, pub ifri_entries: *mut if_rxring_info, } #[test] fn bindgen_test_layout_if_rxrinfo() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 16usize, concat!("Size of: ", stringify!(if_rxrinfo)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(if_rxrinfo)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifri_total) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(if_rxrinfo), "::", stringify!(ifri_total) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifri_entries) as usize - ptr as usize }, 8usize, concat!( "Offset of field: ", stringify!(if_rxrinfo), "::", stringify!(ifri_entries) ) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct if_data { pub ifi_type: u_char, pub ifi_addrlen: u_char, pub ifi_hdrlen: u_char, pub ifi_link_state: u_char, pub ifi_mtu: u_int32_t, pub ifi_metric: u_int32_t, pub ifi_rdomain: u_int32_t, pub ifi_baudrate: u_int64_t, pub ifi_ipackets: u_int64_t, pub ifi_ierrors: u_int64_t, pub ifi_opackets: u_int64_t, pub ifi_oerrors: u_int64_t, pub ifi_collisions: u_int64_t, pub ifi_ibytes: u_int64_t, pub ifi_obytes: u_int64_t, pub ifi_imcasts: u_int64_t, pub ifi_omcasts: u_int64_t, pub ifi_iqdrops: u_int64_t, pub ifi_oqdrops: u_int64_t, pub ifi_noproto: u_int64_t, pub ifi_capabilities: u_int32_t, pub ifi_lastchange: timeval, } #[test] fn bindgen_test_layout_if_data() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 144usize, concat!("Size of: ", stringify!(if_data)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(if_data)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifi_type) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(if_data), "::", stringify!(ifi_type)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifi_addrlen) as usize - ptr as usize }, 1usize, concat!("Offset of field: ", stringify!(if_data), "::", stringify!(ifi_addrlen)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifi_hdrlen) as usize - ptr as usize }, 2usize, concat!("Offset of field: ", stringify!(if_data), "::", stringify!(ifi_hdrlen)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifi_link_state) as usize - ptr as usize }, 3usize, concat!( "Offset of field: ", stringify!(if_data), "::", stringify!(ifi_link_state) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifi_mtu) as usize - ptr as usize }, 4usize, concat!("Offset of field: ", stringify!(if_data), "::", stringify!(ifi_mtu)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifi_metric) as usize - ptr as usize }, 8usize, concat!("Offset of field: ", stringify!(if_data), "::", stringify!(ifi_metric)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifi_rdomain) as usize - ptr as usize }, 12usize, concat!("Offset of field: ", stringify!(if_data), "::", stringify!(ifi_rdomain)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifi_baudrate) as usize - ptr as usize }, 16usize, concat!("Offset of field: ", stringify!(if_data), "::", stringify!(ifi_baudrate)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifi_ipackets) as usize - ptr as usize }, 24usize, concat!("Offset of field: ", stringify!(if_data), "::", stringify!(ifi_ipackets)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifi_ierrors) as usize - ptr as usize }, 32usize, concat!("Offset of field: ", stringify!(if_data), "::", stringify!(ifi_ierrors)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifi_opackets) as usize - ptr as usize }, 40usize, concat!("Offset of field: ", stringify!(if_data), "::", stringify!(ifi_opackets)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifi_oerrors) as usize - ptr as usize }, 48usize, concat!("Offset of field: ", stringify!(if_data), "::", stringify!(ifi_oerrors)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifi_collisions) as usize - ptr as usize }, 56usize, concat!( "Offset of field: ", stringify!(if_data), "::", stringify!(ifi_collisions) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifi_ibytes) as usize - ptr as usize }, 64usize, concat!("Offset of field: ", stringify!(if_data), "::", stringify!(ifi_ibytes)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifi_obytes) as usize - ptr as usize }, 72usize, concat!("Offset of field: ", stringify!(if_data), "::", stringify!(ifi_obytes)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifi_imcasts) as usize - ptr as usize }, 80usize, concat!("Offset of field: ", stringify!(if_data), "::", stringify!(ifi_imcasts)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifi_omcasts) as usize - ptr as usize }, 88usize, concat!("Offset of field: ", stringify!(if_data), "::", stringify!(ifi_omcasts)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifi_iqdrops) as usize - ptr as usize }, 96usize, concat!("Offset of field: ", stringify!(if_data), "::", stringify!(ifi_iqdrops)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifi_oqdrops) as usize - ptr as usize }, 104usize, concat!("Offset of field: ", stringify!(if_data), "::", stringify!(ifi_oqdrops)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifi_noproto) as usize - ptr as usize }, 112usize, concat!("Offset of field: ", stringify!(if_data), "::", stringify!(ifi_noproto)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifi_capabilities) as usize - ptr as usize }, 120usize, concat!( "Offset of field: ", stringify!(if_data), "::", stringify!(ifi_capabilities) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifi_lastchange) as usize - ptr as usize }, 128usize, concat!( "Offset of field: ", stringify!(if_data), "::", stringify!(ifi_lastchange) ) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct if_status_description { pub ifs_type: u_char, pub ifs_state: u_char, pub ifs_string: *const ::std::os::raw::c_char, } #[test] fn bindgen_test_layout_if_status_description() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 16usize, concat!("Size of: ", stringify!(if_status_description)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(if_status_description)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifs_type) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(if_status_description), "::", stringify!(ifs_type) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifs_state) as usize - ptr as usize }, 1usize, concat!( "Offset of field: ", stringify!(if_status_description), "::", stringify!(ifs_state) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifs_string) as usize - ptr as usize }, 8usize, concat!( "Offset of field: ", stringify!(if_status_description), "::", stringify!(ifs_string) ) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct if_msghdr { pub ifm_msglen: u_short, pub ifm_version: u_char, pub ifm_type: u_char, pub ifm_hdrlen: u_short, pub ifm_index: u_short, pub ifm_tableid: u_short, pub ifm_pad1: u_char, pub ifm_pad2: u_char, pub ifm_addrs: ::std::os::raw::c_int, pub ifm_flags: ::std::os::raw::c_int, pub ifm_xflags: ::std::os::raw::c_int, pub ifm_data: if_data, } #[test] fn bindgen_test_layout_if_msghdr() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 168usize, concat!("Size of: ", stringify!(if_msghdr)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(if_msghdr)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifm_msglen) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(if_msghdr), "::", stringify!(ifm_msglen)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifm_version) as usize - ptr as usize }, 2usize, concat!( "Offset of field: ", stringify!(if_msghdr), "::", stringify!(ifm_version) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifm_type) as usize - ptr as usize }, 3usize, concat!("Offset of field: ", stringify!(if_msghdr), "::", stringify!(ifm_type)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifm_hdrlen) as usize - ptr as usize }, 4usize, concat!("Offset of field: ", stringify!(if_msghdr), "::", stringify!(ifm_hdrlen)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifm_index) as usize - ptr as usize }, 6usize, concat!("Offset of field: ", stringify!(if_msghdr), "::", stringify!(ifm_index)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifm_tableid) as usize - ptr as usize }, 8usize, concat!( "Offset of field: ", stringify!(if_msghdr), "::", stringify!(ifm_tableid) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifm_pad1) as usize - ptr as usize }, 10usize, concat!("Offset of field: ", stringify!(if_msghdr), "::", stringify!(ifm_pad1)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifm_pad2) as usize - ptr as usize }, 11usize, concat!("Offset of field: ", stringify!(if_msghdr), "::", stringify!(ifm_pad2)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifm_addrs) as usize - ptr as usize }, 12usize, concat!("Offset of field: ", stringify!(if_msghdr), "::", stringify!(ifm_addrs)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifm_flags) as usize - ptr as usize }, 16usize, concat!("Offset of field: ", stringify!(if_msghdr), "::", stringify!(ifm_flags)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifm_xflags) as usize - ptr as usize }, 20usize, concat!("Offset of field: ", stringify!(if_msghdr), "::", stringify!(ifm_xflags)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifm_data) as usize - ptr as usize }, 24usize, concat!("Offset of field: ", stringify!(if_msghdr), "::", stringify!(ifm_data)) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct ifa_msghdr { pub ifam_msglen: u_short, pub ifam_version: u_char, pub ifam_type: u_char, pub ifam_hdrlen: u_short, pub ifam_index: u_short, pub ifam_tableid: u_short, pub ifam_pad1: u_char, pub ifam_pad2: u_char, pub ifam_addrs: ::std::os::raw::c_int, pub ifam_flags: ::std::os::raw::c_int, pub ifam_metric: ::std::os::raw::c_int, } #[test] fn bindgen_test_layout_ifa_msghdr() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 24usize, concat!("Size of: ", stringify!(ifa_msghdr)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(ifa_msghdr)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifam_msglen) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(ifa_msghdr), "::", stringify!(ifam_msglen) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifam_version) as usize - ptr as usize }, 2usize, concat!( "Offset of field: ", stringify!(ifa_msghdr), "::", stringify!(ifam_version) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifam_type) as usize - ptr as usize }, 3usize, concat!("Offset of field: ", stringify!(ifa_msghdr), "::", stringify!(ifam_type)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifam_hdrlen) as usize - ptr as usize }, 4usize, concat!( "Offset of field: ", stringify!(ifa_msghdr), "::", stringify!(ifam_hdrlen) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifam_index) as usize - ptr as usize }, 6usize, concat!( "Offset of field: ", stringify!(ifa_msghdr), "::", stringify!(ifam_index) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifam_tableid) as usize - ptr as usize }, 8usize, concat!( "Offset of field: ", stringify!(ifa_msghdr), "::", stringify!(ifam_tableid) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifam_pad1) as usize - ptr as usize }, 10usize, concat!("Offset of field: ", stringify!(ifa_msghdr), "::", stringify!(ifam_pad1)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifam_pad2) as usize - ptr as usize }, 11usize, concat!("Offset of field: ", stringify!(ifa_msghdr), "::", stringify!(ifam_pad2)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifam_addrs) as usize - ptr as usize }, 12usize, concat!( "Offset of field: ", stringify!(ifa_msghdr), "::", stringify!(ifam_addrs) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifam_flags) as usize - ptr as usize }, 16usize, concat!( "Offset of field: ", stringify!(ifa_msghdr), "::", stringify!(ifam_flags) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifam_metric) as usize - ptr as usize }, 20usize, concat!( "Offset of field: ", stringify!(ifa_msghdr), "::", stringify!(ifam_metric) ) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct if_announcemsghdr { pub ifan_msglen: u_short, pub ifan_version: u_char, pub ifan_type: u_char, pub ifan_hdrlen: u_short, pub ifan_index: u_short, pub ifan_what: u_short, pub ifan_name: [::std::os::raw::c_char; 16usize], } #[test] fn bindgen_test_layout_if_announcemsghdr() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 26usize, concat!("Size of: ", stringify!(if_announcemsghdr)) ); assert_eq!( ::std::mem::align_of::(), 2usize, concat!("Alignment of ", stringify!(if_announcemsghdr)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifan_msglen) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(if_announcemsghdr), "::", stringify!(ifan_msglen) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifan_version) as usize - ptr as usize }, 2usize, concat!( "Offset of field: ", stringify!(if_announcemsghdr), "::", stringify!(ifan_version) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifan_type) as usize - ptr as usize }, 3usize, concat!( "Offset of field: ", stringify!(if_announcemsghdr), "::", stringify!(ifan_type) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifan_hdrlen) as usize - ptr as usize }, 4usize, concat!( "Offset of field: ", stringify!(if_announcemsghdr), "::", stringify!(ifan_hdrlen) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifan_index) as usize - ptr as usize }, 6usize, concat!( "Offset of field: ", stringify!(if_announcemsghdr), "::", stringify!(ifan_index) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifan_what) as usize - ptr as usize }, 8usize, concat!( "Offset of field: ", stringify!(if_announcemsghdr), "::", stringify!(ifan_what) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifan_name) as usize - ptr as usize }, 10usize, concat!( "Offset of field: ", stringify!(if_announcemsghdr), "::", stringify!(ifan_name) ) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct if_ieee80211_data { pub ifie_channel: u8, pub ifie_nwid_len: u8, pub ifie_flags: u32, pub ifie_xflags: u32, pub ifie_nwid: [u8; 32usize], pub ifie_addr: [u8; 6usize], } #[test] fn bindgen_test_layout_if_ieee80211_data() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 52usize, concat!("Size of: ", stringify!(if_ieee80211_data)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(if_ieee80211_data)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifie_channel) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(if_ieee80211_data), "::", stringify!(ifie_channel) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifie_nwid_len) as usize - ptr as usize }, 1usize, concat!( "Offset of field: ", stringify!(if_ieee80211_data), "::", stringify!(ifie_nwid_len) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifie_flags) as usize - ptr as usize }, 4usize, concat!( "Offset of field: ", stringify!(if_ieee80211_data), "::", stringify!(ifie_flags) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifie_xflags) as usize - ptr as usize }, 8usize, concat!( "Offset of field: ", stringify!(if_ieee80211_data), "::", stringify!(ifie_xflags) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifie_nwid) as usize - ptr as usize }, 12usize, concat!( "Offset of field: ", stringify!(if_ieee80211_data), "::", stringify!(ifie_nwid) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifie_addr) as usize - ptr as usize }, 44usize, concat!( "Offset of field: ", stringify!(if_ieee80211_data), "::", stringify!(ifie_addr) ) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct if_ieee80211_msghdr { pub ifim_msglen: u16, pub ifim_version: u8, pub ifim_type: u8, pub ifim_hdrlen: u16, pub ifim_index: u16, pub ifim_tableid: u16, pub ifim_ifie: if_ieee80211_data, } #[test] fn bindgen_test_layout_if_ieee80211_msghdr() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 64usize, concat!("Size of: ", stringify!(if_ieee80211_msghdr)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(if_ieee80211_msghdr)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifim_msglen) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(if_ieee80211_msghdr), "::", stringify!(ifim_msglen) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifim_version) as usize - ptr as usize }, 2usize, concat!( "Offset of field: ", stringify!(if_ieee80211_msghdr), "::", stringify!(ifim_version) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifim_type) as usize - ptr as usize }, 3usize, concat!( "Offset of field: ", stringify!(if_ieee80211_msghdr), "::", stringify!(ifim_type) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifim_hdrlen) as usize - ptr as usize }, 4usize, concat!( "Offset of field: ", stringify!(if_ieee80211_msghdr), "::", stringify!(ifim_hdrlen) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifim_index) as usize - ptr as usize }, 6usize, concat!( "Offset of field: ", stringify!(if_ieee80211_msghdr), "::", stringify!(ifim_index) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifim_tableid) as usize - ptr as usize }, 8usize, concat!( "Offset of field: ", stringify!(if_ieee80211_msghdr), "::", stringify!(ifim_tableid) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifim_ifie) as usize - ptr as usize }, 12usize, concat!( "Offset of field: ", stringify!(if_ieee80211_msghdr), "::", stringify!(ifim_ifie) ) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct if_nameindex_msg { pub if_index: ::std::os::raw::c_uint, pub if_name: [::std::os::raw::c_char; 16usize], } #[test] fn bindgen_test_layout_if_nameindex_msg() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 20usize, concat!("Size of: ", stringify!(if_nameindex_msg)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(if_nameindex_msg)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).if_index) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(if_nameindex_msg), "::", stringify!(if_index) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).if_name) as usize - ptr as usize }, 4usize, concat!( "Offset of field: ", stringify!(if_nameindex_msg), "::", stringify!(if_name) ) ); } #[repr(C)] #[derive(Copy, Clone)] pub struct ifg_req { pub ifgrq_ifgrqu: ifg_req__bindgen_ty_1, } #[repr(C)] #[derive(Copy, Clone)] pub union ifg_req__bindgen_ty_1 { pub ifgrqu_group: [::std::os::raw::c_char; 16usize], pub ifgrqu_member: [::std::os::raw::c_char; 16usize], } #[test] fn bindgen_test_layout_ifg_req__bindgen_ty_1() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 16usize, concat!("Size of: ", stringify!(ifg_req__bindgen_ty_1)) ); assert_eq!( ::std::mem::align_of::(), 1usize, concat!("Alignment of ", stringify!(ifg_req__bindgen_ty_1)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifgrqu_group) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(ifg_req__bindgen_ty_1), "::", stringify!(ifgrqu_group) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifgrqu_member) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(ifg_req__bindgen_ty_1), "::", stringify!(ifgrqu_member) ) ); } #[test] fn bindgen_test_layout_ifg_req() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 16usize, concat!("Size of: ", stringify!(ifg_req)) ); assert_eq!( ::std::mem::align_of::(), 1usize, concat!("Alignment of ", stringify!(ifg_req)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifgrq_ifgrqu) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(ifg_req), "::", stringify!(ifgrq_ifgrqu)) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct ifg_attrib { pub ifg_carp_demoted: ::std::os::raw::c_int, } #[test] fn bindgen_test_layout_ifg_attrib() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 4usize, concat!("Size of: ", stringify!(ifg_attrib)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(ifg_attrib)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifg_carp_demoted) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(ifg_attrib), "::", stringify!(ifg_carp_demoted) ) ); } #[repr(C)] #[derive(Copy, Clone)] pub struct ifgroupreq { pub ifgr_name: [::std::os::raw::c_char; 16usize], pub ifgr_len: u_int, pub ifgr_ifgru: ifgroupreq__bindgen_ty_1, } #[repr(C)] #[derive(Copy, Clone)] pub union ifgroupreq__bindgen_ty_1 { pub ifgru_group: [::std::os::raw::c_char; 16usize], pub ifgru_groups: *mut ifg_req, pub ifgru_attrib: ifg_attrib, } #[test] fn bindgen_test_layout_ifgroupreq__bindgen_ty_1() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 16usize, concat!("Size of: ", stringify!(ifgroupreq__bindgen_ty_1)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(ifgroupreq__bindgen_ty_1)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifgru_group) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(ifgroupreq__bindgen_ty_1), "::", stringify!(ifgru_group) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifgru_groups) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(ifgroupreq__bindgen_ty_1), "::", stringify!(ifgru_groups) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifgru_attrib) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(ifgroupreq__bindgen_ty_1), "::", stringify!(ifgru_attrib) ) ); } #[test] fn bindgen_test_layout_ifgroupreq() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 40usize, concat!("Size of: ", stringify!(ifgroupreq)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(ifgroupreq)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifgr_name) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(ifgroupreq), "::", stringify!(ifgr_name)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifgr_len) as usize - ptr as usize }, 16usize, concat!("Offset of field: ", stringify!(ifgroupreq), "::", stringify!(ifgr_len)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifgr_ifgru) as usize - ptr as usize }, 24usize, concat!( "Offset of field: ", stringify!(ifgroupreq), "::", stringify!(ifgr_ifgru) ) ); } #[repr(C)] #[derive(Copy, Clone)] pub struct ifreq { pub ifr_name: [::std::os::raw::c_char; 16usize], pub ifr_ifru: ifreq__bindgen_ty_1, } #[repr(C)] #[derive(Copy, Clone)] pub union ifreq__bindgen_ty_1 { pub ifru_addr: sockaddr, pub ifru_dstaddr: sockaddr, pub ifru_broadaddr: sockaddr, pub ifru_flags: ::std::os::raw::c_short, pub ifru_metric: ::std::os::raw::c_int, pub ifru_vnetid: i64, pub ifru_media: u64, pub ifru_data: caddr_t, pub ifru_index: ::std::os::raw::c_uint, } #[test] fn bindgen_test_layout_ifreq__bindgen_ty_1() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 16usize, concat!("Size of: ", stringify!(ifreq__bindgen_ty_1)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(ifreq__bindgen_ty_1)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifru_addr) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(ifreq__bindgen_ty_1), "::", stringify!(ifru_addr) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifru_dstaddr) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(ifreq__bindgen_ty_1), "::", stringify!(ifru_dstaddr) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifru_broadaddr) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(ifreq__bindgen_ty_1), "::", stringify!(ifru_broadaddr) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifru_flags) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(ifreq__bindgen_ty_1), "::", stringify!(ifru_flags) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifru_metric) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(ifreq__bindgen_ty_1), "::", stringify!(ifru_metric) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifru_vnetid) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(ifreq__bindgen_ty_1), "::", stringify!(ifru_vnetid) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifru_media) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(ifreq__bindgen_ty_1), "::", stringify!(ifru_media) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifru_data) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(ifreq__bindgen_ty_1), "::", stringify!(ifru_data) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifru_index) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(ifreq__bindgen_ty_1), "::", stringify!(ifru_index) ) ); } #[test] fn bindgen_test_layout_ifreq() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 32usize, concat!("Size of: ", stringify!(ifreq)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(ifreq)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifr_name) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(ifreq), "::", stringify!(ifr_name)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifr_ifru) as usize - ptr as usize }, 16usize, concat!("Offset of field: ", stringify!(ifreq), "::", stringify!(ifr_ifru)) ); } #[repr(C)] #[derive(Copy, Clone)] pub struct ifaliasreq { pub ifra_name: [::std::os::raw::c_char; 16usize], pub ifra_ifrau: ifaliasreq__bindgen_ty_1, pub ifra_dstaddr: sockaddr, pub ifra_mask: sockaddr, } #[repr(C)] #[derive(Copy, Clone)] pub union ifaliasreq__bindgen_ty_1 { pub ifrau_addr: sockaddr, pub ifrau_align: ::std::os::raw::c_int, } #[test] fn bindgen_test_layout_ifaliasreq__bindgen_ty_1() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 16usize, concat!("Size of: ", stringify!(ifaliasreq__bindgen_ty_1)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(ifaliasreq__bindgen_ty_1)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifrau_addr) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(ifaliasreq__bindgen_ty_1), "::", stringify!(ifrau_addr) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifrau_align) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(ifaliasreq__bindgen_ty_1), "::", stringify!(ifrau_align) ) ); } #[test] fn bindgen_test_layout_ifaliasreq() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 64usize, concat!("Size of: ", stringify!(ifaliasreq)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(ifaliasreq)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifra_name) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(ifaliasreq), "::", stringify!(ifra_name)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifra_ifrau) as usize - ptr as usize }, 16usize, concat!( "Offset of field: ", stringify!(ifaliasreq), "::", stringify!(ifra_ifrau) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifra_dstaddr) as usize - ptr as usize }, 32usize, concat!( "Offset of field: ", stringify!(ifaliasreq), "::", stringify!(ifra_dstaddr) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifra_mask) as usize - ptr as usize }, 48usize, concat!("Offset of field: ", stringify!(ifaliasreq), "::", stringify!(ifra_mask)) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct ifmediareq { pub ifm_name: [::std::os::raw::c_char; 16usize], pub ifm_current: u64, pub ifm_mask: u64, pub ifm_status: u64, pub ifm_active: u64, pub ifm_count: ::std::os::raw::c_int, pub ifm_ulist: *mut u64, } #[test] fn bindgen_test_layout_ifmediareq() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 64usize, concat!("Size of: ", stringify!(ifmediareq)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(ifmediareq)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifm_name) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(ifmediareq), "::", stringify!(ifm_name)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifm_current) as usize - ptr as usize }, 16usize, concat!( "Offset of field: ", stringify!(ifmediareq), "::", stringify!(ifm_current) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifm_mask) as usize - ptr as usize }, 24usize, concat!("Offset of field: ", stringify!(ifmediareq), "::", stringify!(ifm_mask)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifm_status) as usize - ptr as usize }, 32usize, concat!( "Offset of field: ", stringify!(ifmediareq), "::", stringify!(ifm_status) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifm_active) as usize - ptr as usize }, 40usize, concat!( "Offset of field: ", stringify!(ifmediareq), "::", stringify!(ifm_active) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifm_count) as usize - ptr as usize }, 48usize, concat!("Offset of field: ", stringify!(ifmediareq), "::", stringify!(ifm_count)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifm_ulist) as usize - ptr as usize }, 56usize, concat!("Offset of field: ", stringify!(ifmediareq), "::", stringify!(ifm_ulist)) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct ifkalivereq { pub ikar_name: [::std::os::raw::c_char; 16usize], pub ikar_timeo: ::std::os::raw::c_int, pub ikar_cnt: ::std::os::raw::c_int, } #[test] fn bindgen_test_layout_ifkalivereq() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 24usize, concat!("Size of: ", stringify!(ifkalivereq)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(ifkalivereq)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ikar_name) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(ifkalivereq), "::", stringify!(ikar_name) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ikar_timeo) as usize - ptr as usize }, 16usize, concat!( "Offset of field: ", stringify!(ifkalivereq), "::", stringify!(ikar_timeo) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ikar_cnt) as usize - ptr as usize }, 20usize, concat!("Offset of field: ", stringify!(ifkalivereq), "::", stringify!(ikar_cnt)) ); } #[repr(C)] #[derive(Copy, Clone)] pub struct ifconf { pub ifc_len: ::std::os::raw::c_int, pub ifc_ifcu: ifconf__bindgen_ty_1, } #[repr(C)] #[derive(Copy, Clone)] pub union ifconf__bindgen_ty_1 { pub ifcu_buf: caddr_t, pub ifcu_req: *mut ifreq, } #[test] fn bindgen_test_layout_ifconf__bindgen_ty_1() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 8usize, concat!("Size of: ", stringify!(ifconf__bindgen_ty_1)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(ifconf__bindgen_ty_1)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifcu_buf) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(ifconf__bindgen_ty_1), "::", stringify!(ifcu_buf) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifcu_req) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(ifconf__bindgen_ty_1), "::", stringify!(ifcu_req) ) ); } #[test] fn bindgen_test_layout_ifconf() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 16usize, concat!("Size of: ", stringify!(ifconf)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(ifconf)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifc_len) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(ifconf), "::", stringify!(ifc_len)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifc_ifcu) as usize - ptr as usize }, 8usize, concat!("Offset of field: ", stringify!(ifconf), "::", stringify!(ifc_ifcu)) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct if_laddrreq { pub iflr_name: [::std::os::raw::c_char; 16usize], pub flags: ::std::os::raw::c_uint, pub prefixlen: ::std::os::raw::c_uint, pub addr: sockaddr_storage, pub dstaddr: sockaddr_storage, } #[test] fn bindgen_test_layout_if_laddrreq() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 536usize, concat!("Size of: ", stringify!(if_laddrreq)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(if_laddrreq)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).iflr_name) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(if_laddrreq), "::", stringify!(iflr_name) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).flags) as usize - ptr as usize }, 16usize, concat!("Offset of field: ", stringify!(if_laddrreq), "::", stringify!(flags)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).prefixlen) as usize - ptr as usize }, 20usize, concat!( "Offset of field: ", stringify!(if_laddrreq), "::", stringify!(prefixlen) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).addr) as usize - ptr as usize }, 24usize, concat!("Offset of field: ", stringify!(if_laddrreq), "::", stringify!(addr)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).dstaddr) as usize - ptr as usize }, 280usize, concat!("Offset of field: ", stringify!(if_laddrreq), "::", stringify!(dstaddr)) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct if_afreq { pub ifar_name: [::std::os::raw::c_char; 16usize], pub ifar_af: sa_family_t, } #[test] fn bindgen_test_layout_if_afreq() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 17usize, concat!("Size of: ", stringify!(if_afreq)) ); assert_eq!( ::std::mem::align_of::(), 1usize, concat!("Alignment of ", stringify!(if_afreq)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifar_name) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(if_afreq), "::", stringify!(ifar_name)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifar_af) as usize - ptr as usize }, 16usize, concat!("Offset of field: ", stringify!(if_afreq), "::", stringify!(ifar_af)) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct if_parent { pub ifp_name: [::std::os::raw::c_char; 16usize], pub ifp_parent: [::std::os::raw::c_char; 16usize], } #[test] fn bindgen_test_layout_if_parent() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 32usize, concat!("Size of: ", stringify!(if_parent)) ); assert_eq!( ::std::mem::align_of::(), 1usize, concat!("Alignment of ", stringify!(if_parent)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifp_name) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(if_parent), "::", stringify!(ifp_name)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifp_parent) as usize - ptr as usize }, 16usize, concat!("Offset of field: ", stringify!(if_parent), "::", stringify!(ifp_parent)) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct if_sffpage { pub sff_ifname: [::std::os::raw::c_char; 16usize], pub sff_addr: u8, pub sff_page: u8, pub sff_data: [u8; 256usize], } #[test] fn bindgen_test_layout_if_sffpage() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 274usize, concat!("Size of: ", stringify!(if_sffpage)) ); assert_eq!( ::std::mem::align_of::(), 1usize, concat!("Alignment of ", stringify!(if_sffpage)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).sff_ifname) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(if_sffpage), "::", stringify!(sff_ifname) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).sff_addr) as usize - ptr as usize }, 16usize, concat!("Offset of field: ", stringify!(if_sffpage), "::", stringify!(sff_addr)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).sff_page) as usize - ptr as usize }, 17usize, concat!("Offset of field: ", stringify!(if_sffpage), "::", stringify!(sff_page)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).sff_data) as usize - ptr as usize }, 18usize, concat!("Offset of field: ", stringify!(if_sffpage), "::", stringify!(sff_data)) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct arphdr { pub ar_hrd: u_int16_t, pub ar_pro: u_int16_t, pub ar_hln: u_int8_t, pub ar_pln: u_int8_t, pub ar_op: u_int16_t, } #[test] fn bindgen_test_layout_arphdr() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 8usize, concat!("Size of: ", stringify!(arphdr)) ); assert_eq!( ::std::mem::align_of::(), 2usize, concat!("Alignment of ", stringify!(arphdr)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ar_hrd) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(arphdr), "::", stringify!(ar_hrd)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ar_pro) as usize - ptr as usize }, 2usize, concat!("Offset of field: ", stringify!(arphdr), "::", stringify!(ar_pro)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ar_hln) as usize - ptr as usize }, 4usize, concat!("Offset of field: ", stringify!(arphdr), "::", stringify!(ar_hln)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ar_pln) as usize - ptr as usize }, 5usize, concat!("Offset of field: ", stringify!(arphdr), "::", stringify!(ar_pln)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ar_op) as usize - ptr as usize }, 6usize, concat!("Offset of field: ", stringify!(arphdr), "::", stringify!(ar_op)) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct arpreq { pub arp_pa: sockaddr, pub arp_ha: sockaddr, pub arp_flags: ::std::os::raw::c_int, } #[test] fn bindgen_test_layout_arpreq() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 36usize, concat!("Size of: ", stringify!(arpreq)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(arpreq)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).arp_pa) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(arpreq), "::", stringify!(arp_pa)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).arp_ha) as usize - ptr as usize }, 16usize, concat!("Offset of field: ", stringify!(arpreq), "::", stringify!(arp_ha)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).arp_flags) as usize - ptr as usize }, 32usize, concat!("Offset of field: ", stringify!(arpreq), "::", stringify!(arp_flags)) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct rb_type { pub t_compare: ::std::option::Option< unsafe extern "C" fn( arg1: *const ::std::os::raw::c_void, arg2: *const ::std::os::raw::c_void, ) -> ::std::os::raw::c_int, >, pub t_augment: ::std::option::Option, pub t_offset: ::std::os::raw::c_uint, } #[test] fn bindgen_test_layout_rb_type() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 24usize, concat!("Size of: ", stringify!(rb_type)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(rb_type)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).t_compare) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(rb_type), "::", stringify!(t_compare)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).t_augment) as usize - ptr as usize }, 8usize, concat!("Offset of field: ", stringify!(rb_type), "::", stringify!(t_augment)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).t_offset) as usize - ptr as usize }, 16usize, concat!("Offset of field: ", stringify!(rb_type), "::", stringify!(t_offset)) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct rb_tree { pub rbt_root: *mut rb_entry, } #[test] fn bindgen_test_layout_rb_tree() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 8usize, concat!("Size of: ", stringify!(rb_tree)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(rb_tree)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rbt_root) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(rb_tree), "::", stringify!(rbt_root)) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct rb_entry { pub rbt_parent: *mut rb_entry, pub rbt_left: *mut rb_entry, pub rbt_right: *mut rb_entry, pub rbt_color: ::std::os::raw::c_uint, } #[test] fn bindgen_test_layout_rb_entry() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 32usize, concat!("Size of: ", stringify!(rb_entry)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(rb_entry)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rbt_parent) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(rb_entry), "::", stringify!(rbt_parent)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rbt_left) as usize - ptr as usize }, 8usize, concat!("Offset of field: ", stringify!(rb_entry), "::", stringify!(rbt_left)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rbt_right) as usize - ptr as usize }, 16usize, concat!("Offset of field: ", stringify!(rb_entry), "::", stringify!(rbt_right)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rbt_color) as usize - ptr as usize }, 24usize, concat!("Offset of field: ", stringify!(rb_entry), "::", stringify!(rbt_color)) ); } unsafe extern "C" { pub fn _rb_insert( arg1: *const rb_type, arg2: *mut rb_tree, arg3: *mut ::std::os::raw::c_void, ) -> *mut ::std::os::raw::c_void; } unsafe extern "C" { pub fn _rb_remove( arg1: *const rb_type, arg2: *mut rb_tree, arg3: *mut ::std::os::raw::c_void, ) -> *mut ::std::os::raw::c_void; } unsafe extern "C" { pub fn _rb_find( arg1: *const rb_type, arg2: *mut rb_tree, arg3: *const ::std::os::raw::c_void, ) -> *mut ::std::os::raw::c_void; } unsafe extern "C" { pub fn _rb_nfind( arg1: *const rb_type, arg2: *mut rb_tree, arg3: *const ::std::os::raw::c_void, ) -> *mut ::std::os::raw::c_void; } unsafe extern "C" { pub fn _rb_root(arg1: *const rb_type, arg2: *mut rb_tree) -> *mut ::std::os::raw::c_void; } unsafe extern "C" { pub fn _rb_min(arg1: *const rb_type, arg2: *mut rb_tree) -> *mut ::std::os::raw::c_void; } unsafe extern "C" { pub fn _rb_max(arg1: *const rb_type, arg2: *mut rb_tree) -> *mut ::std::os::raw::c_void; } unsafe extern "C" { pub fn _rb_next(arg1: *const rb_type, arg2: *mut ::std::os::raw::c_void) -> *mut ::std::os::raw::c_void; } unsafe extern "C" { pub fn _rb_prev(arg1: *const rb_type, arg2: *mut ::std::os::raw::c_void) -> *mut ::std::os::raw::c_void; } unsafe extern "C" { pub fn _rb_left(arg1: *const rb_type, arg2: *mut ::std::os::raw::c_void) -> *mut ::std::os::raw::c_void; } unsafe extern "C" { pub fn _rb_right(arg1: *const rb_type, arg2: *mut ::std::os::raw::c_void) -> *mut ::std::os::raw::c_void; } unsafe extern "C" { pub fn _rb_parent(arg1: *const rb_type, arg2: *mut ::std::os::raw::c_void) -> *mut ::std::os::raw::c_void; } unsafe extern "C" { pub fn _rb_set_left(arg1: *const rb_type, arg2: *mut ::std::os::raw::c_void, arg3: *mut ::std::os::raw::c_void); } unsafe extern "C" { pub fn _rb_set_right(arg1: *const rb_type, arg2: *mut ::std::os::raw::c_void, arg3: *mut ::std::os::raw::c_void); } unsafe extern "C" { pub fn _rb_set_parent(arg1: *const rb_type, arg2: *mut ::std::os::raw::c_void, arg3: *mut ::std::os::raw::c_void); } unsafe extern "C" { pub fn _rb_poison(arg1: *const rb_type, arg2: *mut ::std::os::raw::c_void, arg3: ::std::os::raw::c_ulong); } unsafe extern "C" { pub fn _rb_check( arg1: *const rb_type, arg2: *mut ::std::os::raw::c_void, arg3: ::std::os::raw::c_ulong, ) -> ::std::os::raw::c_int; } pub const lock_class_index_LO_CLASS_KERNEL_LOCK: lock_class_index = 0; pub const lock_class_index_LO_CLASS_SCHED_LOCK: lock_class_index = 1; pub const lock_class_index_LO_CLASS_MUTEX: lock_class_index = 2; pub const lock_class_index_LO_CLASS_RWLOCK: lock_class_index = 3; pub const lock_class_index_LO_CLASS_RRWLOCK: lock_class_index = 4; pub type lock_class_index = ::std::os::raw::c_uint; #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct lock_object { pub lo_type: *const lock_type, pub lo_name: *const ::std::os::raw::c_char, pub lo_witness: *mut witness, pub lo_flags: ::std::os::raw::c_uint, } #[test] fn bindgen_test_layout_lock_object() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 32usize, concat!("Size of: ", stringify!(lock_object)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(lock_object)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).lo_type) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(lock_object), "::", stringify!(lo_type)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).lo_name) as usize - ptr as usize }, 8usize, concat!("Offset of field: ", stringify!(lock_object), "::", stringify!(lo_name)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).lo_witness) as usize - ptr as usize }, 16usize, concat!( "Offset of field: ", stringify!(lock_object), "::", stringify!(lo_witness) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).lo_flags) as usize - ptr as usize }, 24usize, concat!("Offset of field: ", stringify!(lock_object), "::", stringify!(lo_flags)) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct lock_type { pub lt_name: *const ::std::os::raw::c_char, } #[test] fn bindgen_test_layout_lock_type() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 8usize, concat!("Size of: ", stringify!(lock_type)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(lock_type)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).lt_name) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(lock_type), "::", stringify!(lt_name)) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct proc_ { _unused: [u8; 0], } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct rwlock { pub rwl_owner: ::std::os::raw::c_ulong, pub rwl_name: *const ::std::os::raw::c_char, } #[test] fn bindgen_test_layout_rwlock() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 16usize, concat!("Size of: ", stringify!(rwlock)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(rwlock)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rwl_owner) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(rwlock), "::", stringify!(rwl_owner)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rwl_name) as usize - ptr as usize }, 8usize, concat!("Offset of field: ", stringify!(rwlock), "::", stringify!(rwl_name)) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct rrwlock { pub rrwl_lock: rwlock, pub rrwl_wcnt: u32, } #[test] fn bindgen_test_layout_rrwlock() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 24usize, concat!("Size of: ", stringify!(rrwlock)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(rrwlock)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rrwl_lock) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(rrwlock), "::", stringify!(rrwl_lock)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rrwl_wcnt) as usize - ptr as usize }, 16usize, concat!("Offset of field: ", stringify!(rrwlock), "::", stringify!(rrwl_wcnt)) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct refcnt { pub r_refs: ::std::os::raw::c_uint, pub r_traceidx: ::std::os::raw::c_int, } #[test] fn bindgen_test_layout_refcnt() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 8usize, concat!("Size of: ", stringify!(refcnt)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(refcnt)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).r_refs) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(refcnt), "::", stringify!(r_refs)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).r_traceidx) as usize - ptr as usize }, 4usize, concat!("Offset of field: ", stringify!(refcnt), "::", stringify!(r_traceidx)) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct circq { pub next: *mut circq, pub prev: *mut circq, } #[test] fn bindgen_test_layout_circq() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 16usize, concat!("Size of: ", stringify!(circq)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(circq)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).next) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(circq), "::", stringify!(next)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).prev) as usize - ptr as usize }, 8usize, concat!("Offset of field: ", stringify!(circq), "::", stringify!(prev)) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct timeout { pub to_list: circq, pub to_abstime: timespec, pub to_func: ::std::option::Option, pub to_arg: *mut ::std::os::raw::c_void, pub to_process: *mut process, pub to_time: ::std::os::raw::c_int, pub to_flags: ::std::os::raw::c_int, pub to_kclock: ::std::os::raw::c_int, } #[test] fn bindgen_test_layout_timeout() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 72usize, concat!("Size of: ", stringify!(timeout)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(timeout)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).to_list) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(timeout), "::", stringify!(to_list)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).to_abstime) as usize - ptr as usize }, 16usize, concat!("Offset of field: ", stringify!(timeout), "::", stringify!(to_abstime)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).to_func) as usize - ptr as usize }, 32usize, concat!("Offset of field: ", stringify!(timeout), "::", stringify!(to_func)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).to_arg) as usize - ptr as usize }, 40usize, concat!("Offset of field: ", stringify!(timeout), "::", stringify!(to_arg)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).to_process) as usize - ptr as usize }, 48usize, concat!("Offset of field: ", stringify!(timeout), "::", stringify!(to_process)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).to_time) as usize - ptr as usize }, 56usize, concat!("Offset of field: ", stringify!(timeout), "::", stringify!(to_time)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).to_flags) as usize - ptr as usize }, 60usize, concat!("Offset of field: ", stringify!(timeout), "::", stringify!(to_flags)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).to_kclock) as usize - ptr as usize }, 64usize, concat!("Offset of field: ", stringify!(timeout), "::", stringify!(to_kclock)) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct timeoutstat { pub tos_added: u64, pub tos_cancelled: u64, pub tos_deleted: u64, pub tos_late: u64, pub tos_pending: u64, pub tos_readded: u64, pub tos_rescheduled: u64, pub tos_run_softclock: u64, pub tos_run_thread: u64, pub tos_scheduled: u64, pub tos_softclocks: u64, pub tos_thread_wakeups: u64, } #[test] fn bindgen_test_layout_timeoutstat() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 96usize, concat!("Size of: ", stringify!(timeoutstat)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(timeoutstat)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).tos_added) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(timeoutstat), "::", stringify!(tos_added) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).tos_cancelled) as usize - ptr as usize }, 8usize, concat!( "Offset of field: ", stringify!(timeoutstat), "::", stringify!(tos_cancelled) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).tos_deleted) as usize - ptr as usize }, 16usize, concat!( "Offset of field: ", stringify!(timeoutstat), "::", stringify!(tos_deleted) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).tos_late) as usize - ptr as usize }, 24usize, concat!("Offset of field: ", stringify!(timeoutstat), "::", stringify!(tos_late)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).tos_pending) as usize - ptr as usize }, 32usize, concat!( "Offset of field: ", stringify!(timeoutstat), "::", stringify!(tos_pending) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).tos_readded) as usize - ptr as usize }, 40usize, concat!( "Offset of field: ", stringify!(timeoutstat), "::", stringify!(tos_readded) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).tos_rescheduled) as usize - ptr as usize }, 48usize, concat!( "Offset of field: ", stringify!(timeoutstat), "::", stringify!(tos_rescheduled) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).tos_run_softclock) as usize - ptr as usize }, 56usize, concat!( "Offset of field: ", stringify!(timeoutstat), "::", stringify!(tos_run_softclock) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).tos_run_thread) as usize - ptr as usize }, 64usize, concat!( "Offset of field: ", stringify!(timeoutstat), "::", stringify!(tos_run_thread) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).tos_scheduled) as usize - ptr as usize }, 72usize, concat!( "Offset of field: ", stringify!(timeoutstat), "::", stringify!(tos_scheduled) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).tos_softclocks) as usize - ptr as usize }, 80usize, concat!( "Offset of field: ", stringify!(timeoutstat), "::", stringify!(tos_softclocks) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).tos_thread_wakeups) as usize - ptr as usize }, 88usize, concat!( "Offset of field: ", stringify!(timeoutstat), "::", stringify!(tos_thread_wakeups) ) ); } pub type in_addr_t = __in_addr_t; pub type in_port_t = __in_port_t; #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct in_addr { pub s_addr: in_addr_t, } #[test] fn bindgen_test_layout_in_addr() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 4usize, concat!("Size of: ", stringify!(in_addr)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(in_addr)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).s_addr) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(in_addr), "::", stringify!(s_addr)) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct sockaddr_in { pub sin_len: u_int8_t, pub sin_family: sa_family_t, pub sin_port: in_port_t, pub sin_addr: in_addr, pub sin_zero: [i8; 8usize], } #[test] fn bindgen_test_layout_sockaddr_in() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 16usize, concat!("Size of: ", stringify!(sockaddr_in)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(sockaddr_in)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).sin_len) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(sockaddr_in), "::", stringify!(sin_len)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).sin_family) as usize - ptr as usize }, 1usize, concat!( "Offset of field: ", stringify!(sockaddr_in), "::", stringify!(sin_family) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).sin_port) as usize - ptr as usize }, 2usize, concat!("Offset of field: ", stringify!(sockaddr_in), "::", stringify!(sin_port)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).sin_addr) as usize - ptr as usize }, 4usize, concat!("Offset of field: ", stringify!(sockaddr_in), "::", stringify!(sin_addr)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).sin_zero) as usize - ptr as usize }, 8usize, concat!("Offset of field: ", stringify!(sockaddr_in), "::", stringify!(sin_zero)) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct ip_opts { pub ip_dst: in_addr, pub ip_opts: [i8; 40usize], } #[test] fn bindgen_test_layout_ip_opts() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 44usize, concat!("Size of: ", stringify!(ip_opts)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(ip_opts)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ip_dst) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(ip_opts), "::", stringify!(ip_dst)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ip_opts) as usize - ptr as usize }, 4usize, concat!("Offset of field: ", stringify!(ip_opts), "::", stringify!(ip_opts)) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct ip_mreq { pub imr_multiaddr: in_addr, pub imr_interface: in_addr, } #[test] fn bindgen_test_layout_ip_mreq() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 8usize, concat!("Size of: ", stringify!(ip_mreq)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(ip_mreq)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).imr_multiaddr) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(ip_mreq), "::", stringify!(imr_multiaddr) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).imr_interface) as usize - ptr as usize }, 4usize, concat!( "Offset of field: ", stringify!(ip_mreq), "::", stringify!(imr_interface) ) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct ip_mreqn { pub imr_multiaddr: in_addr, pub imr_address: in_addr, pub imr_ifindex: ::std::os::raw::c_int, } #[test] fn bindgen_test_layout_ip_mreqn() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 12usize, concat!("Size of: ", stringify!(ip_mreqn)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(ip_mreqn)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).imr_multiaddr) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(ip_mreqn), "::", stringify!(imr_multiaddr) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).imr_address) as usize - ptr as usize }, 4usize, concat!("Offset of field: ", stringify!(ip_mreqn), "::", stringify!(imr_address)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).imr_ifindex) as usize - ptr as usize }, 8usize, concat!("Offset of field: ", stringify!(ip_mreqn), "::", stringify!(imr_ifindex)) ); } #[repr(C)] #[derive(Copy, Clone)] pub struct in6_addr { pub __u6_addr: in6_addr__bindgen_ty_1, } #[repr(C)] #[derive(Copy, Clone)] pub union in6_addr__bindgen_ty_1 { pub __u6_addr8: [u_int8_t; 16usize], pub __u6_addr16: [u_int16_t; 8usize], pub __u6_addr32: [u_int32_t; 4usize], } #[test] fn bindgen_test_layout_in6_addr__bindgen_ty_1() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 16usize, concat!("Size of: ", stringify!(in6_addr__bindgen_ty_1)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(in6_addr__bindgen_ty_1)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__u6_addr8) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(in6_addr__bindgen_ty_1), "::", stringify!(__u6_addr8) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__u6_addr16) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(in6_addr__bindgen_ty_1), "::", stringify!(__u6_addr16) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__u6_addr32) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(in6_addr__bindgen_ty_1), "::", stringify!(__u6_addr32) ) ); } #[test] fn bindgen_test_layout_in6_addr() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 16usize, concat!("Size of: ", stringify!(in6_addr)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(in6_addr)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).__u6_addr) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(in6_addr), "::", stringify!(__u6_addr)) ); } #[repr(C)] #[derive(Copy, Clone)] pub struct sockaddr_in6 { pub sin6_len: u_int8_t, pub sin6_family: sa_family_t, pub sin6_port: in_port_t, pub sin6_flowinfo: u_int32_t, pub sin6_addr: in6_addr, pub sin6_scope_id: u_int32_t, } #[test] fn bindgen_test_layout_sockaddr_in6() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 28usize, concat!("Size of: ", stringify!(sockaddr_in6)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(sockaddr_in6)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).sin6_len) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(sockaddr_in6), "::", stringify!(sin6_len) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).sin6_family) as usize - ptr as usize }, 1usize, concat!( "Offset of field: ", stringify!(sockaddr_in6), "::", stringify!(sin6_family) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).sin6_port) as usize - ptr as usize }, 2usize, concat!( "Offset of field: ", stringify!(sockaddr_in6), "::", stringify!(sin6_port) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).sin6_flowinfo) as usize - ptr as usize }, 4usize, concat!( "Offset of field: ", stringify!(sockaddr_in6), "::", stringify!(sin6_flowinfo) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).sin6_addr) as usize - ptr as usize }, 8usize, concat!( "Offset of field: ", stringify!(sockaddr_in6), "::", stringify!(sin6_addr) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).sin6_scope_id) as usize - ptr as usize }, 24usize, concat!( "Offset of field: ", stringify!(sockaddr_in6), "::", stringify!(sin6_scope_id) ) ); } unsafe extern "C" { pub static in6addr_any: in6_addr; } unsafe extern "C" { pub static in6addr_loopback: in6_addr; } unsafe extern "C" { pub static in6addr_intfacelocal_allnodes: in6_addr; } unsafe extern "C" { pub static in6addr_linklocal_allnodes: in6_addr; } unsafe extern "C" { pub static in6addr_linklocal_allrouters: in6_addr; } #[repr(C)] #[derive(Copy, Clone)] pub struct ipv6_mreq { pub ipv6mr_multiaddr: in6_addr, pub ipv6mr_interface: ::std::os::raw::c_uint, } #[test] fn bindgen_test_layout_ipv6_mreq() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 20usize, concat!("Size of: ", stringify!(ipv6_mreq)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(ipv6_mreq)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ipv6mr_multiaddr) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(ipv6_mreq), "::", stringify!(ipv6mr_multiaddr) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ipv6mr_interface) as usize - ptr as usize }, 16usize, concat!( "Offset of field: ", stringify!(ipv6_mreq), "::", stringify!(ipv6mr_interface) ) ); } #[repr(C)] #[derive(Copy, Clone)] pub struct in6_pktinfo { pub ipi6_addr: in6_addr, pub ipi6_ifindex: ::std::os::raw::c_uint, } #[test] fn bindgen_test_layout_in6_pktinfo() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 20usize, concat!("Size of: ", stringify!(in6_pktinfo)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(in6_pktinfo)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ipi6_addr) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(in6_pktinfo), "::", stringify!(ipi6_addr) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ipi6_ifindex) as usize - ptr as usize }, 16usize, concat!( "Offset of field: ", stringify!(in6_pktinfo), "::", stringify!(ipi6_ifindex) ) ); } #[repr(C)] #[derive(Copy, Clone)] pub struct ip6_mtuinfo { pub ip6m_addr: sockaddr_in6, pub ip6m_mtu: u_int32_t, } #[test] fn bindgen_test_layout_ip6_mtuinfo() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 32usize, concat!("Size of: ", stringify!(ip6_mtuinfo)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(ip6_mtuinfo)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ip6m_addr) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(ip6_mtuinfo), "::", stringify!(ip6m_addr) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ip6m_mtu) as usize - ptr as usize }, 28usize, concat!("Offset of field: ", stringify!(ip6_mtuinfo), "::", stringify!(ip6m_mtu)) ); } unsafe extern "C" { pub fn inet6_opt_init(arg1: *mut ::std::os::raw::c_void, arg2: socklen_t) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn inet6_opt_append( arg1: *mut ::std::os::raw::c_void, arg2: socklen_t, arg3: ::std::os::raw::c_int, arg4: u_int8_t, arg5: socklen_t, arg6: u_int8_t, arg7: *mut *mut ::std::os::raw::c_void, ) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn inet6_opt_finish( arg1: *mut ::std::os::raw::c_void, arg2: socklen_t, arg3: ::std::os::raw::c_int, ) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn inet6_opt_set_val( arg1: *mut ::std::os::raw::c_void, arg2: ::std::os::raw::c_int, arg3: *mut ::std::os::raw::c_void, arg4: socklen_t, ) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn inet6_opt_next( arg1: *mut ::std::os::raw::c_void, arg2: socklen_t, arg3: ::std::os::raw::c_int, arg4: *mut u_int8_t, arg5: *mut socklen_t, arg6: *mut *mut ::std::os::raw::c_void, ) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn inet6_opt_find( arg1: *mut ::std::os::raw::c_void, arg2: socklen_t, arg3: ::std::os::raw::c_int, arg4: u_int8_t, arg5: *mut socklen_t, arg6: *mut *mut ::std::os::raw::c_void, ) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn inet6_opt_get_val( arg1: *mut ::std::os::raw::c_void, arg2: ::std::os::raw::c_int, arg3: *mut ::std::os::raw::c_void, arg4: socklen_t, ) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn inet6_rth_space(arg1: ::std::os::raw::c_int, arg2: ::std::os::raw::c_int) -> socklen_t; } unsafe extern "C" { pub fn inet6_rth_init( arg1: *mut ::std::os::raw::c_void, arg2: socklen_t, arg3: ::std::os::raw::c_int, arg4: ::std::os::raw::c_int, ) -> *mut ::std::os::raw::c_void; } unsafe extern "C" { pub fn inet6_rth_add(arg1: *mut ::std::os::raw::c_void, arg2: *const in6_addr) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn inet6_rth_reverse( arg1: *const ::std::os::raw::c_void, arg2: *mut ::std::os::raw::c_void, ) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn inet6_rth_segments(arg1: *const ::std::os::raw::c_void) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn inet6_rth_getaddr(arg1: *const ::std::os::raw::c_void, arg2: ::std::os::raw::c_int) -> *mut in6_addr; } unsafe extern "C" { pub fn bindresvport(arg1: ::std::os::raw::c_int, arg2: *mut sockaddr_in) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn bindresvport_sa(arg1: ::std::os::raw::c_int, arg2: *mut sockaddr) -> ::std::os::raw::c_int; } #[repr(C)] #[derive(Copy, Clone)] pub struct radix_node { pub rn_mklist: *mut radix_mask, pub rn_p: *mut radix_node, pub rn_b: ::std::os::raw::c_short, pub rn_bmask: ::std::os::raw::c_char, pub rn_flags: u_char, pub rn_u: radix_node__bindgen_ty_1, } #[repr(C)] #[derive(Copy, Clone)] pub union radix_node__bindgen_ty_1 { pub rn_leaf: radix_node__bindgen_ty_1__bindgen_ty_1, pub rn_node: radix_node__bindgen_ty_1__bindgen_ty_2, } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct radix_node__bindgen_ty_1__bindgen_ty_1 { pub rn_Key: caddr_t, pub rn_Mask: caddr_t, pub rn_Dupedkey: *mut radix_node, } #[test] fn bindgen_test_layout_radix_node__bindgen_ty_1__bindgen_ty_1() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 24usize, concat!("Size of: ", stringify!(radix_node__bindgen_ty_1__bindgen_ty_1)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(radix_node__bindgen_ty_1__bindgen_ty_1)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rn_Key) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(radix_node__bindgen_ty_1__bindgen_ty_1), "::", stringify!(rn_Key) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rn_Mask) as usize - ptr as usize }, 8usize, concat!( "Offset of field: ", stringify!(radix_node__bindgen_ty_1__bindgen_ty_1), "::", stringify!(rn_Mask) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rn_Dupedkey) as usize - ptr as usize }, 16usize, concat!( "Offset of field: ", stringify!(radix_node__bindgen_ty_1__bindgen_ty_1), "::", stringify!(rn_Dupedkey) ) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct radix_node__bindgen_ty_1__bindgen_ty_2 { pub rn_Off: ::std::os::raw::c_int, pub rn_L: *mut radix_node, pub rn_R: *mut radix_node, } #[test] fn bindgen_test_layout_radix_node__bindgen_ty_1__bindgen_ty_2() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 24usize, concat!("Size of: ", stringify!(radix_node__bindgen_ty_1__bindgen_ty_2)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(radix_node__bindgen_ty_1__bindgen_ty_2)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rn_Off) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(radix_node__bindgen_ty_1__bindgen_ty_2), "::", stringify!(rn_Off) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rn_L) as usize - ptr as usize }, 8usize, concat!( "Offset of field: ", stringify!(radix_node__bindgen_ty_1__bindgen_ty_2), "::", stringify!(rn_L) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rn_R) as usize - ptr as usize }, 16usize, concat!( "Offset of field: ", stringify!(radix_node__bindgen_ty_1__bindgen_ty_2), "::", stringify!(rn_R) ) ); } #[test] fn bindgen_test_layout_radix_node__bindgen_ty_1() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 24usize, concat!("Size of: ", stringify!(radix_node__bindgen_ty_1)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(radix_node__bindgen_ty_1)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rn_leaf) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(radix_node__bindgen_ty_1), "::", stringify!(rn_leaf) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rn_node) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(radix_node__bindgen_ty_1), "::", stringify!(rn_node) ) ); } #[test] fn bindgen_test_layout_radix_node() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 48usize, concat!("Size of: ", stringify!(radix_node)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(radix_node)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rn_mklist) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(radix_node), "::", stringify!(rn_mklist)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rn_p) as usize - ptr as usize }, 8usize, concat!("Offset of field: ", stringify!(radix_node), "::", stringify!(rn_p)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rn_b) as usize - ptr as usize }, 16usize, concat!("Offset of field: ", stringify!(radix_node), "::", stringify!(rn_b)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rn_bmask) as usize - ptr as usize }, 18usize, concat!("Offset of field: ", stringify!(radix_node), "::", stringify!(rn_bmask)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rn_flags) as usize - ptr as usize }, 19usize, concat!("Offset of field: ", stringify!(radix_node), "::", stringify!(rn_flags)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rn_u) as usize - ptr as usize }, 24usize, concat!("Offset of field: ", stringify!(radix_node), "::", stringify!(rn_u)) ); } #[repr(C)] #[derive(Copy, Clone)] pub struct radix_mask { pub rm_b: ::std::os::raw::c_short, pub rm_unused: ::std::os::raw::c_char, pub rm_flags: u_char, pub rm_mklist: *mut radix_mask, pub rm_rmu: radix_mask__bindgen_ty_1, pub rm_refs: ::std::os::raw::c_int, } #[repr(C)] #[derive(Copy, Clone)] pub union radix_mask__bindgen_ty_1 { pub rmu_mask: caddr_t, pub rmu_leaf: *mut radix_node, } #[test] fn bindgen_test_layout_radix_mask__bindgen_ty_1() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 8usize, concat!("Size of: ", stringify!(radix_mask__bindgen_ty_1)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(radix_mask__bindgen_ty_1)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rmu_mask) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(radix_mask__bindgen_ty_1), "::", stringify!(rmu_mask) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rmu_leaf) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(radix_mask__bindgen_ty_1), "::", stringify!(rmu_leaf) ) ); } #[test] fn bindgen_test_layout_radix_mask() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 32usize, concat!("Size of: ", stringify!(radix_mask)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(radix_mask)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rm_b) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(radix_mask), "::", stringify!(rm_b)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rm_unused) as usize - ptr as usize }, 2usize, concat!("Offset of field: ", stringify!(radix_mask), "::", stringify!(rm_unused)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rm_flags) as usize - ptr as usize }, 3usize, concat!("Offset of field: ", stringify!(radix_mask), "::", stringify!(rm_flags)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rm_mklist) as usize - ptr as usize }, 8usize, concat!("Offset of field: ", stringify!(radix_mask), "::", stringify!(rm_mklist)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rm_rmu) as usize - ptr as usize }, 16usize, concat!("Offset of field: ", stringify!(radix_mask), "::", stringify!(rm_rmu)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rm_refs) as usize - ptr as usize }, 24usize, concat!("Offset of field: ", stringify!(radix_mask), "::", stringify!(rm_refs)) ); } #[repr(C)] #[derive(Copy, Clone)] pub struct radix_node_head { pub rnh_treetop: *mut radix_node, pub rnh_addrsize: ::std::os::raw::c_int, pub rnh_pktsize: ::std::os::raw::c_int, pub rnh_nodes: [radix_node; 3usize], pub rnh_rtableid: u_int, } #[test] fn bindgen_test_layout_radix_node_head() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 168usize, concat!("Size of: ", stringify!(radix_node_head)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(radix_node_head)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rnh_treetop) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(radix_node_head), "::", stringify!(rnh_treetop) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rnh_addrsize) as usize - ptr as usize }, 8usize, concat!( "Offset of field: ", stringify!(radix_node_head), "::", stringify!(rnh_addrsize) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rnh_pktsize) as usize - ptr as usize }, 12usize, concat!( "Offset of field: ", stringify!(radix_node_head), "::", stringify!(rnh_pktsize) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rnh_nodes) as usize - ptr as usize }, 16usize, concat!( "Offset of field: ", stringify!(radix_node_head), "::", stringify!(rnh_nodes) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rnh_rtableid) as usize - ptr as usize }, 160usize, concat!( "Offset of field: ", stringify!(radix_node_head), "::", stringify!(rnh_rtableid) ) ); } unsafe extern "C" { pub fn rn_init(arg1: ::std::os::raw::c_uint); } unsafe extern "C" { pub fn rn_inithead(arg1: *mut *mut ::std::os::raw::c_void, arg2: ::std::os::raw::c_int) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn rn_walktree( arg1: *mut radix_node_head, arg2: ::std::option::Option< unsafe extern "C" fn( arg1: *mut radix_node, arg2: *mut ::std::os::raw::c_void, arg3: u_int, ) -> ::std::os::raw::c_int, >, arg3: *mut ::std::os::raw::c_void, ) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn rn_addroute( arg1: *mut ::std::os::raw::c_void, arg2: *mut ::std::os::raw::c_void, arg3: *mut radix_node_head, arg4: *mut radix_node, arg5: u_int8_t, ) -> *mut radix_node; } unsafe extern "C" { pub fn rn_delete( arg1: *mut ::std::os::raw::c_void, arg2: *mut ::std::os::raw::c_void, arg3: *mut radix_node_head, arg4: *mut radix_node, ) -> *mut radix_node; } unsafe extern "C" { pub fn rn_lookup( arg1: *mut ::std::os::raw::c_void, arg2: *mut ::std::os::raw::c_void, arg3: *mut radix_node_head, ) -> *mut radix_node; } unsafe extern "C" { pub fn rn_match(arg1: *mut ::std::os::raw::c_void, arg2: *mut radix_node_head) -> *mut radix_node; } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct rt_metrics { pub rmx_pksent: u_int64_t, pub rmx_expire: i64, pub rmx_locks: u_int, pub rmx_mtu: u_int, pub rmx_refcnt: u_int, pub rmx_hopcount: u_int, pub rmx_recvpipe: u_int, pub rmx_sendpipe: u_int, pub rmx_ssthresh: u_int, pub rmx_rtt: u_int, pub rmx_rttvar: u_int, pub rmx_pad: u_int, } #[test] fn bindgen_test_layout_rt_metrics() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 56usize, concat!("Size of: ", stringify!(rt_metrics)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(rt_metrics)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rmx_pksent) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(rt_metrics), "::", stringify!(rmx_pksent) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rmx_expire) as usize - ptr as usize }, 8usize, concat!( "Offset of field: ", stringify!(rt_metrics), "::", stringify!(rmx_expire) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rmx_locks) as usize - ptr as usize }, 16usize, concat!("Offset of field: ", stringify!(rt_metrics), "::", stringify!(rmx_locks)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rmx_mtu) as usize - ptr as usize }, 20usize, concat!("Offset of field: ", stringify!(rt_metrics), "::", stringify!(rmx_mtu)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rmx_refcnt) as usize - ptr as usize }, 24usize, concat!( "Offset of field: ", stringify!(rt_metrics), "::", stringify!(rmx_refcnt) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rmx_hopcount) as usize - ptr as usize }, 28usize, concat!( "Offset of field: ", stringify!(rt_metrics), "::", stringify!(rmx_hopcount) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rmx_recvpipe) as usize - ptr as usize }, 32usize, concat!( "Offset of field: ", stringify!(rt_metrics), "::", stringify!(rmx_recvpipe) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rmx_sendpipe) as usize - ptr as usize }, 36usize, concat!( "Offset of field: ", stringify!(rt_metrics), "::", stringify!(rmx_sendpipe) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rmx_ssthresh) as usize - ptr as usize }, 40usize, concat!( "Offset of field: ", stringify!(rt_metrics), "::", stringify!(rmx_ssthresh) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rmx_rtt) as usize - ptr as usize }, 44usize, concat!("Offset of field: ", stringify!(rt_metrics), "::", stringify!(rmx_rtt)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rmx_rttvar) as usize - ptr as usize }, 48usize, concat!( "Offset of field: ", stringify!(rt_metrics), "::", stringify!(rmx_rttvar) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rmx_pad) as usize - ptr as usize }, 52usize, concat!("Offset of field: ", stringify!(rt_metrics), "::", stringify!(rmx_pad)) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct rtstat { pub rts_badredirect: u_int32_t, pub rts_dynamic: u_int32_t, pub rts_newgateway: u_int32_t, pub rts_unreach: u_int32_t, pub rts_wildcard: u_int32_t, } #[test] fn bindgen_test_layout_rtstat() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 20usize, concat!("Size of: ", stringify!(rtstat)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(rtstat)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rts_badredirect) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(rtstat), "::", stringify!(rts_badredirect) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rts_dynamic) as usize - ptr as usize }, 4usize, concat!("Offset of field: ", stringify!(rtstat), "::", stringify!(rts_dynamic)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rts_newgateway) as usize - ptr as usize }, 8usize, concat!( "Offset of field: ", stringify!(rtstat), "::", stringify!(rts_newgateway) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rts_unreach) as usize - ptr as usize }, 12usize, concat!("Offset of field: ", stringify!(rtstat), "::", stringify!(rts_unreach)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rts_wildcard) as usize - ptr as usize }, 16usize, concat!("Offset of field: ", stringify!(rtstat), "::", stringify!(rts_wildcard)) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct rt_tableinfo { pub rti_tableid: u_short, pub rti_domainid: u_short, } #[test] fn bindgen_test_layout_rt_tableinfo() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 4usize, concat!("Size of: ", stringify!(rt_tableinfo)) ); assert_eq!( ::std::mem::align_of::(), 2usize, concat!("Alignment of ", stringify!(rt_tableinfo)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rti_tableid) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(rt_tableinfo), "::", stringify!(rti_tableid) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rti_domainid) as usize - ptr as usize }, 2usize, concat!( "Offset of field: ", stringify!(rt_tableinfo), "::", stringify!(rti_domainid) ) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct rt_msghdr { pub rtm_msglen: u_short, pub rtm_version: u_char, pub rtm_type: u_char, pub rtm_hdrlen: u_short, pub rtm_index: u_short, pub rtm_tableid: u_short, pub rtm_priority: u_char, pub rtm_mpls: u_char, pub rtm_addrs: ::std::os::raw::c_int, pub rtm_flags: ::std::os::raw::c_int, pub rtm_fmask: ::std::os::raw::c_int, pub rtm_pid: pid_t, pub rtm_seq: ::std::os::raw::c_int, pub rtm_errno: ::std::os::raw::c_int, pub rtm_inits: u_int, pub rtm_rmx: rt_metrics, } #[test] fn bindgen_test_layout_rt_msghdr() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 96usize, concat!("Size of: ", stringify!(rt_msghdr)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(rt_msghdr)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rtm_msglen) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(rt_msghdr), "::", stringify!(rtm_msglen)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rtm_version) as usize - ptr as usize }, 2usize, concat!( "Offset of field: ", stringify!(rt_msghdr), "::", stringify!(rtm_version) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rtm_type) as usize - ptr as usize }, 3usize, concat!("Offset of field: ", stringify!(rt_msghdr), "::", stringify!(rtm_type)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rtm_hdrlen) as usize - ptr as usize }, 4usize, concat!("Offset of field: ", stringify!(rt_msghdr), "::", stringify!(rtm_hdrlen)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rtm_index) as usize - ptr as usize }, 6usize, concat!("Offset of field: ", stringify!(rt_msghdr), "::", stringify!(rtm_index)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rtm_tableid) as usize - ptr as usize }, 8usize, concat!( "Offset of field: ", stringify!(rt_msghdr), "::", stringify!(rtm_tableid) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rtm_priority) as usize - ptr as usize }, 10usize, concat!( "Offset of field: ", stringify!(rt_msghdr), "::", stringify!(rtm_priority) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rtm_mpls) as usize - ptr as usize }, 11usize, concat!("Offset of field: ", stringify!(rt_msghdr), "::", stringify!(rtm_mpls)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rtm_addrs) as usize - ptr as usize }, 12usize, concat!("Offset of field: ", stringify!(rt_msghdr), "::", stringify!(rtm_addrs)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rtm_flags) as usize - ptr as usize }, 16usize, concat!("Offset of field: ", stringify!(rt_msghdr), "::", stringify!(rtm_flags)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rtm_fmask) as usize - ptr as usize }, 20usize, concat!("Offset of field: ", stringify!(rt_msghdr), "::", stringify!(rtm_fmask)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rtm_pid) as usize - ptr as usize }, 24usize, concat!("Offset of field: ", stringify!(rt_msghdr), "::", stringify!(rtm_pid)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rtm_seq) as usize - ptr as usize }, 28usize, concat!("Offset of field: ", stringify!(rt_msghdr), "::", stringify!(rtm_seq)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rtm_errno) as usize - ptr as usize }, 32usize, concat!("Offset of field: ", stringify!(rt_msghdr), "::", stringify!(rtm_errno)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rtm_inits) as usize - ptr as usize }, 36usize, concat!("Offset of field: ", stringify!(rt_msghdr), "::", stringify!(rtm_inits)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rtm_rmx) as usize - ptr as usize }, 40usize, concat!("Offset of field: ", stringify!(rt_msghdr), "::", stringify!(rtm_rmx)) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct sockaddr_rtlabel { pub sr_len: u_int8_t, pub sr_family: sa_family_t, pub sr_label: [::std::os::raw::c_char; 32usize], } #[test] fn bindgen_test_layout_sockaddr_rtlabel() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 34usize, concat!("Size of: ", stringify!(sockaddr_rtlabel)) ); assert_eq!( ::std::mem::align_of::(), 1usize, concat!("Alignment of ", stringify!(sockaddr_rtlabel)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).sr_len) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(sockaddr_rtlabel), "::", stringify!(sr_len) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).sr_family) as usize - ptr as usize }, 1usize, concat!( "Offset of field: ", stringify!(sockaddr_rtlabel), "::", stringify!(sr_family) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).sr_label) as usize - ptr as usize }, 2usize, concat!( "Offset of field: ", stringify!(sockaddr_rtlabel), "::", stringify!(sr_label) ) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct sockaddr_rtdns { pub sr_len: u_int8_t, pub sr_family: sa_family_t, pub sr_dns: [::std::os::raw::c_char; 128usize], } #[test] fn bindgen_test_layout_sockaddr_rtdns() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 130usize, concat!("Size of: ", stringify!(sockaddr_rtdns)) ); assert_eq!( ::std::mem::align_of::(), 1usize, concat!("Alignment of ", stringify!(sockaddr_rtdns)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).sr_len) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(sockaddr_rtdns), "::", stringify!(sr_len) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).sr_family) as usize - ptr as usize }, 1usize, concat!( "Offset of field: ", stringify!(sockaddr_rtdns), "::", stringify!(sr_family) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).sr_dns) as usize - ptr as usize }, 2usize, concat!( "Offset of field: ", stringify!(sockaddr_rtdns), "::", stringify!(sr_dns) ) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct sockaddr_rtstatic { pub sr_len: u_int8_t, pub sr_family: sa_family_t, pub sr_static: [::std::os::raw::c_char; 128usize], } #[test] fn bindgen_test_layout_sockaddr_rtstatic() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 130usize, concat!("Size of: ", stringify!(sockaddr_rtstatic)) ); assert_eq!( ::std::mem::align_of::(), 1usize, concat!("Alignment of ", stringify!(sockaddr_rtstatic)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).sr_len) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(sockaddr_rtstatic), "::", stringify!(sr_len) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).sr_family) as usize - ptr as usize }, 1usize, concat!( "Offset of field: ", stringify!(sockaddr_rtstatic), "::", stringify!(sr_family) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).sr_static) as usize - ptr as usize }, 2usize, concat!( "Offset of field: ", stringify!(sockaddr_rtstatic), "::", stringify!(sr_static) ) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct sockaddr_rtsearch { pub sr_len: u_int8_t, pub sr_family: sa_family_t, pub sr_search: [::std::os::raw::c_char; 128usize], } #[test] fn bindgen_test_layout_sockaddr_rtsearch() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 130usize, concat!("Size of: ", stringify!(sockaddr_rtsearch)) ); assert_eq!( ::std::mem::align_of::(), 1usize, concat!("Alignment of ", stringify!(sockaddr_rtsearch)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).sr_len) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(sockaddr_rtsearch), "::", stringify!(sr_len) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).sr_family) as usize - ptr as usize }, 1usize, concat!( "Offset of field: ", stringify!(sockaddr_rtsearch), "::", stringify!(sr_family) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).sr_search) as usize - ptr as usize }, 2usize, concat!( "Offset of field: ", stringify!(sockaddr_rtsearch), "::", stringify!(sr_search) ) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct rt_addrinfo { pub rti_addrs: ::std::os::raw::c_int, pub rti_info: [*const sockaddr; 15usize], pub rti_flags: ::std::os::raw::c_int, pub rti_ifa: *mut ifaddr, pub rti_rtm: *mut rt_msghdr, pub rti_mpls: u_char, } #[test] fn bindgen_test_layout_rt_addrinfo() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 160usize, concat!("Size of: ", stringify!(rt_addrinfo)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(rt_addrinfo)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rti_addrs) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(rt_addrinfo), "::", stringify!(rti_addrs) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rti_info) as usize - ptr as usize }, 8usize, concat!("Offset of field: ", stringify!(rt_addrinfo), "::", stringify!(rti_info)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rti_flags) as usize - ptr as usize }, 128usize, concat!( "Offset of field: ", stringify!(rt_addrinfo), "::", stringify!(rti_flags) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rti_ifa) as usize - ptr as usize }, 136usize, concat!("Offset of field: ", stringify!(rt_addrinfo), "::", stringify!(rti_ifa)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rti_rtm) as usize - ptr as usize }, 144usize, concat!("Offset of field: ", stringify!(rt_addrinfo), "::", stringify!(rti_rtm)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rti_mpls) as usize - ptr as usize }, 152usize, concat!("Offset of field: ", stringify!(rt_addrinfo), "::", stringify!(rti_mpls)) ); } #[repr(C)] #[derive(Copy, Clone)] pub struct route { pub ro_rt: *mut rtentry, pub ro_generation: u_long, pub ro_tableid: u_long, pub __bindgen_anon_1: route__bindgen_ty_1, pub __bindgen_anon_2: route__bindgen_ty_2, } #[repr(C)] #[derive(Copy, Clone)] pub union route__bindgen_ty_1 { pub ro_dstsa: sockaddr, pub ro_dstsin: sockaddr_in, pub ro_dstsin6: sockaddr_in6, } #[test] fn bindgen_test_layout_route__bindgen_ty_1() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 28usize, concat!("Size of: ", stringify!(route__bindgen_ty_1)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(route__bindgen_ty_1)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ro_dstsa) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(route__bindgen_ty_1), "::", stringify!(ro_dstsa) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ro_dstsin) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(route__bindgen_ty_1), "::", stringify!(ro_dstsin) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ro_dstsin6) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(route__bindgen_ty_1), "::", stringify!(ro_dstsin6) ) ); } #[repr(C)] #[derive(Copy, Clone)] pub union route__bindgen_ty_2 { pub ro_srcin: in_addr, pub ro_srcin6: in6_addr, } #[test] fn bindgen_test_layout_route__bindgen_ty_2() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 16usize, concat!("Size of: ", stringify!(route__bindgen_ty_2)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(route__bindgen_ty_2)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ro_srcin) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(route__bindgen_ty_2), "::", stringify!(ro_srcin) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ro_srcin6) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(route__bindgen_ty_2), "::", stringify!(ro_srcin6) ) ); } #[test] fn bindgen_test_layout_route() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 72usize, concat!("Size of: ", stringify!(route)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(route)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ro_rt) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(route), "::", stringify!(ro_rt)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ro_generation) as usize - ptr as usize }, 8usize, concat!("Offset of field: ", stringify!(route), "::", stringify!(ro_generation)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ro_tableid) as usize - ptr as usize }, 16usize, concat!("Offset of field: ", stringify!(route), "::", stringify!(ro_tableid)) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct ip { _unused: [u8; 0], } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct ip6_hdr { _unused: [u8; 0], } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct mbuf_list { _unused: [u8; 0], } pub type pf_refcnt_t = refcnt; pub const PF_INOUT: _bindgen_ty_1 = 0; pub const PF_IN: _bindgen_ty_1 = 1; pub const PF_OUT: _bindgen_ty_1 = 2; pub const PF_FWD: _bindgen_ty_1 = 3; pub type _bindgen_ty_1 = ::std::os::raw::c_uint; pub const PF_PASS: _bindgen_ty_2 = 0; pub const PF_DROP: _bindgen_ty_2 = 1; pub const PF_SCRUB: _bindgen_ty_2 = 2; pub const PF_NOSCRUB: _bindgen_ty_2 = 3; pub const PF_NAT: _bindgen_ty_2 = 4; pub const PF_NONAT: _bindgen_ty_2 = 5; pub const PF_BINAT: _bindgen_ty_2 = 6; pub const PF_NOBINAT: _bindgen_ty_2 = 7; pub const PF_RDR: _bindgen_ty_2 = 8; pub const PF_NORDR: _bindgen_ty_2 = 9; pub const PF_SYNPROXY_DROP: _bindgen_ty_2 = 10; pub const PF_DEFER: _bindgen_ty_2 = 11; pub const PF_MATCH: _bindgen_ty_2 = 12; pub const PF_DIVERT: _bindgen_ty_2 = 13; pub const PF_RT: _bindgen_ty_2 = 14; pub const PF_AFRT: _bindgen_ty_2 = 15; pub type _bindgen_ty_2 = ::std::os::raw::c_uint; pub const PF_TRANS_RULESET: _bindgen_ty_3 = 0; pub const PF_TRANS_TABLE: _bindgen_ty_3 = 1; pub type _bindgen_ty_3 = ::std::os::raw::c_uint; pub const PF_OP_NONE: _bindgen_ty_4 = 0; pub const PF_OP_IRG: _bindgen_ty_4 = 1; pub const PF_OP_EQ: _bindgen_ty_4 = 2; pub const PF_OP_NE: _bindgen_ty_4 = 3; pub const PF_OP_LT: _bindgen_ty_4 = 4; pub const PF_OP_LE: _bindgen_ty_4 = 5; pub const PF_OP_GT: _bindgen_ty_4 = 6; pub const PF_OP_GE: _bindgen_ty_4 = 7; pub const PF_OP_XRG: _bindgen_ty_4 = 8; pub const PF_OP_RRG: _bindgen_ty_4 = 9; pub type _bindgen_ty_4 = ::std::os::raw::c_uint; pub const PF_CHANGE_NONE: _bindgen_ty_5 = 0; pub const PF_CHANGE_ADD_HEAD: _bindgen_ty_5 = 1; pub const PF_CHANGE_ADD_TAIL: _bindgen_ty_5 = 2; pub const PF_CHANGE_ADD_BEFORE: _bindgen_ty_5 = 3; pub const PF_CHANGE_ADD_AFTER: _bindgen_ty_5 = 4; pub const PF_CHANGE_REMOVE: _bindgen_ty_5 = 5; pub const PF_CHANGE_GET_TICKET: _bindgen_ty_5 = 6; pub type _bindgen_ty_5 = ::std::os::raw::c_uint; pub const PF_GET_NONE: _bindgen_ty_6 = 0; pub const PF_GET_CLR_CNTR: _bindgen_ty_6 = 1; pub type _bindgen_ty_6 = ::std::os::raw::c_uint; pub const PF_SK_WIRE: _bindgen_ty_7 = 0; pub const PF_SK_STACK: _bindgen_ty_7 = 1; pub const PF_SK_BOTH: _bindgen_ty_7 = 2; pub type _bindgen_ty_7 = ::std::os::raw::c_uint; pub const PF_PEER_SRC: _bindgen_ty_8 = 0; pub const PF_PEER_DST: _bindgen_ty_8 = 1; pub const PF_PEER_BOTH: _bindgen_ty_8 = 2; pub type _bindgen_ty_8 = ::std::os::raw::c_uint; pub const PFTM_TCP_FIRST_PACKET: _bindgen_ty_9 = 0; pub const PFTM_TCP_OPENING: _bindgen_ty_9 = 1; pub const PFTM_TCP_ESTABLISHED: _bindgen_ty_9 = 2; pub const PFTM_TCP_CLOSING: _bindgen_ty_9 = 3; pub const PFTM_TCP_FIN_WAIT: _bindgen_ty_9 = 4; pub const PFTM_TCP_CLOSED: _bindgen_ty_9 = 5; pub const PFTM_UDP_FIRST_PACKET: _bindgen_ty_9 = 6; pub const PFTM_UDP_SINGLE: _bindgen_ty_9 = 7; pub const PFTM_UDP_MULTIPLE: _bindgen_ty_9 = 8; pub const PFTM_ICMP_FIRST_PACKET: _bindgen_ty_9 = 9; pub const PFTM_ICMP_ERROR_REPLY: _bindgen_ty_9 = 10; pub const PFTM_OTHER_FIRST_PACKET: _bindgen_ty_9 = 11; pub const PFTM_OTHER_SINGLE: _bindgen_ty_9 = 12; pub const PFTM_OTHER_MULTIPLE: _bindgen_ty_9 = 13; pub const PFTM_FRAG: _bindgen_ty_9 = 14; pub const PFTM_INTERVAL: _bindgen_ty_9 = 15; pub const PFTM_ADAPTIVE_START: _bindgen_ty_9 = 16; pub const PFTM_ADAPTIVE_END: _bindgen_ty_9 = 17; pub const PFTM_SRC_NODE: _bindgen_ty_9 = 18; pub const PFTM_TS_DIFF: _bindgen_ty_9 = 19; pub const PFTM_MAX: _bindgen_ty_9 = 20; pub const PFTM_PURGE: _bindgen_ty_9 = 21; pub const PFTM_UNLINKED: _bindgen_ty_9 = 22; pub type _bindgen_ty_9 = ::std::os::raw::c_uint; pub const PF_NOPFROUTE: _bindgen_ty_10 = 0; pub const PF_ROUTETO: _bindgen_ty_10 = 1; pub const PF_DUPTO: _bindgen_ty_10 = 2; pub const PF_REPLYTO: _bindgen_ty_10 = 3; pub type _bindgen_ty_10 = ::std::os::raw::c_uint; pub const PF_LIMIT_STATES: _bindgen_ty_11 = 0; pub const PF_LIMIT_SRC_NODES: _bindgen_ty_11 = 1; pub const PF_LIMIT_FRAGS: _bindgen_ty_11 = 2; pub const PF_LIMIT_TABLES: _bindgen_ty_11 = 3; pub const PF_LIMIT_TABLE_ENTRIES: _bindgen_ty_11 = 4; pub const PF_LIMIT_PKTDELAY_PKTS: _bindgen_ty_11 = 5; pub const PF_LIMIT_ANCHORS: _bindgen_ty_11 = 6; pub const PF_LIMIT_MAX: _bindgen_ty_11 = 7; pub type _bindgen_ty_11 = ::std::os::raw::c_uint; pub const PF_POOL_NONE: _bindgen_ty_12 = 0; pub const PF_POOL_BITMASK: _bindgen_ty_12 = 1; pub const PF_POOL_RANDOM: _bindgen_ty_12 = 2; pub const PF_POOL_SRCHASH: _bindgen_ty_12 = 3; pub const PF_POOL_ROUNDROBIN: _bindgen_ty_12 = 4; pub const PF_POOL_LEASTSTATES: _bindgen_ty_12 = 5; pub type _bindgen_ty_12 = ::std::os::raw::c_uint; pub const PF_ADDR_ADDRMASK: _bindgen_ty_13 = 0; pub const PF_ADDR_NOROUTE: _bindgen_ty_13 = 1; pub const PF_ADDR_DYNIFTL: _bindgen_ty_13 = 2; pub const PF_ADDR_TABLE: _bindgen_ty_13 = 3; pub const PF_ADDR_RTLABEL: _bindgen_ty_13 = 4; pub const PF_ADDR_URPFFAILED: _bindgen_ty_13 = 5; pub const PF_ADDR_RANGE: _bindgen_ty_13 = 6; pub const PF_ADDR_NONE: _bindgen_ty_13 = 7; pub type _bindgen_ty_13 = ::std::os::raw::c_uint; #[repr(C)] #[derive(Copy, Clone)] pub struct pf_addr { pub pfa: pf_addr__bindgen_ty_1, } #[repr(C)] #[derive(Copy, Clone)] pub union pf_addr__bindgen_ty_1 { pub v4: in_addr, pub v6: in6_addr, pub addr8: [u_int8_t; 16usize], pub addr16: [u_int16_t; 8usize], pub addr32: [u_int32_t; 4usize], } #[test] fn bindgen_test_layout_pf_addr__bindgen_ty_1() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 16usize, concat!("Size of: ", stringify!(pf_addr__bindgen_ty_1)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(pf_addr__bindgen_ty_1)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).v4) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pf_addr__bindgen_ty_1), "::", stringify!(v4) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).v6) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pf_addr__bindgen_ty_1), "::", stringify!(v6) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).addr8) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pf_addr__bindgen_ty_1), "::", stringify!(addr8) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).addr16) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pf_addr__bindgen_ty_1), "::", stringify!(addr16) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).addr32) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pf_addr__bindgen_ty_1), "::", stringify!(addr32) ) ); } #[test] fn bindgen_test_layout_pf_addr() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 16usize, concat!("Size of: ", stringify!(pf_addr)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(pf_addr)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfa) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(pf_addr), "::", stringify!(pfa)) ); } #[repr(C)] #[derive(Copy, Clone)] pub struct pf_addr_wrap { pub v: pf_addr_wrap__bindgen_ty_1, pub p: pf_addr_wrap__bindgen_ty_2, pub type_: u_int8_t, pub iflags: u_int8_t, } #[repr(C)] #[derive(Copy, Clone)] pub union pf_addr_wrap__bindgen_ty_1 { pub a: pf_addr_wrap__bindgen_ty_1__bindgen_ty_1, pub ifname: [::std::os::raw::c_char; 16usize], pub tblname: [::std::os::raw::c_char; 32usize], pub rtlabelname: [::std::os::raw::c_char; 32usize], pub rtlabel: u_int32_t, } #[repr(C)] #[derive(Copy, Clone)] pub struct pf_addr_wrap__bindgen_ty_1__bindgen_ty_1 { pub addr: pf_addr, pub mask: pf_addr, } #[test] fn bindgen_test_layout_pf_addr_wrap__bindgen_ty_1__bindgen_ty_1() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 32usize, concat!("Size of: ", stringify!(pf_addr_wrap__bindgen_ty_1__bindgen_ty_1)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(pf_addr_wrap__bindgen_ty_1__bindgen_ty_1)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).addr) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pf_addr_wrap__bindgen_ty_1__bindgen_ty_1), "::", stringify!(addr) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).mask) as usize - ptr as usize }, 16usize, concat!( "Offset of field: ", stringify!(pf_addr_wrap__bindgen_ty_1__bindgen_ty_1), "::", stringify!(mask) ) ); } #[test] fn bindgen_test_layout_pf_addr_wrap__bindgen_ty_1() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 32usize, concat!("Size of: ", stringify!(pf_addr_wrap__bindgen_ty_1)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(pf_addr_wrap__bindgen_ty_1)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).a) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pf_addr_wrap__bindgen_ty_1), "::", stringify!(a) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifname) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pf_addr_wrap__bindgen_ty_1), "::", stringify!(ifname) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).tblname) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pf_addr_wrap__bindgen_ty_1), "::", stringify!(tblname) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rtlabelname) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pf_addr_wrap__bindgen_ty_1), "::", stringify!(rtlabelname) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rtlabel) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pf_addr_wrap__bindgen_ty_1), "::", stringify!(rtlabel) ) ); } #[repr(C)] #[derive(Copy, Clone)] pub union pf_addr_wrap__bindgen_ty_2 { pub dyn_: *mut pfi_dynaddr, pub tbl: *mut pfr_ktable, pub dyncnt: ::std::os::raw::c_int, pub tblcnt: ::std::os::raw::c_int, } #[test] fn bindgen_test_layout_pf_addr_wrap__bindgen_ty_2() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 8usize, concat!("Size of: ", stringify!(pf_addr_wrap__bindgen_ty_2)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pf_addr_wrap__bindgen_ty_2)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).dyn_) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pf_addr_wrap__bindgen_ty_2), "::", stringify!(dyn_) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).tbl) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pf_addr_wrap__bindgen_ty_2), "::", stringify!(tbl) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).dyncnt) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pf_addr_wrap__bindgen_ty_2), "::", stringify!(dyncnt) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).tblcnt) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pf_addr_wrap__bindgen_ty_2), "::", stringify!(tblcnt) ) ); } #[test] fn bindgen_test_layout_pf_addr_wrap() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 48usize, concat!("Size of: ", stringify!(pf_addr_wrap)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pf_addr_wrap)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).v) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(pf_addr_wrap), "::", stringify!(v)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).p) as usize - ptr as usize }, 32usize, concat!("Offset of field: ", stringify!(pf_addr_wrap), "::", stringify!(p)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).type_) as usize - ptr as usize }, 40usize, concat!("Offset of field: ", stringify!(pf_addr_wrap), "::", stringify!(type_)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).iflags) as usize - ptr as usize }, 41usize, concat!("Offset of field: ", stringify!(pf_addr_wrap), "::", stringify!(iflags)) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pf_rule_uid { pub uid: [uid_t; 2usize], pub op: u_int8_t, } #[test] fn bindgen_test_layout_pf_rule_uid() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 12usize, concat!("Size of: ", stringify!(pf_rule_uid)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(pf_rule_uid)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).uid) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(pf_rule_uid), "::", stringify!(uid)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).op) as usize - ptr as usize }, 8usize, concat!("Offset of field: ", stringify!(pf_rule_uid), "::", stringify!(op)) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pf_rule_gid { pub gid: [uid_t; 2usize], pub op: u_int8_t, } #[test] fn bindgen_test_layout_pf_rule_gid() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 12usize, concat!("Size of: ", stringify!(pf_rule_gid)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(pf_rule_gid)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).gid) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(pf_rule_gid), "::", stringify!(gid)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).op) as usize - ptr as usize }, 8usize, concat!("Offset of field: ", stringify!(pf_rule_gid), "::", stringify!(op)) ); } #[repr(C)] #[derive(Copy, Clone)] pub struct pf_rule_addr { pub addr: pf_addr_wrap, pub port: [u_int16_t; 2usize], pub neg: u_int8_t, pub port_op: u_int8_t, pub weight: u_int16_t, } #[test] fn bindgen_test_layout_pf_rule_addr() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 56usize, concat!("Size of: ", stringify!(pf_rule_addr)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pf_rule_addr)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).addr) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(pf_rule_addr), "::", stringify!(addr)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).port) as usize - ptr as usize }, 48usize, concat!("Offset of field: ", stringify!(pf_rule_addr), "::", stringify!(port)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).neg) as usize - ptr as usize }, 52usize, concat!("Offset of field: ", stringify!(pf_rule_addr), "::", stringify!(neg)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).port_op) as usize - ptr as usize }, 53usize, concat!("Offset of field: ", stringify!(pf_rule_addr), "::", stringify!(port_op)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).weight) as usize - ptr as usize }, 54usize, concat!("Offset of field: ", stringify!(pf_rule_addr), "::", stringify!(weight)) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pf_threshold { pub limit: u_int32_t, pub seconds: u_int32_t, pub count: u_int32_t, pub last: u_int32_t, } #[test] fn bindgen_test_layout_pf_threshold() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 16usize, concat!("Size of: ", stringify!(pf_threshold)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(pf_threshold)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).limit) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(pf_threshold), "::", stringify!(limit)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).seconds) as usize - ptr as usize }, 4usize, concat!("Offset of field: ", stringify!(pf_threshold), "::", stringify!(seconds)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).count) as usize - ptr as usize }, 8usize, concat!("Offset of field: ", stringify!(pf_threshold), "::", stringify!(count)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).last) as usize - ptr as usize }, 12usize, concat!("Offset of field: ", stringify!(pf_threshold), "::", stringify!(last)) ); } #[repr(C)] #[derive(Copy, Clone)] pub struct pf_poolhashkey { pub pfk: pf_poolhashkey__bindgen_ty_1, } #[repr(C)] #[derive(Copy, Clone)] pub union pf_poolhashkey__bindgen_ty_1 { pub key8: [u_int8_t; 16usize], pub key16: [u_int16_t; 8usize], pub key32: [u_int32_t; 4usize], } #[test] fn bindgen_test_layout_pf_poolhashkey__bindgen_ty_1() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 16usize, concat!("Size of: ", stringify!(pf_poolhashkey__bindgen_ty_1)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(pf_poolhashkey__bindgen_ty_1)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).key8) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pf_poolhashkey__bindgen_ty_1), "::", stringify!(key8) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).key16) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pf_poolhashkey__bindgen_ty_1), "::", stringify!(key16) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).key32) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pf_poolhashkey__bindgen_ty_1), "::", stringify!(key32) ) ); } #[test] fn bindgen_test_layout_pf_poolhashkey() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 16usize, concat!("Size of: ", stringify!(pf_poolhashkey)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(pf_poolhashkey)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfk) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(pf_poolhashkey), "::", stringify!(pfk)) ); } #[repr(C)] #[derive(Copy, Clone)] pub struct pf_pool { pub addr: pf_addr_wrap, pub key: pf_poolhashkey, pub counter: pf_addr, pub ifname: [::std::os::raw::c_char; 16usize], pub kif: *mut pfi_kif, pub tblidx: ::std::os::raw::c_int, pub states: u_int64_t, pub curweight: ::std::os::raw::c_int, pub weight: u_int16_t, pub proxy_port: [u_int16_t; 2usize], pub port_op: u_int8_t, pub opts: u_int8_t, } #[test] fn bindgen_test_layout_pf_pool() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 136usize, concat!("Size of: ", stringify!(pf_pool)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pf_pool)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).addr) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(pf_pool), "::", stringify!(addr)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).key) as usize - ptr as usize }, 48usize, concat!("Offset of field: ", stringify!(pf_pool), "::", stringify!(key)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).counter) as usize - ptr as usize }, 64usize, concat!("Offset of field: ", stringify!(pf_pool), "::", stringify!(counter)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifname) as usize - ptr as usize }, 80usize, concat!("Offset of field: ", stringify!(pf_pool), "::", stringify!(ifname)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).kif) as usize - ptr as usize }, 96usize, concat!("Offset of field: ", stringify!(pf_pool), "::", stringify!(kif)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).tblidx) as usize - ptr as usize }, 104usize, concat!("Offset of field: ", stringify!(pf_pool), "::", stringify!(tblidx)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).states) as usize - ptr as usize }, 112usize, concat!("Offset of field: ", stringify!(pf_pool), "::", stringify!(states)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).curweight) as usize - ptr as usize }, 120usize, concat!("Offset of field: ", stringify!(pf_pool), "::", stringify!(curweight)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).weight) as usize - ptr as usize }, 124usize, concat!("Offset of field: ", stringify!(pf_pool), "::", stringify!(weight)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).proxy_port) as usize - ptr as usize }, 126usize, concat!("Offset of field: ", stringify!(pf_pool), "::", stringify!(proxy_port)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).port_op) as usize - ptr as usize }, 130usize, concat!("Offset of field: ", stringify!(pf_pool), "::", stringify!(port_op)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).opts) as usize - ptr as usize }, 131usize, concat!("Offset of field: ", stringify!(pf_pool), "::", stringify!(opts)) ); } pub type pf_osfp_t = u_int32_t; #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pf_osfp_entry { pub fp_entry: pf_osfp_entry__bindgen_ty_1, pub fp_os: pf_osfp_t, pub fp_enflags: ::std::os::raw::c_int, pub fp_class_nm: [u_char; 32usize], pub fp_version_nm: [u_char; 32usize], pub fp_subtype_nm: [u_char; 32usize], } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pf_osfp_entry__bindgen_ty_1 { pub sle_next: *mut pf_osfp_entry, } #[test] fn bindgen_test_layout_pf_osfp_entry__bindgen_ty_1() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 8usize, concat!("Size of: ", stringify!(pf_osfp_entry__bindgen_ty_1)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pf_osfp_entry__bindgen_ty_1)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).sle_next) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pf_osfp_entry__bindgen_ty_1), "::", stringify!(sle_next) ) ); } #[test] fn bindgen_test_layout_pf_osfp_entry() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 112usize, concat!("Size of: ", stringify!(pf_osfp_entry)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pf_osfp_entry)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).fp_entry) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pf_osfp_entry), "::", stringify!(fp_entry) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).fp_os) as usize - ptr as usize }, 8usize, concat!("Offset of field: ", stringify!(pf_osfp_entry), "::", stringify!(fp_os)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).fp_enflags) as usize - ptr as usize }, 12usize, concat!( "Offset of field: ", stringify!(pf_osfp_entry), "::", stringify!(fp_enflags) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).fp_class_nm) as usize - ptr as usize }, 16usize, concat!( "Offset of field: ", stringify!(pf_osfp_entry), "::", stringify!(fp_class_nm) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).fp_version_nm) as usize - ptr as usize }, 48usize, concat!( "Offset of field: ", stringify!(pf_osfp_entry), "::", stringify!(fp_version_nm) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).fp_subtype_nm) as usize - ptr as usize }, 80usize, concat!( "Offset of field: ", stringify!(pf_osfp_entry), "::", stringify!(fp_subtype_nm) ) ); } pub type pf_tcpopts_t = u_int64_t; #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pf_os_fingerprint { pub fp_oses: pf_os_fingerprint_pf_osfp_enlist, pub fp_tcpopts: pf_tcpopts_t, pub fp_wsize: u_int16_t, pub fp_psize: u_int16_t, pub fp_mss: u_int16_t, pub fp_flags: u_int16_t, pub fp_optcnt: u_int8_t, pub fp_wscale: u_int8_t, pub fp_ttl: u_int8_t, pub fp_next: pf_os_fingerprint__bindgen_ty_1, } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pf_os_fingerprint_pf_osfp_enlist { pub slh_first: *mut pf_osfp_entry, } #[test] fn bindgen_test_layout_pf_os_fingerprint_pf_osfp_enlist() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 8usize, concat!("Size of: ", stringify!(pf_os_fingerprint_pf_osfp_enlist)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pf_os_fingerprint_pf_osfp_enlist)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).slh_first) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pf_os_fingerprint_pf_osfp_enlist), "::", stringify!(slh_first) ) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pf_os_fingerprint__bindgen_ty_1 { pub sle_next: *mut pf_os_fingerprint, } #[test] fn bindgen_test_layout_pf_os_fingerprint__bindgen_ty_1() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 8usize, concat!("Size of: ", stringify!(pf_os_fingerprint__bindgen_ty_1)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pf_os_fingerprint__bindgen_ty_1)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).sle_next) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pf_os_fingerprint__bindgen_ty_1), "::", stringify!(sle_next) ) ); } #[test] fn bindgen_test_layout_pf_os_fingerprint() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 40usize, concat!("Size of: ", stringify!(pf_os_fingerprint)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pf_os_fingerprint)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).fp_oses) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pf_os_fingerprint), "::", stringify!(fp_oses) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).fp_tcpopts) as usize - ptr as usize }, 8usize, concat!( "Offset of field: ", stringify!(pf_os_fingerprint), "::", stringify!(fp_tcpopts) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).fp_wsize) as usize - ptr as usize }, 16usize, concat!( "Offset of field: ", stringify!(pf_os_fingerprint), "::", stringify!(fp_wsize) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).fp_psize) as usize - ptr as usize }, 18usize, concat!( "Offset of field: ", stringify!(pf_os_fingerprint), "::", stringify!(fp_psize) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).fp_mss) as usize - ptr as usize }, 20usize, concat!( "Offset of field: ", stringify!(pf_os_fingerprint), "::", stringify!(fp_mss) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).fp_flags) as usize - ptr as usize }, 22usize, concat!( "Offset of field: ", stringify!(pf_os_fingerprint), "::", stringify!(fp_flags) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).fp_optcnt) as usize - ptr as usize }, 24usize, concat!( "Offset of field: ", stringify!(pf_os_fingerprint), "::", stringify!(fp_optcnt) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).fp_wscale) as usize - ptr as usize }, 25usize, concat!( "Offset of field: ", stringify!(pf_os_fingerprint), "::", stringify!(fp_wscale) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).fp_ttl) as usize - ptr as usize }, 26usize, concat!( "Offset of field: ", stringify!(pf_os_fingerprint), "::", stringify!(fp_ttl) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).fp_next) as usize - ptr as usize }, 32usize, concat!( "Offset of field: ", stringify!(pf_os_fingerprint), "::", stringify!(fp_next) ) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pf_osfp_ioctl { pub fp_os: pf_osfp_entry, pub fp_tcpopts: pf_tcpopts_t, pub fp_wsize: u_int16_t, pub fp_psize: u_int16_t, pub fp_mss: u_int16_t, pub fp_flags: u_int16_t, pub fp_optcnt: u_int8_t, pub fp_wscale: u_int8_t, pub fp_ttl: u_int8_t, pub fp_getnum: ::std::os::raw::c_int, } #[test] fn bindgen_test_layout_pf_osfp_ioctl() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 136usize, concat!("Size of: ", stringify!(pf_osfp_ioctl)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pf_osfp_ioctl)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).fp_os) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(pf_osfp_ioctl), "::", stringify!(fp_os)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).fp_tcpopts) as usize - ptr as usize }, 112usize, concat!( "Offset of field: ", stringify!(pf_osfp_ioctl), "::", stringify!(fp_tcpopts) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).fp_wsize) as usize - ptr as usize }, 120usize, concat!( "Offset of field: ", stringify!(pf_osfp_ioctl), "::", stringify!(fp_wsize) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).fp_psize) as usize - ptr as usize }, 122usize, concat!( "Offset of field: ", stringify!(pf_osfp_ioctl), "::", stringify!(fp_psize) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).fp_mss) as usize - ptr as usize }, 124usize, concat!("Offset of field: ", stringify!(pf_osfp_ioctl), "::", stringify!(fp_mss)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).fp_flags) as usize - ptr as usize }, 126usize, concat!( "Offset of field: ", stringify!(pf_osfp_ioctl), "::", stringify!(fp_flags) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).fp_optcnt) as usize - ptr as usize }, 128usize, concat!( "Offset of field: ", stringify!(pf_osfp_ioctl), "::", stringify!(fp_optcnt) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).fp_wscale) as usize - ptr as usize }, 129usize, concat!( "Offset of field: ", stringify!(pf_osfp_ioctl), "::", stringify!(fp_wscale) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).fp_ttl) as usize - ptr as usize }, 130usize, concat!("Offset of field: ", stringify!(pf_osfp_ioctl), "::", stringify!(fp_ttl)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).fp_getnum) as usize - ptr as usize }, 132usize, concat!( "Offset of field: ", stringify!(pf_osfp_ioctl), "::", stringify!(fp_getnum) ) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pf_rule_actions { pub rtableid: ::std::os::raw::c_int, pub qid: u_int16_t, pub pqid: u_int16_t, pub max_mss: u_int16_t, pub flags: u_int16_t, pub delay: u_int16_t, pub log: u_int8_t, pub set_tos: u_int8_t, pub min_ttl: u_int8_t, pub set_prio: [u_int8_t; 2usize], pub pad: [u_int8_t; 1usize], } #[test] fn bindgen_test_layout_pf_rule_actions() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 20usize, concat!("Size of: ", stringify!(pf_rule_actions)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(pf_rule_actions)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rtableid) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pf_rule_actions), "::", stringify!(rtableid) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).qid) as usize - ptr as usize }, 4usize, concat!("Offset of field: ", stringify!(pf_rule_actions), "::", stringify!(qid)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pqid) as usize - ptr as usize }, 6usize, concat!("Offset of field: ", stringify!(pf_rule_actions), "::", stringify!(pqid)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).max_mss) as usize - ptr as usize }, 8usize, concat!( "Offset of field: ", stringify!(pf_rule_actions), "::", stringify!(max_mss) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).flags) as usize - ptr as usize }, 10usize, concat!( "Offset of field: ", stringify!(pf_rule_actions), "::", stringify!(flags) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).delay) as usize - ptr as usize }, 12usize, concat!( "Offset of field: ", stringify!(pf_rule_actions), "::", stringify!(delay) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).log) as usize - ptr as usize }, 14usize, concat!("Offset of field: ", stringify!(pf_rule_actions), "::", stringify!(log)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).set_tos) as usize - ptr as usize }, 15usize, concat!( "Offset of field: ", stringify!(pf_rule_actions), "::", stringify!(set_tos) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).min_ttl) as usize - ptr as usize }, 16usize, concat!( "Offset of field: ", stringify!(pf_rule_actions), "::", stringify!(min_ttl) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).set_prio) as usize - ptr as usize }, 17usize, concat!( "Offset of field: ", stringify!(pf_rule_actions), "::", stringify!(set_prio) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pad) as usize - ptr as usize }, 19usize, concat!("Offset of field: ", stringify!(pf_rule_actions), "::", stringify!(pad)) ); } #[repr(C)] #[derive(Copy, Clone)] pub union pf_rule_ptr { pub ptr: *mut pf_rule, pub nr: u_int32_t, } #[test] fn bindgen_test_layout_pf_rule_ptr() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 8usize, concat!("Size of: ", stringify!(pf_rule_ptr)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pf_rule_ptr)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ptr) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(pf_rule_ptr), "::", stringify!(ptr)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).nr) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(pf_rule_ptr), "::", stringify!(nr)) ); } #[repr(C)] #[derive(Copy, Clone)] pub struct pf_rule { pub src: pf_rule_addr, pub dst: pf_rule_addr, pub skip: [pf_rule_ptr; 9usize], pub label: [::std::os::raw::c_char; 64usize], pub ifname: [::std::os::raw::c_char; 16usize], pub rcv_ifname: [::std::os::raw::c_char; 16usize], pub qname: [::std::os::raw::c_char; 64usize], pub pqname: [::std::os::raw::c_char; 64usize], pub tagname: [::std::os::raw::c_char; 64usize], pub match_tagname: [::std::os::raw::c_char; 64usize], pub overload_tblname: [::std::os::raw::c_char; 32usize], pub entries: pf_rule__bindgen_ty_1, pub nat: pf_pool, pub rdr: pf_pool, pub route: pf_pool, pub pktrate: pf_threshold, pub evaluations: u_int64_t, pub packets: [u_int64_t; 2usize], pub bytes: [u_int64_t; 2usize], pub kif: *mut pfi_kif, pub rcv_kif: *mut pfi_kif, pub anchor: *mut pf_anchor, pub overload_tbl: *mut pfr_ktable, pub os_fingerprint: pf_osfp_t, pub rtableid: ::std::os::raw::c_int, pub onrdomain: ::std::os::raw::c_int, pub timeout: [u_int32_t; 20usize], pub states_cur: u_int32_t, pub states_tot: u_int32_t, pub max_states: u_int32_t, pub src_nodes: u_int32_t, pub max_src_nodes: u_int32_t, pub max_src_states: u_int32_t, pub max_src_conn: u_int32_t, pub max_src_conn_rate: pf_rule__bindgen_ty_2, pub qid: u_int32_t, pub pqid: u_int32_t, pub rt_listid: u_int32_t, pub nr: u_int32_t, pub prob: u_int32_t, pub cuid: uid_t, pub cpid: pid_t, pub return_icmp: u_int16_t, pub return_icmp6: u_int16_t, pub max_mss: u_int16_t, pub tag: u_int16_t, pub match_tag: u_int16_t, pub scrub_flags: u_int16_t, pub delay: u_int16_t, pub uid: pf_rule_uid, pub gid: pf_rule_gid, pub rule_flag: u_int32_t, pub action: u_int8_t, pub direction: u_int8_t, pub log: u_int8_t, pub logif: u_int8_t, pub quick: u_int8_t, pub ifnot: u_int8_t, pub match_tag_not: u_int8_t, pub keep_state: u_int8_t, pub af: sa_family_t, pub proto: u_int8_t, pub type_: u_int16_t, pub code: u_int16_t, pub flags: u_int8_t, pub flagset: u_int8_t, pub min_ttl: u_int8_t, pub allow_opts: u_int8_t, pub rt: u_int8_t, pub return_ttl: u_int8_t, pub tos: u_int8_t, pub set_tos: u_int8_t, pub anchor_relative: u_int8_t, pub anchor_wildcard: u_int8_t, pub flush: u_int8_t, pub prio: u_int8_t, pub set_prio: [u_int8_t; 2usize], pub naf: sa_family_t, pub rcvifnot: u_int8_t, pub divert: pf_rule__bindgen_ty_3, pub exptime: time_t, } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pf_rule__bindgen_ty_1 { pub tqe_next: *mut pf_rule, pub tqe_prev: *mut *mut pf_rule, } #[test] fn bindgen_test_layout_pf_rule__bindgen_ty_1() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 16usize, concat!("Size of: ", stringify!(pf_rule__bindgen_ty_1)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pf_rule__bindgen_ty_1)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).tqe_next) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pf_rule__bindgen_ty_1), "::", stringify!(tqe_next) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).tqe_prev) as usize - ptr as usize }, 8usize, concat!( "Offset of field: ", stringify!(pf_rule__bindgen_ty_1), "::", stringify!(tqe_prev) ) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pf_rule__bindgen_ty_2 { pub limit: u_int32_t, pub seconds: u_int32_t, } #[test] fn bindgen_test_layout_pf_rule__bindgen_ty_2() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 8usize, concat!("Size of: ", stringify!(pf_rule__bindgen_ty_2)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(pf_rule__bindgen_ty_2)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).limit) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pf_rule__bindgen_ty_2), "::", stringify!(limit) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).seconds) as usize - ptr as usize }, 4usize, concat!( "Offset of field: ", stringify!(pf_rule__bindgen_ty_2), "::", stringify!(seconds) ) ); } #[repr(C)] #[derive(Copy, Clone)] pub struct pf_rule__bindgen_ty_3 { pub addr: pf_addr, pub port: u_int16_t, pub type_: u_int8_t, } #[test] fn bindgen_test_layout_pf_rule__bindgen_ty_3() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 20usize, concat!("Size of: ", stringify!(pf_rule__bindgen_ty_3)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(pf_rule__bindgen_ty_3)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).addr) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pf_rule__bindgen_ty_3), "::", stringify!(addr) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).port) as usize - ptr as usize }, 16usize, concat!( "Offset of field: ", stringify!(pf_rule__bindgen_ty_3), "::", stringify!(port) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).type_) as usize - ptr as usize }, 18usize, concat!( "Offset of field: ", stringify!(pf_rule__bindgen_ty_3), "::", stringify!(type_) ) ); } #[test] fn bindgen_test_layout_pf_rule() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 1344usize, concat!("Size of: ", stringify!(pf_rule)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pf_rule)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).src) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(src)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).dst) as usize - ptr as usize }, 56usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(dst)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).skip) as usize - ptr as usize }, 112usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(skip)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).label) as usize - ptr as usize }, 184usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(label)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifname) as usize - ptr as usize }, 248usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(ifname)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rcv_ifname) as usize - ptr as usize }, 264usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(rcv_ifname)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).qname) as usize - ptr as usize }, 280usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(qname)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pqname) as usize - ptr as usize }, 344usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(pqname)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).tagname) as usize - ptr as usize }, 408usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(tagname)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).match_tagname) as usize - ptr as usize }, 472usize, concat!( "Offset of field: ", stringify!(pf_rule), "::", stringify!(match_tagname) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).overload_tblname) as usize - ptr as usize }, 536usize, concat!( "Offset of field: ", stringify!(pf_rule), "::", stringify!(overload_tblname) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).entries) as usize - ptr as usize }, 568usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(entries)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).nat) as usize - ptr as usize }, 584usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(nat)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rdr) as usize - ptr as usize }, 720usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(rdr)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).route) as usize - ptr as usize }, 856usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(route)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pktrate) as usize - ptr as usize }, 992usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(pktrate)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).evaluations) as usize - ptr as usize }, 1008usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(evaluations)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).packets) as usize - ptr as usize }, 1016usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(packets)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).bytes) as usize - ptr as usize }, 1032usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(bytes)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).kif) as usize - ptr as usize }, 1048usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(kif)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rcv_kif) as usize - ptr as usize }, 1056usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(rcv_kif)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).anchor) as usize - ptr as usize }, 1064usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(anchor)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).overload_tbl) as usize - ptr as usize }, 1072usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(overload_tbl)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).os_fingerprint) as usize - ptr as usize }, 1080usize, concat!( "Offset of field: ", stringify!(pf_rule), "::", stringify!(os_fingerprint) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rtableid) as usize - ptr as usize }, 1084usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(rtableid)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).onrdomain) as usize - ptr as usize }, 1088usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(onrdomain)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).timeout) as usize - ptr as usize }, 1092usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(timeout)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).states_cur) as usize - ptr as usize }, 1172usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(states_cur)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).states_tot) as usize - ptr as usize }, 1176usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(states_tot)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).max_states) as usize - ptr as usize }, 1180usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(max_states)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).src_nodes) as usize - ptr as usize }, 1184usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(src_nodes)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).max_src_nodes) as usize - ptr as usize }, 1188usize, concat!( "Offset of field: ", stringify!(pf_rule), "::", stringify!(max_src_nodes) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).max_src_states) as usize - ptr as usize }, 1192usize, concat!( "Offset of field: ", stringify!(pf_rule), "::", stringify!(max_src_states) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).max_src_conn) as usize - ptr as usize }, 1196usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(max_src_conn)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).max_src_conn_rate) as usize - ptr as usize }, 1200usize, concat!( "Offset of field: ", stringify!(pf_rule), "::", stringify!(max_src_conn_rate) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).qid) as usize - ptr as usize }, 1208usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(qid)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pqid) as usize - ptr as usize }, 1212usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(pqid)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rt_listid) as usize - ptr as usize }, 1216usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(rt_listid)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).nr) as usize - ptr as usize }, 1220usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(nr)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).prob) as usize - ptr as usize }, 1224usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(prob)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).cuid) as usize - ptr as usize }, 1228usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(cuid)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).cpid) as usize - ptr as usize }, 1232usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(cpid)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).return_icmp) as usize - ptr as usize }, 1236usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(return_icmp)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).return_icmp6) as usize - ptr as usize }, 1238usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(return_icmp6)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).max_mss) as usize - ptr as usize }, 1240usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(max_mss)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).tag) as usize - ptr as usize }, 1242usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(tag)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).match_tag) as usize - ptr as usize }, 1244usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(match_tag)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).scrub_flags) as usize - ptr as usize }, 1246usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(scrub_flags)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).delay) as usize - ptr as usize }, 1248usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(delay)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).uid) as usize - ptr as usize }, 1252usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(uid)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).gid) as usize - ptr as usize }, 1264usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(gid)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rule_flag) as usize - ptr as usize }, 1276usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(rule_flag)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).action) as usize - ptr as usize }, 1280usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(action)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).direction) as usize - ptr as usize }, 1281usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(direction)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).log) as usize - ptr as usize }, 1282usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(log)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).logif) as usize - ptr as usize }, 1283usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(logif)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).quick) as usize - ptr as usize }, 1284usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(quick)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifnot) as usize - ptr as usize }, 1285usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(ifnot)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).match_tag_not) as usize - ptr as usize }, 1286usize, concat!( "Offset of field: ", stringify!(pf_rule), "::", stringify!(match_tag_not) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).keep_state) as usize - ptr as usize }, 1287usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(keep_state)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).af) as usize - ptr as usize }, 1288usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(af)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).proto) as usize - ptr as usize }, 1289usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(proto)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).type_) as usize - ptr as usize }, 1290usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(type_)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).code) as usize - ptr as usize }, 1292usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(code)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).flags) as usize - ptr as usize }, 1294usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(flags)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).flagset) as usize - ptr as usize }, 1295usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(flagset)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).min_ttl) as usize - ptr as usize }, 1296usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(min_ttl)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).allow_opts) as usize - ptr as usize }, 1297usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(allow_opts)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rt) as usize - ptr as usize }, 1298usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(rt)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).return_ttl) as usize - ptr as usize }, 1299usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(return_ttl)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).tos) as usize - ptr as usize }, 1300usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(tos)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).set_tos) as usize - ptr as usize }, 1301usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(set_tos)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).anchor_relative) as usize - ptr as usize }, 1302usize, concat!( "Offset of field: ", stringify!(pf_rule), "::", stringify!(anchor_relative) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).anchor_wildcard) as usize - ptr as usize }, 1303usize, concat!( "Offset of field: ", stringify!(pf_rule), "::", stringify!(anchor_wildcard) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).flush) as usize - ptr as usize }, 1304usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(flush)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).prio) as usize - ptr as usize }, 1305usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(prio)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).set_prio) as usize - ptr as usize }, 1306usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(set_prio)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).naf) as usize - ptr as usize }, 1308usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(naf)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rcvifnot) as usize - ptr as usize }, 1309usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(rcvifnot)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).divert) as usize - ptr as usize }, 1312usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(divert)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).exptime) as usize - ptr as usize }, 1336usize, concat!("Offset of field: ", stringify!(pf_rule), "::", stringify!(exptime)) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pf_rule_item { pub entry: pf_rule_item__bindgen_ty_1, pub r: *mut pf_rule, } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pf_rule_item__bindgen_ty_1 { pub sle_next: *mut pf_rule_item, } #[test] fn bindgen_test_layout_pf_rule_item__bindgen_ty_1() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 8usize, concat!("Size of: ", stringify!(pf_rule_item__bindgen_ty_1)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pf_rule_item__bindgen_ty_1)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).sle_next) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pf_rule_item__bindgen_ty_1), "::", stringify!(sle_next) ) ); } #[test] fn bindgen_test_layout_pf_rule_item() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 16usize, concat!("Size of: ", stringify!(pf_rule_item)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pf_rule_item)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).entry) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(pf_rule_item), "::", stringify!(entry)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).r) as usize - ptr as usize }, 8usize, concat!("Offset of field: ", stringify!(pf_rule_item), "::", stringify!(r)) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pf_rule_slist { pub slh_first: *mut pf_rule_item, } #[test] fn bindgen_test_layout_pf_rule_slist() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 8usize, concat!("Size of: ", stringify!(pf_rule_slist)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pf_rule_slist)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).slh_first) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pf_rule_slist), "::", stringify!(slh_first) ) ); } pub const pf_sn_types_PF_SN_NONE: pf_sn_types = 0; pub const pf_sn_types_PF_SN_NAT: pf_sn_types = 1; pub const pf_sn_types_PF_SN_RDR: pf_sn_types = 2; pub const pf_sn_types_PF_SN_ROUTE: pf_sn_types = 3; pub const pf_sn_types_PF_SN_MAX: pf_sn_types = 4; pub type pf_sn_types = ::std::os::raw::c_uint; #[repr(C)] #[derive(Copy, Clone)] pub struct pf_src_node { pub entry: pf_src_node__bindgen_ty_1, pub addr: pf_addr, pub raddr: pf_addr, pub rule: pf_rule_ptr, pub kif: *mut pfi_kif, pub bytes: [u_int64_t; 2usize], pub packets: [u_int64_t; 2usize], pub states: u_int32_t, pub conn: u_int32_t, pub conn_rate: pf_threshold, pub creation: i32, pub expire: i32, pub af: sa_family_t, pub naf: sa_family_t, pub type_: u_int8_t, } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pf_src_node__bindgen_ty_1 { pub rbe_left: *mut pf_src_node, pub rbe_right: *mut pf_src_node, pub rbe_parent: *mut pf_src_node, pub rbe_color: ::std::os::raw::c_int, } #[test] fn bindgen_test_layout_pf_src_node__bindgen_ty_1() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 32usize, concat!("Size of: ", stringify!(pf_src_node__bindgen_ty_1)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pf_src_node__bindgen_ty_1)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rbe_left) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pf_src_node__bindgen_ty_1), "::", stringify!(rbe_left) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rbe_right) as usize - ptr as usize }, 8usize, concat!( "Offset of field: ", stringify!(pf_src_node__bindgen_ty_1), "::", stringify!(rbe_right) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rbe_parent) as usize - ptr as usize }, 16usize, concat!( "Offset of field: ", stringify!(pf_src_node__bindgen_ty_1), "::", stringify!(rbe_parent) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rbe_color) as usize - ptr as usize }, 24usize, concat!( "Offset of field: ", stringify!(pf_src_node__bindgen_ty_1), "::", stringify!(rbe_color) ) ); } #[test] fn bindgen_test_layout_pf_src_node() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 152usize, concat!("Size of: ", stringify!(pf_src_node)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pf_src_node)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).entry) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(pf_src_node), "::", stringify!(entry)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).addr) as usize - ptr as usize }, 32usize, concat!("Offset of field: ", stringify!(pf_src_node), "::", stringify!(addr)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).raddr) as usize - ptr as usize }, 48usize, concat!("Offset of field: ", stringify!(pf_src_node), "::", stringify!(raddr)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rule) as usize - ptr as usize }, 64usize, concat!("Offset of field: ", stringify!(pf_src_node), "::", stringify!(rule)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).kif) as usize - ptr as usize }, 72usize, concat!("Offset of field: ", stringify!(pf_src_node), "::", stringify!(kif)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).bytes) as usize - ptr as usize }, 80usize, concat!("Offset of field: ", stringify!(pf_src_node), "::", stringify!(bytes)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).packets) as usize - ptr as usize }, 96usize, concat!("Offset of field: ", stringify!(pf_src_node), "::", stringify!(packets)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).states) as usize - ptr as usize }, 112usize, concat!("Offset of field: ", stringify!(pf_src_node), "::", stringify!(states)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).conn) as usize - ptr as usize }, 116usize, concat!("Offset of field: ", stringify!(pf_src_node), "::", stringify!(conn)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).conn_rate) as usize - ptr as usize }, 120usize, concat!( "Offset of field: ", stringify!(pf_src_node), "::", stringify!(conn_rate) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).creation) as usize - ptr as usize }, 136usize, concat!("Offset of field: ", stringify!(pf_src_node), "::", stringify!(creation)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).expire) as usize - ptr as usize }, 140usize, concat!("Offset of field: ", stringify!(pf_src_node), "::", stringify!(expire)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).af) as usize - ptr as usize }, 144usize, concat!("Offset of field: ", stringify!(pf_src_node), "::", stringify!(af)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).naf) as usize - ptr as usize }, 145usize, concat!("Offset of field: ", stringify!(pf_src_node), "::", stringify!(naf)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).type_) as usize - ptr as usize }, 146usize, concat!("Offset of field: ", stringify!(pf_src_node), "::", stringify!(type_)) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pf_sn_item { pub next: pf_sn_item__bindgen_ty_1, pub sn: *mut pf_src_node, } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pf_sn_item__bindgen_ty_1 { pub sle_next: *mut pf_sn_item, } #[test] fn bindgen_test_layout_pf_sn_item__bindgen_ty_1() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 8usize, concat!("Size of: ", stringify!(pf_sn_item__bindgen_ty_1)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pf_sn_item__bindgen_ty_1)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).sle_next) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pf_sn_item__bindgen_ty_1), "::", stringify!(sle_next) ) ); } #[test] fn bindgen_test_layout_pf_sn_item() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 16usize, concat!("Size of: ", stringify!(pf_sn_item)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pf_sn_item)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).next) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(pf_sn_item), "::", stringify!(next)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).sn) as usize - ptr as usize }, 8usize, concat!("Offset of field: ", stringify!(pf_sn_item), "::", stringify!(sn)) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pf_sn_head { pub slh_first: *mut pf_sn_item, } #[test] fn bindgen_test_layout_pf_sn_head() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 8usize, concat!("Size of: ", stringify!(pf_sn_head)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pf_sn_head)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).slh_first) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(pf_sn_head), "::", stringify!(slh_first)) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pf_state_scrub { pub pfss_last: timeval, pub pfss_tsecr: u_int32_t, pub pfss_tsval: u_int32_t, pub pfss_tsval0: u_int32_t, pub pfss_flags: u_int16_t, pub pfss_ttl: u_int8_t, pub pad: u_int8_t, pub pfss_ts_mod: u_int32_t, } #[test] fn bindgen_test_layout_pf_state_scrub() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 40usize, concat!("Size of: ", stringify!(pf_state_scrub)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pf_state_scrub)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfss_last) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pf_state_scrub), "::", stringify!(pfss_last) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfss_tsecr) as usize - ptr as usize }, 16usize, concat!( "Offset of field: ", stringify!(pf_state_scrub), "::", stringify!(pfss_tsecr) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfss_tsval) as usize - ptr as usize }, 20usize, concat!( "Offset of field: ", stringify!(pf_state_scrub), "::", stringify!(pfss_tsval) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfss_tsval0) as usize - ptr as usize }, 24usize, concat!( "Offset of field: ", stringify!(pf_state_scrub), "::", stringify!(pfss_tsval0) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfss_flags) as usize - ptr as usize }, 28usize, concat!( "Offset of field: ", stringify!(pf_state_scrub), "::", stringify!(pfss_flags) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfss_ttl) as usize - ptr as usize }, 30usize, concat!( "Offset of field: ", stringify!(pf_state_scrub), "::", stringify!(pfss_ttl) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pad) as usize - ptr as usize }, 31usize, concat!("Offset of field: ", stringify!(pf_state_scrub), "::", stringify!(pad)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfss_ts_mod) as usize - ptr as usize }, 32usize, concat!( "Offset of field: ", stringify!(pf_state_scrub), "::", stringify!(pfss_ts_mod) ) ); } #[repr(C)] #[derive(Copy, Clone)] pub struct pf_state_host { pub addr: pf_addr, pub port: u_int16_t, pub pad: u_int16_t, } #[test] fn bindgen_test_layout_pf_state_host() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 20usize, concat!("Size of: ", stringify!(pf_state_host)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(pf_state_host)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).addr) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(pf_state_host), "::", stringify!(addr)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).port) as usize - ptr as usize }, 16usize, concat!("Offset of field: ", stringify!(pf_state_host), "::", stringify!(port)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pad) as usize - ptr as usize }, 18usize, concat!("Offset of field: ", stringify!(pf_state_host), "::", stringify!(pad)) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pf_state_peer { pub scrub: *mut pf_state_scrub, pub seqlo: u_int32_t, pub seqhi: u_int32_t, pub seqdiff: u_int32_t, pub max_win: u_int16_t, pub mss: u_int16_t, pub state: u_int8_t, pub wscale: u_int8_t, pub tcp_est: u_int8_t, pub pad: [u_int8_t; 1usize], } #[test] fn bindgen_test_layout_pf_state_peer() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 32usize, concat!("Size of: ", stringify!(pf_state_peer)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pf_state_peer)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).scrub) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(pf_state_peer), "::", stringify!(scrub)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).seqlo) as usize - ptr as usize }, 8usize, concat!("Offset of field: ", stringify!(pf_state_peer), "::", stringify!(seqlo)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).seqhi) as usize - ptr as usize }, 12usize, concat!("Offset of field: ", stringify!(pf_state_peer), "::", stringify!(seqhi)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).seqdiff) as usize - ptr as usize }, 16usize, concat!( "Offset of field: ", stringify!(pf_state_peer), "::", stringify!(seqdiff) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).max_win) as usize - ptr as usize }, 20usize, concat!( "Offset of field: ", stringify!(pf_state_peer), "::", stringify!(max_win) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).mss) as usize - ptr as usize }, 22usize, concat!("Offset of field: ", stringify!(pf_state_peer), "::", stringify!(mss)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).state) as usize - ptr as usize }, 24usize, concat!("Offset of field: ", stringify!(pf_state_peer), "::", stringify!(state)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).wscale) as usize - ptr as usize }, 25usize, concat!("Offset of field: ", stringify!(pf_state_peer), "::", stringify!(wscale)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).tcp_est) as usize - ptr as usize }, 26usize, concat!( "Offset of field: ", stringify!(pf_state_peer), "::", stringify!(tcp_est) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pad) as usize - ptr as usize }, 27usize, concat!("Offset of field: ", stringify!(pf_state_peer), "::", stringify!(pad)) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pf_state_queue { pub tqh_first: *mut pf_state, pub tqh_last: *mut *mut pf_state, } #[test] fn bindgen_test_layout_pf_state_queue() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 16usize, concat!("Size of: ", stringify!(pf_state_queue)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pf_state_queue)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).tqh_first) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pf_state_queue), "::", stringify!(tqh_first) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).tqh_last) as usize - ptr as usize }, 8usize, concat!( "Offset of field: ", stringify!(pf_state_queue), "::", stringify!(tqh_last) ) ); } #[repr(C)] #[derive(Copy, Clone)] pub struct pf_state_key_cmp { pub addr: [pf_addr; 2usize], pub port: [u_int16_t; 2usize], pub rdomain: u_int16_t, pub hash: u_int16_t, pub af: sa_family_t, pub proto: u_int8_t, } #[test] fn bindgen_test_layout_pf_state_key_cmp() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 44usize, concat!("Size of: ", stringify!(pf_state_key_cmp)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(pf_state_key_cmp)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).addr) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pf_state_key_cmp), "::", stringify!(addr) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).port) as usize - ptr as usize }, 32usize, concat!( "Offset of field: ", stringify!(pf_state_key_cmp), "::", stringify!(port) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rdomain) as usize - ptr as usize }, 36usize, concat!( "Offset of field: ", stringify!(pf_state_key_cmp), "::", stringify!(rdomain) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).hash) as usize - ptr as usize }, 38usize, concat!( "Offset of field: ", stringify!(pf_state_key_cmp), "::", stringify!(hash) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).af) as usize - ptr as usize }, 40usize, concat!("Offset of field: ", stringify!(pf_state_key_cmp), "::", stringify!(af)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).proto) as usize - ptr as usize }, 41usize, concat!( "Offset of field: ", stringify!(pf_state_key_cmp), "::", stringify!(proto) ) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pf_state_cmp { pub id: u_int64_t, pub creatorid: u_int32_t, pub direction: u_int8_t, pub pad: [u_int8_t; 3usize], } #[test] fn bindgen_test_layout_pf_state_cmp() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 16usize, concat!("Size of: ", stringify!(pf_state_cmp)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pf_state_cmp)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).id) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(pf_state_cmp), "::", stringify!(id)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).creatorid) as usize - ptr as usize }, 8usize, concat!( "Offset of field: ", stringify!(pf_state_cmp), "::", stringify!(creatorid) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).direction) as usize - ptr as usize }, 12usize, concat!( "Offset of field: ", stringify!(pf_state_cmp), "::", stringify!(direction) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pad) as usize - ptr as usize }, 13usize, concat!("Offset of field: ", stringify!(pf_state_cmp), "::", stringify!(pad)) ); } #[repr(C, packed)] #[derive(Debug, Copy, Clone)] pub struct pfsync_state_scrub { pub pfss_flags: u_int16_t, pub pfss_ttl: u_int8_t, pub scrub_flag: u_int8_t, pub pfss_ts_mod: u_int32_t, } #[test] fn bindgen_test_layout_pfsync_state_scrub() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 8usize, concat!("Size of: ", stringify!(pfsync_state_scrub)) ); assert_eq!( ::std::mem::align_of::(), 1usize, concat!("Alignment of ", stringify!(pfsync_state_scrub)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfss_flags) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pfsync_state_scrub), "::", stringify!(pfss_flags) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfss_ttl) as usize - ptr as usize }, 2usize, concat!( "Offset of field: ", stringify!(pfsync_state_scrub), "::", stringify!(pfss_ttl) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).scrub_flag) as usize - ptr as usize }, 3usize, concat!( "Offset of field: ", stringify!(pfsync_state_scrub), "::", stringify!(scrub_flag) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfss_ts_mod) as usize - ptr as usize }, 4usize, concat!( "Offset of field: ", stringify!(pfsync_state_scrub), "::", stringify!(pfss_ts_mod) ) ); } #[repr(C, packed)] #[derive(Debug, Copy, Clone)] pub struct pfsync_state_peer { pub scrub: pfsync_state_scrub, pub seqlo: u_int32_t, pub seqhi: u_int32_t, pub seqdiff: u_int32_t, pub max_win: u_int16_t, pub mss: u_int16_t, pub state: u_int8_t, pub wscale: u_int8_t, pub pad: [u_int8_t; 6usize], } #[test] fn bindgen_test_layout_pfsync_state_peer() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 32usize, concat!("Size of: ", stringify!(pfsync_state_peer)) ); assert_eq!( ::std::mem::align_of::(), 1usize, concat!("Alignment of ", stringify!(pfsync_state_peer)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).scrub) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pfsync_state_peer), "::", stringify!(scrub) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).seqlo) as usize - ptr as usize }, 8usize, concat!( "Offset of field: ", stringify!(pfsync_state_peer), "::", stringify!(seqlo) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).seqhi) as usize - ptr as usize }, 12usize, concat!( "Offset of field: ", stringify!(pfsync_state_peer), "::", stringify!(seqhi) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).seqdiff) as usize - ptr as usize }, 16usize, concat!( "Offset of field: ", stringify!(pfsync_state_peer), "::", stringify!(seqdiff) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).max_win) as usize - ptr as usize }, 20usize, concat!( "Offset of field: ", stringify!(pfsync_state_peer), "::", stringify!(max_win) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).mss) as usize - ptr as usize }, 22usize, concat!( "Offset of field: ", stringify!(pfsync_state_peer), "::", stringify!(mss) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).state) as usize - ptr as usize }, 24usize, concat!( "Offset of field: ", stringify!(pfsync_state_peer), "::", stringify!(state) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).wscale) as usize - ptr as usize }, 25usize, concat!( "Offset of field: ", stringify!(pfsync_state_peer), "::", stringify!(wscale) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pad) as usize - ptr as usize }, 26usize, concat!( "Offset of field: ", stringify!(pfsync_state_peer), "::", stringify!(pad) ) ); } #[repr(C)] #[derive(Copy, Clone)] pub struct pfsync_state_key { pub addr: [pf_addr; 2usize], pub port: [u_int16_t; 2usize], pub rdomain: u_int16_t, pub af: sa_family_t, pub pad: u_int8_t, } #[test] fn bindgen_test_layout_pfsync_state_key() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 40usize, concat!("Size of: ", stringify!(pfsync_state_key)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(pfsync_state_key)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).addr) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pfsync_state_key), "::", stringify!(addr) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).port) as usize - ptr as usize }, 32usize, concat!( "Offset of field: ", stringify!(pfsync_state_key), "::", stringify!(port) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rdomain) as usize - ptr as usize }, 36usize, concat!( "Offset of field: ", stringify!(pfsync_state_key), "::", stringify!(rdomain) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).af) as usize - ptr as usize }, 38usize, concat!("Offset of field: ", stringify!(pfsync_state_key), "::", stringify!(af)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pad) as usize - ptr as usize }, 39usize, concat!("Offset of field: ", stringify!(pfsync_state_key), "::", stringify!(pad)) ); } #[repr(C, packed)] #[derive(Copy, Clone)] pub struct pfsync_state { pub id: u_int64_t, pub ifname: [::std::os::raw::c_char; 16usize], pub key: [pfsync_state_key; 2usize], pub src: pfsync_state_peer, pub dst: pfsync_state_peer, pub rt_addr: pf_addr, pub rule: u_int32_t, pub anchor: u_int32_t, pub nat_rule: u_int32_t, pub creation: u_int32_t, pub expire: u_int32_t, pub packets: [[u_int32_t; 2usize]; 2usize], pub bytes: [[u_int32_t; 2usize]; 2usize], pub creatorid: u_int32_t, pub rtableid: [i32; 2usize], pub max_mss: u_int16_t, pub af: sa_family_t, pub proto: u_int8_t, pub direction: u_int8_t, pub log: u_int8_t, pub rt: u_int8_t, pub timeout: u_int8_t, pub sync_flags: u_int8_t, pub updates: u_int8_t, pub min_ttl: u_int8_t, pub set_tos: u_int8_t, pub state_flags: u_int16_t, pub set_prio: [u_int8_t; 2usize], } #[test] fn bindgen_test_layout_pfsync_state() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 264usize, concat!("Size of: ", stringify!(pfsync_state)) ); assert_eq!( ::std::mem::align_of::(), 1usize, concat!("Alignment of ", stringify!(pfsync_state)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).id) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(pfsync_state), "::", stringify!(id)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifname) as usize - ptr as usize }, 8usize, concat!("Offset of field: ", stringify!(pfsync_state), "::", stringify!(ifname)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).key) as usize - ptr as usize }, 24usize, concat!("Offset of field: ", stringify!(pfsync_state), "::", stringify!(key)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).src) as usize - ptr as usize }, 104usize, concat!("Offset of field: ", stringify!(pfsync_state), "::", stringify!(src)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).dst) as usize - ptr as usize }, 136usize, concat!("Offset of field: ", stringify!(pfsync_state), "::", stringify!(dst)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rt_addr) as usize - ptr as usize }, 168usize, concat!("Offset of field: ", stringify!(pfsync_state), "::", stringify!(rt_addr)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rule) as usize - ptr as usize }, 184usize, concat!("Offset of field: ", stringify!(pfsync_state), "::", stringify!(rule)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).anchor) as usize - ptr as usize }, 188usize, concat!("Offset of field: ", stringify!(pfsync_state), "::", stringify!(anchor)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).nat_rule) as usize - ptr as usize }, 192usize, concat!( "Offset of field: ", stringify!(pfsync_state), "::", stringify!(nat_rule) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).creation) as usize - ptr as usize }, 196usize, concat!( "Offset of field: ", stringify!(pfsync_state), "::", stringify!(creation) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).expire) as usize - ptr as usize }, 200usize, concat!("Offset of field: ", stringify!(pfsync_state), "::", stringify!(expire)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).packets) as usize - ptr as usize }, 204usize, concat!("Offset of field: ", stringify!(pfsync_state), "::", stringify!(packets)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).bytes) as usize - ptr as usize }, 220usize, concat!("Offset of field: ", stringify!(pfsync_state), "::", stringify!(bytes)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).creatorid) as usize - ptr as usize }, 236usize, concat!( "Offset of field: ", stringify!(pfsync_state), "::", stringify!(creatorid) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rtableid) as usize - ptr as usize }, 240usize, concat!( "Offset of field: ", stringify!(pfsync_state), "::", stringify!(rtableid) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).max_mss) as usize - ptr as usize }, 248usize, concat!("Offset of field: ", stringify!(pfsync_state), "::", stringify!(max_mss)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).af) as usize - ptr as usize }, 250usize, concat!("Offset of field: ", stringify!(pfsync_state), "::", stringify!(af)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).proto) as usize - ptr as usize }, 251usize, concat!("Offset of field: ", stringify!(pfsync_state), "::", stringify!(proto)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).direction) as usize - ptr as usize }, 252usize, concat!( "Offset of field: ", stringify!(pfsync_state), "::", stringify!(direction) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).log) as usize - ptr as usize }, 253usize, concat!("Offset of field: ", stringify!(pfsync_state), "::", stringify!(log)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rt) as usize - ptr as usize }, 254usize, concat!("Offset of field: ", stringify!(pfsync_state), "::", stringify!(rt)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).timeout) as usize - ptr as usize }, 255usize, concat!("Offset of field: ", stringify!(pfsync_state), "::", stringify!(timeout)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).sync_flags) as usize - ptr as usize }, 256usize, concat!( "Offset of field: ", stringify!(pfsync_state), "::", stringify!(sync_flags) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).updates) as usize - ptr as usize }, 257usize, concat!("Offset of field: ", stringify!(pfsync_state), "::", stringify!(updates)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).min_ttl) as usize - ptr as usize }, 258usize, concat!("Offset of field: ", stringify!(pfsync_state), "::", stringify!(min_ttl)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).set_tos) as usize - ptr as usize }, 259usize, concat!("Offset of field: ", stringify!(pfsync_state), "::", stringify!(set_tos)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).state_flags) as usize - ptr as usize }, 260usize, concat!( "Offset of field: ", stringify!(pfsync_state), "::", stringify!(state_flags) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).set_prio) as usize - ptr as usize }, 262usize, concat!( "Offset of field: ", stringify!(pfsync_state), "::", stringify!(set_prio) ) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pf_rulequeue { pub tqh_first: *mut pf_rule, pub tqh_last: *mut *mut pf_rule, } #[test] fn bindgen_test_layout_pf_rulequeue() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 16usize, concat!("Size of: ", stringify!(pf_rulequeue)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pf_rulequeue)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).tqh_first) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pf_rulequeue), "::", stringify!(tqh_first) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).tqh_last) as usize - ptr as usize }, 8usize, concat!( "Offset of field: ", stringify!(pf_rulequeue), "::", stringify!(tqh_last) ) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pf_ruleset { pub rules: pf_ruleset__bindgen_ty_1, pub anchor: *mut pf_anchor, pub tticket: u_int32_t, pub tables: ::std::os::raw::c_int, pub topen: ::std::os::raw::c_int, } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pf_ruleset__bindgen_ty_1 { pub queues: [pf_rulequeue; 2usize], pub active: pf_ruleset__bindgen_ty_1__bindgen_ty_1, pub inactive: pf_ruleset__bindgen_ty_1__bindgen_ty_1, } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pf_ruleset__bindgen_ty_1__bindgen_ty_1 { pub ptr: *mut pf_rulequeue, pub rcount: u_int32_t, pub version: u_int32_t, pub open: ::std::os::raw::c_int, } #[test] fn bindgen_test_layout_pf_ruleset__bindgen_ty_1__bindgen_ty_1() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 24usize, concat!("Size of: ", stringify!(pf_ruleset__bindgen_ty_1__bindgen_ty_1)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pf_ruleset__bindgen_ty_1__bindgen_ty_1)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ptr) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pf_ruleset__bindgen_ty_1__bindgen_ty_1), "::", stringify!(ptr) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rcount) as usize - ptr as usize }, 8usize, concat!( "Offset of field: ", stringify!(pf_ruleset__bindgen_ty_1__bindgen_ty_1), "::", stringify!(rcount) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).version) as usize - ptr as usize }, 12usize, concat!( "Offset of field: ", stringify!(pf_ruleset__bindgen_ty_1__bindgen_ty_1), "::", stringify!(version) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).open) as usize - ptr as usize }, 16usize, concat!( "Offset of field: ", stringify!(pf_ruleset__bindgen_ty_1__bindgen_ty_1), "::", stringify!(open) ) ); } #[test] fn bindgen_test_layout_pf_ruleset__bindgen_ty_1() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 80usize, concat!("Size of: ", stringify!(pf_ruleset__bindgen_ty_1)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pf_ruleset__bindgen_ty_1)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).queues) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pf_ruleset__bindgen_ty_1), "::", stringify!(queues) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).active) as usize - ptr as usize }, 32usize, concat!( "Offset of field: ", stringify!(pf_ruleset__bindgen_ty_1), "::", stringify!(active) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).inactive) as usize - ptr as usize }, 56usize, concat!( "Offset of field: ", stringify!(pf_ruleset__bindgen_ty_1), "::", stringify!(inactive) ) ); } #[test] fn bindgen_test_layout_pf_ruleset() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 104usize, concat!("Size of: ", stringify!(pf_ruleset)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pf_ruleset)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rules) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(pf_ruleset), "::", stringify!(rules)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).anchor) as usize - ptr as usize }, 80usize, concat!("Offset of field: ", stringify!(pf_ruleset), "::", stringify!(anchor)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).tticket) as usize - ptr as usize }, 88usize, concat!("Offset of field: ", stringify!(pf_ruleset), "::", stringify!(tticket)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).tables) as usize - ptr as usize }, 92usize, concat!("Offset of field: ", stringify!(pf_ruleset), "::", stringify!(tables)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).topen) as usize - ptr as usize }, 96usize, concat!("Offset of field: ", stringify!(pf_ruleset), "::", stringify!(topen)) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pf_anchor_global { pub rbh_root: *mut pf_anchor, } #[test] fn bindgen_test_layout_pf_anchor_global() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 8usize, concat!("Size of: ", stringify!(pf_anchor_global)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pf_anchor_global)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rbh_root) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pf_anchor_global), "::", stringify!(rbh_root) ) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pf_anchor_node { pub rbh_root: *mut pf_anchor, } #[test] fn bindgen_test_layout_pf_anchor_node() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 8usize, concat!("Size of: ", stringify!(pf_anchor_node)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pf_anchor_node)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rbh_root) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pf_anchor_node), "::", stringify!(rbh_root) ) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pf_anchor { pub entry_global: pf_anchor__bindgen_ty_1, pub entry_node: pf_anchor__bindgen_ty_2, pub parent: *mut pf_anchor, pub children: pf_anchor_node, pub name: [::std::os::raw::c_char; 64usize], pub path: [::std::os::raw::c_char; 1024usize], pub ruleset: pf_ruleset, pub refcnt: ::std::os::raw::c_int, pub match_: ::std::os::raw::c_int, pub ref_: refcnt, } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pf_anchor__bindgen_ty_1 { pub rbe_left: *mut pf_anchor, pub rbe_right: *mut pf_anchor, pub rbe_parent: *mut pf_anchor, pub rbe_color: ::std::os::raw::c_int, } #[test] fn bindgen_test_layout_pf_anchor__bindgen_ty_1() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 32usize, concat!("Size of: ", stringify!(pf_anchor__bindgen_ty_1)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pf_anchor__bindgen_ty_1)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rbe_left) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pf_anchor__bindgen_ty_1), "::", stringify!(rbe_left) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rbe_right) as usize - ptr as usize }, 8usize, concat!( "Offset of field: ", stringify!(pf_anchor__bindgen_ty_1), "::", stringify!(rbe_right) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rbe_parent) as usize - ptr as usize }, 16usize, concat!( "Offset of field: ", stringify!(pf_anchor__bindgen_ty_1), "::", stringify!(rbe_parent) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rbe_color) as usize - ptr as usize }, 24usize, concat!( "Offset of field: ", stringify!(pf_anchor__bindgen_ty_1), "::", stringify!(rbe_color) ) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pf_anchor__bindgen_ty_2 { pub rbe_left: *mut pf_anchor, pub rbe_right: *mut pf_anchor, pub rbe_parent: *mut pf_anchor, pub rbe_color: ::std::os::raw::c_int, } #[test] fn bindgen_test_layout_pf_anchor__bindgen_ty_2() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 32usize, concat!("Size of: ", stringify!(pf_anchor__bindgen_ty_2)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pf_anchor__bindgen_ty_2)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rbe_left) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pf_anchor__bindgen_ty_2), "::", stringify!(rbe_left) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rbe_right) as usize - ptr as usize }, 8usize, concat!( "Offset of field: ", stringify!(pf_anchor__bindgen_ty_2), "::", stringify!(rbe_right) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rbe_parent) as usize - ptr as usize }, 16usize, concat!( "Offset of field: ", stringify!(pf_anchor__bindgen_ty_2), "::", stringify!(rbe_parent) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rbe_color) as usize - ptr as usize }, 24usize, concat!( "Offset of field: ", stringify!(pf_anchor__bindgen_ty_2), "::", stringify!(rbe_color) ) ); } #[test] fn bindgen_test_layout_pf_anchor() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 1288usize, concat!("Size of: ", stringify!(pf_anchor)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pf_anchor)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).entry_global) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pf_anchor), "::", stringify!(entry_global) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).entry_node) as usize - ptr as usize }, 32usize, concat!("Offset of field: ", stringify!(pf_anchor), "::", stringify!(entry_node)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).parent) as usize - ptr as usize }, 64usize, concat!("Offset of field: ", stringify!(pf_anchor), "::", stringify!(parent)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).children) as usize - ptr as usize }, 72usize, concat!("Offset of field: ", stringify!(pf_anchor), "::", stringify!(children)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).name) as usize - ptr as usize }, 80usize, concat!("Offset of field: ", stringify!(pf_anchor), "::", stringify!(name)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).path) as usize - ptr as usize }, 144usize, concat!("Offset of field: ", stringify!(pf_anchor), "::", stringify!(path)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ruleset) as usize - ptr as usize }, 1168usize, concat!("Offset of field: ", stringify!(pf_anchor), "::", stringify!(ruleset)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).refcnt) as usize - ptr as usize }, 1272usize, concat!("Offset of field: ", stringify!(pf_anchor), "::", stringify!(refcnt)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).match_) as usize - ptr as usize }, 1276usize, concat!("Offset of field: ", stringify!(pf_anchor), "::", stringify!(match_)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ref_) as usize - ptr as usize }, 1280usize, concat!("Offset of field: ", stringify!(pf_anchor), "::", stringify!(ref_)) ); } unsafe extern "C" { pub fn pf_anchor_global_RB_INSERT_COLOR(arg1: *mut pf_anchor_global, arg2: *mut pf_anchor); } unsafe extern "C" { pub fn pf_anchor_global_RB_REMOVE_COLOR(arg1: *mut pf_anchor_global, arg2: *mut pf_anchor, arg3: *mut pf_anchor); } unsafe extern "C" { pub fn pf_anchor_global_RB_REMOVE(arg1: *mut pf_anchor_global, arg2: *mut pf_anchor) -> *mut pf_anchor; } unsafe extern "C" { pub fn pf_anchor_global_RB_INSERT(arg1: *mut pf_anchor_global, arg2: *mut pf_anchor) -> *mut pf_anchor; } unsafe extern "C" { pub fn pf_anchor_global_RB_FIND(arg1: *mut pf_anchor_global, arg2: *mut pf_anchor) -> *mut pf_anchor; } unsafe extern "C" { pub fn pf_anchor_global_RB_NFIND(arg1: *mut pf_anchor_global, arg2: *mut pf_anchor) -> *mut pf_anchor; } unsafe extern "C" { pub fn pf_anchor_global_RB_NEXT(arg1: *mut pf_anchor) -> *mut pf_anchor; } unsafe extern "C" { pub fn pf_anchor_global_RB_PREV(arg1: *mut pf_anchor) -> *mut pf_anchor; } unsafe extern "C" { pub fn pf_anchor_global_RB_MINMAX(arg1: *mut pf_anchor_global, arg2: ::std::os::raw::c_int) -> *mut pf_anchor; } unsafe extern "C" { pub fn pf_anchor_node_RB_INSERT_COLOR(arg1: *mut pf_anchor_node, arg2: *mut pf_anchor); } unsafe extern "C" { pub fn pf_anchor_node_RB_REMOVE_COLOR(arg1: *mut pf_anchor_node, arg2: *mut pf_anchor, arg3: *mut pf_anchor); } unsafe extern "C" { pub fn pf_anchor_node_RB_REMOVE(arg1: *mut pf_anchor_node, arg2: *mut pf_anchor) -> *mut pf_anchor; } unsafe extern "C" { pub fn pf_anchor_node_RB_INSERT(arg1: *mut pf_anchor_node, arg2: *mut pf_anchor) -> *mut pf_anchor; } unsafe extern "C" { pub fn pf_anchor_node_RB_FIND(arg1: *mut pf_anchor_node, arg2: *mut pf_anchor) -> *mut pf_anchor; } unsafe extern "C" { pub fn pf_anchor_node_RB_NFIND(arg1: *mut pf_anchor_node, arg2: *mut pf_anchor) -> *mut pf_anchor; } unsafe extern "C" { pub fn pf_anchor_node_RB_NEXT(arg1: *mut pf_anchor) -> *mut pf_anchor; } unsafe extern "C" { pub fn pf_anchor_node_RB_PREV(arg1: *mut pf_anchor) -> *mut pf_anchor; } unsafe extern "C" { pub fn pf_anchor_node_RB_MINMAX(arg1: *mut pf_anchor_node, arg2: ::std::os::raw::c_int) -> *mut pf_anchor; } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pfr_table { pub pfrt_anchor: [::std::os::raw::c_char; 1024usize], pub pfrt_name: [::std::os::raw::c_char; 32usize], pub pfrt_flags: u_int32_t, pub pfrt_fback: u_int8_t, } #[test] fn bindgen_test_layout_pfr_table() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 1064usize, concat!("Size of: ", stringify!(pfr_table)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(pfr_table)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfrt_anchor) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pfr_table), "::", stringify!(pfrt_anchor) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfrt_name) as usize - ptr as usize }, 1024usize, concat!("Offset of field: ", stringify!(pfr_table), "::", stringify!(pfrt_name)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfrt_flags) as usize - ptr as usize }, 1056usize, concat!("Offset of field: ", stringify!(pfr_table), "::", stringify!(pfrt_flags)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfrt_fback) as usize - ptr as usize }, 1060usize, concat!("Offset of field: ", stringify!(pfr_table), "::", stringify!(pfrt_fback)) ); } pub const PFR_FB_NONE: _bindgen_ty_14 = 0; pub const PFR_FB_MATCH: _bindgen_ty_14 = 1; pub const PFR_FB_ADDED: _bindgen_ty_14 = 2; pub const PFR_FB_DELETED: _bindgen_ty_14 = 3; pub const PFR_FB_CHANGED: _bindgen_ty_14 = 4; pub const PFR_FB_CLEARED: _bindgen_ty_14 = 5; pub const PFR_FB_DUPLICATE: _bindgen_ty_14 = 6; pub const PFR_FB_NOTMATCH: _bindgen_ty_14 = 7; pub const PFR_FB_CONFLICT: _bindgen_ty_14 = 8; pub const PFR_FB_NOCOUNT: _bindgen_ty_14 = 9; pub const PFR_FB_MAX: _bindgen_ty_14 = 10; pub type _bindgen_ty_14 = ::std::os::raw::c_uint; #[repr(C)] #[derive(Copy, Clone)] pub struct pfr_addr { pub pfra_u: pfr_addr__bindgen_ty_1, pub pfra_ifname: [::std::os::raw::c_char; 16usize], pub pfra_states: u_int32_t, pub pfra_weight: u_int16_t, pub pfra_af: u_int8_t, pub pfra_net: u_int8_t, pub pfra_not: u_int8_t, pub pfra_fback: u_int8_t, pub pfra_type: u_int8_t, pub pad: [u_int8_t; 7usize], } #[repr(C)] #[derive(Copy, Clone)] pub union pfr_addr__bindgen_ty_1 { pub _pfra_ip4addr: in_addr, pub _pfra_ip6addr: in6_addr, } #[test] fn bindgen_test_layout_pfr_addr__bindgen_ty_1() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 16usize, concat!("Size of: ", stringify!(pfr_addr__bindgen_ty_1)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(pfr_addr__bindgen_ty_1)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr)._pfra_ip4addr) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pfr_addr__bindgen_ty_1), "::", stringify!(_pfra_ip4addr) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr)._pfra_ip6addr) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pfr_addr__bindgen_ty_1), "::", stringify!(_pfra_ip6addr) ) ); } #[test] fn bindgen_test_layout_pfr_addr() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 52usize, concat!("Size of: ", stringify!(pfr_addr)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(pfr_addr)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfra_u) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(pfr_addr), "::", stringify!(pfra_u)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfra_ifname) as usize - ptr as usize }, 16usize, concat!("Offset of field: ", stringify!(pfr_addr), "::", stringify!(pfra_ifname)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfra_states) as usize - ptr as usize }, 32usize, concat!("Offset of field: ", stringify!(pfr_addr), "::", stringify!(pfra_states)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfra_weight) as usize - ptr as usize }, 36usize, concat!("Offset of field: ", stringify!(pfr_addr), "::", stringify!(pfra_weight)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfra_af) as usize - ptr as usize }, 38usize, concat!("Offset of field: ", stringify!(pfr_addr), "::", stringify!(pfra_af)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfra_net) as usize - ptr as usize }, 39usize, concat!("Offset of field: ", stringify!(pfr_addr), "::", stringify!(pfra_net)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfra_not) as usize - ptr as usize }, 40usize, concat!("Offset of field: ", stringify!(pfr_addr), "::", stringify!(pfra_not)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfra_fback) as usize - ptr as usize }, 41usize, concat!("Offset of field: ", stringify!(pfr_addr), "::", stringify!(pfra_fback)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfra_type) as usize - ptr as usize }, 42usize, concat!("Offset of field: ", stringify!(pfr_addr), "::", stringify!(pfra_type)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pad) as usize - ptr as usize }, 43usize, concat!("Offset of field: ", stringify!(pfr_addr), "::", stringify!(pad)) ); } pub const PFR_DIR_IN: _bindgen_ty_15 = 0; pub const PFR_DIR_OUT: _bindgen_ty_15 = 1; pub const PFR_DIR_MAX: _bindgen_ty_15 = 2; pub type _bindgen_ty_15 = ::std::os::raw::c_uint; pub const PFR_OP_BLOCK: _bindgen_ty_16 = 0; pub const PFR_OP_MATCH: _bindgen_ty_16 = 1; pub const PFR_OP_PASS: _bindgen_ty_16 = 2; pub const PFR_OP_ADDR_MAX: _bindgen_ty_16 = 3; pub const PFR_OP_TABLE_MAX: _bindgen_ty_16 = 4; pub type _bindgen_ty_16 = ::std::os::raw::c_uint; #[repr(C)] #[derive(Copy, Clone)] pub struct pfr_astats { pub pfras_a: pfr_addr, pub pfras_packets: [[u_int64_t; 3usize]; 2usize], pub pfras_bytes: [[u_int64_t; 3usize]; 2usize], pub pfras_tzero: time_t, } #[test] fn bindgen_test_layout_pfr_astats() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 160usize, concat!("Size of: ", stringify!(pfr_astats)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pfr_astats)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfras_a) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(pfr_astats), "::", stringify!(pfras_a)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfras_packets) as usize - ptr as usize }, 56usize, concat!( "Offset of field: ", stringify!(pfr_astats), "::", stringify!(pfras_packets) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfras_bytes) as usize - ptr as usize }, 104usize, concat!( "Offset of field: ", stringify!(pfr_astats), "::", stringify!(pfras_bytes) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfras_tzero) as usize - ptr as usize }, 152usize, concat!( "Offset of field: ", stringify!(pfr_astats), "::", stringify!(pfras_tzero) ) ); } pub const PFR_REFCNT_RULE: _bindgen_ty_17 = 0; pub const PFR_REFCNT_ANCHOR: _bindgen_ty_17 = 1; pub const PFR_REFCNT_MAX: _bindgen_ty_17 = 2; pub type _bindgen_ty_17 = ::std::os::raw::c_uint; #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pfr_tstats { pub pfrts_t: pfr_table, pub pfrts_packets: [[u_int64_t; 4usize]; 2usize], pub pfrts_bytes: [[u_int64_t; 4usize]; 2usize], pub pfrts_match: u_int64_t, pub pfrts_nomatch: u_int64_t, pub pfrts_tzero: time_t, pub pfrts_cnt: ::std::os::raw::c_int, pub pfrts_refcnt: [::std::os::raw::c_int; 2usize], } #[test] fn bindgen_test_layout_pfr_tstats() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 1232usize, concat!("Size of: ", stringify!(pfr_tstats)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pfr_tstats)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfrts_t) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(pfr_tstats), "::", stringify!(pfrts_t)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfrts_packets) as usize - ptr as usize }, 1064usize, concat!( "Offset of field: ", stringify!(pfr_tstats), "::", stringify!(pfrts_packets) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfrts_bytes) as usize - ptr as usize }, 1128usize, concat!( "Offset of field: ", stringify!(pfr_tstats), "::", stringify!(pfrts_bytes) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfrts_match) as usize - ptr as usize }, 1192usize, concat!( "Offset of field: ", stringify!(pfr_tstats), "::", stringify!(pfrts_match) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfrts_nomatch) as usize - ptr as usize }, 1200usize, concat!( "Offset of field: ", stringify!(pfr_tstats), "::", stringify!(pfrts_nomatch) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfrts_tzero) as usize - ptr as usize }, 1208usize, concat!( "Offset of field: ", stringify!(pfr_tstats), "::", stringify!(pfrts_tzero) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfrts_cnt) as usize - ptr as usize }, 1216usize, concat!("Offset of field: ", stringify!(pfr_tstats), "::", stringify!(pfrts_cnt)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfrts_refcnt) as usize - ptr as usize }, 1220usize, concat!( "Offset of field: ", stringify!(pfr_tstats), "::", stringify!(pfrts_refcnt) ) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pfr_kcounters { pub pfrkc_packets: [[u_int64_t; 3usize]; 2usize], pub pfrkc_bytes: [[u_int64_t; 3usize]; 2usize], pub states: u_int64_t, } #[test] fn bindgen_test_layout_pfr_kcounters() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 104usize, concat!("Size of: ", stringify!(pfr_kcounters)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pfr_kcounters)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfrkc_packets) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pfr_kcounters), "::", stringify!(pfrkc_packets) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfrkc_bytes) as usize - ptr as usize }, 48usize, concat!( "Offset of field: ", stringify!(pfr_kcounters), "::", stringify!(pfrkc_bytes) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).states) as usize - ptr as usize }, 96usize, concat!("Offset of field: ", stringify!(pfr_kcounters), "::", stringify!(states)) ); } #[repr(C)] #[derive(Copy, Clone)] pub union pfsockaddr_union { pub sa: sockaddr, pub sin: sockaddr_in, pub sin6: sockaddr_in6, } #[test] fn bindgen_test_layout_pfsockaddr_union() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 28usize, concat!("Size of: ", stringify!(pfsockaddr_union)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(pfsockaddr_union)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).sa) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(pfsockaddr_union), "::", stringify!(sa)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).sin) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(pfsockaddr_union), "::", stringify!(sin)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).sin6) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pfsockaddr_union), "::", stringify!(sin6) ) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pfr_kentryworkq { pub slh_first: *mut pfr_kentry, } #[test] fn bindgen_test_layout_pfr_kentryworkq() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 8usize, concat!("Size of: ", stringify!(pfr_kentryworkq)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pfr_kentryworkq)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).slh_first) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pfr_kentryworkq), "::", stringify!(slh_first) ) ); } #[repr(C)] #[derive(Copy, Clone)] pub struct _pfr_kentry { pub _pfrke_node: [radix_node; 2usize], pub _pfrke_sa: pfsockaddr_union, pub _pfrke_workq: _pfr_kentry__bindgen_ty_1, pub _pfrke_ioq: _pfr_kentry__bindgen_ty_2, pub _pfrke_counters: *mut pfr_kcounters, pub _pfrke_tzero: time_t, pub _pfrke_af: u_int8_t, pub _pfrke_net: u_int8_t, pub _pfrke_flags: u_int8_t, pub _pfrke_type: u_int8_t, pub _pfrke_fb: u_int8_t, } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct _pfr_kentry__bindgen_ty_1 { pub sle_next: *mut pfr_kentry, } #[test] fn bindgen_test_layout__pfr_kentry__bindgen_ty_1() { const UNINIT: ::std::mem::MaybeUninit<_pfr_kentry__bindgen_ty_1> = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::<_pfr_kentry__bindgen_ty_1>(), 8usize, concat!("Size of: ", stringify!(_pfr_kentry__bindgen_ty_1)) ); assert_eq!( ::std::mem::align_of::<_pfr_kentry__bindgen_ty_1>(), 8usize, concat!("Alignment of ", stringify!(_pfr_kentry__bindgen_ty_1)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).sle_next) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(_pfr_kentry__bindgen_ty_1), "::", stringify!(sle_next) ) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct _pfr_kentry__bindgen_ty_2 { pub sle_next: *mut pfr_kentry, } #[test] fn bindgen_test_layout__pfr_kentry__bindgen_ty_2() { const UNINIT: ::std::mem::MaybeUninit<_pfr_kentry__bindgen_ty_2> = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::<_pfr_kentry__bindgen_ty_2>(), 8usize, concat!("Size of: ", stringify!(_pfr_kentry__bindgen_ty_2)) ); assert_eq!( ::std::mem::align_of::<_pfr_kentry__bindgen_ty_2>(), 8usize, concat!("Alignment of ", stringify!(_pfr_kentry__bindgen_ty_2)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).sle_next) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(_pfr_kentry__bindgen_ty_2), "::", stringify!(sle_next) ) ); } #[test] fn bindgen_test_layout__pfr_kentry() { const UNINIT: ::std::mem::MaybeUninit<_pfr_kentry> = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::<_pfr_kentry>(), 168usize, concat!("Size of: ", stringify!(_pfr_kentry)) ); assert_eq!( ::std::mem::align_of::<_pfr_kentry>(), 8usize, concat!("Alignment of ", stringify!(_pfr_kentry)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr)._pfrke_node) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(_pfr_kentry), "::", stringify!(_pfrke_node) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr)._pfrke_sa) as usize - ptr as usize }, 96usize, concat!( "Offset of field: ", stringify!(_pfr_kentry), "::", stringify!(_pfrke_sa) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr)._pfrke_workq) as usize - ptr as usize }, 128usize, concat!( "Offset of field: ", stringify!(_pfr_kentry), "::", stringify!(_pfrke_workq) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr)._pfrke_ioq) as usize - ptr as usize }, 136usize, concat!( "Offset of field: ", stringify!(_pfr_kentry), "::", stringify!(_pfrke_ioq) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr)._pfrke_counters) as usize - ptr as usize }, 144usize, concat!( "Offset of field: ", stringify!(_pfr_kentry), "::", stringify!(_pfrke_counters) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr)._pfrke_tzero) as usize - ptr as usize }, 152usize, concat!( "Offset of field: ", stringify!(_pfr_kentry), "::", stringify!(_pfrke_tzero) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr)._pfrke_af) as usize - ptr as usize }, 160usize, concat!( "Offset of field: ", stringify!(_pfr_kentry), "::", stringify!(_pfrke_af) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr)._pfrke_net) as usize - ptr as usize }, 161usize, concat!( "Offset of field: ", stringify!(_pfr_kentry), "::", stringify!(_pfrke_net) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr)._pfrke_flags) as usize - ptr as usize }, 162usize, concat!( "Offset of field: ", stringify!(_pfr_kentry), "::", stringify!(_pfrke_flags) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr)._pfrke_type) as usize - ptr as usize }, 163usize, concat!( "Offset of field: ", stringify!(_pfr_kentry), "::", stringify!(_pfrke_type) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr)._pfrke_fb) as usize - ptr as usize }, 164usize, concat!( "Offset of field: ", stringify!(_pfr_kentry), "::", stringify!(_pfrke_fb) ) ); } pub const PFRKE_PLAIN: _bindgen_ty_18 = 0; pub const PFRKE_ROUTE: _bindgen_ty_18 = 1; pub const PFRKE_COST: _bindgen_ty_18 = 2; pub const PFRKE_MAX: _bindgen_ty_18 = 3; pub type _bindgen_ty_18 = ::std::os::raw::c_uint; #[repr(C)] #[derive(Copy, Clone)] pub struct pfr_kentry { pub u: pfr_kentry__bindgen_ty_1, } #[repr(C)] #[derive(Copy, Clone)] pub union pfr_kentry__bindgen_ty_1 { pub _ke: _pfr_kentry, } #[test] fn bindgen_test_layout_pfr_kentry__bindgen_ty_1() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 168usize, concat!("Size of: ", stringify!(pfr_kentry__bindgen_ty_1)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pfr_kentry__bindgen_ty_1)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr)._ke) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pfr_kentry__bindgen_ty_1), "::", stringify!(_ke) ) ); } #[test] fn bindgen_test_layout_pfr_kentry() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 168usize, concat!("Size of: ", stringify!(pfr_kentry)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pfr_kentry)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).u) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(pfr_kentry), "::", stringify!(u)) ); } #[repr(C)] #[derive(Copy, Clone)] pub struct pfr_kentry_route { pub u: pfr_kentry_route__bindgen_ty_1, pub kif: *mut pfi_kif, pub ifname: [::std::os::raw::c_char; 16usize], } #[repr(C)] #[derive(Copy, Clone)] pub union pfr_kentry_route__bindgen_ty_1 { pub _ke: _pfr_kentry, } #[test] fn bindgen_test_layout_pfr_kentry_route__bindgen_ty_1() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 168usize, concat!("Size of: ", stringify!(pfr_kentry_route__bindgen_ty_1)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pfr_kentry_route__bindgen_ty_1)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr)._ke) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pfr_kentry_route__bindgen_ty_1), "::", stringify!(_ke) ) ); } #[test] fn bindgen_test_layout_pfr_kentry_route() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 192usize, concat!("Size of: ", stringify!(pfr_kentry_route)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pfr_kentry_route)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).u) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(pfr_kentry_route), "::", stringify!(u)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).kif) as usize - ptr as usize }, 168usize, concat!("Offset of field: ", stringify!(pfr_kentry_route), "::", stringify!(kif)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifname) as usize - ptr as usize }, 176usize, concat!( "Offset of field: ", stringify!(pfr_kentry_route), "::", stringify!(ifname) ) ); } #[repr(C)] #[derive(Copy, Clone)] pub struct pfr_kentry_cost { pub u: pfr_kentry_cost__bindgen_ty_1, pub kif: *mut pfi_kif, pub ifname: [::std::os::raw::c_char; 16usize], pub weight: u_int16_t, } #[repr(C)] #[derive(Copy, Clone)] pub union pfr_kentry_cost__bindgen_ty_1 { pub _ke: _pfr_kentry, } #[test] fn bindgen_test_layout_pfr_kentry_cost__bindgen_ty_1() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 168usize, concat!("Size of: ", stringify!(pfr_kentry_cost__bindgen_ty_1)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pfr_kentry_cost__bindgen_ty_1)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr)._ke) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pfr_kentry_cost__bindgen_ty_1), "::", stringify!(_ke) ) ); } #[test] fn bindgen_test_layout_pfr_kentry_cost() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 200usize, concat!("Size of: ", stringify!(pfr_kentry_cost)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pfr_kentry_cost)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).u) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(pfr_kentry_cost), "::", stringify!(u)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).kif) as usize - ptr as usize }, 168usize, concat!("Offset of field: ", stringify!(pfr_kentry_cost), "::", stringify!(kif)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifname) as usize - ptr as usize }, 176usize, concat!( "Offset of field: ", stringify!(pfr_kentry_cost), "::", stringify!(ifname) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).weight) as usize - ptr as usize }, 192usize, concat!( "Offset of field: ", stringify!(pfr_kentry_cost), "::", stringify!(weight) ) ); } #[repr(C)] #[derive(Copy, Clone)] pub struct pfr_kentry_all { pub u: pfr_kentry_all__bindgen_ty_1, } #[repr(C)] #[derive(Copy, Clone)] pub union pfr_kentry_all__bindgen_ty_1 { pub _ke: _pfr_kentry, pub kr: pfr_kentry_route, pub kc: pfr_kentry_cost, } #[test] fn bindgen_test_layout_pfr_kentry_all__bindgen_ty_1() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 200usize, concat!("Size of: ", stringify!(pfr_kentry_all__bindgen_ty_1)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pfr_kentry_all__bindgen_ty_1)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr)._ke) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pfr_kentry_all__bindgen_ty_1), "::", stringify!(_ke) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).kr) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pfr_kentry_all__bindgen_ty_1), "::", stringify!(kr) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).kc) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pfr_kentry_all__bindgen_ty_1), "::", stringify!(kc) ) ); } #[test] fn bindgen_test_layout_pfr_kentry_all() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 200usize, concat!("Size of: ", stringify!(pfr_kentry_all)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pfr_kentry_all)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).u) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(pfr_kentry_all), "::", stringify!(u)) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pfr_ktableworkq { pub slh_first: *mut pfr_ktable, } #[test] fn bindgen_test_layout_pfr_ktableworkq() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 8usize, concat!("Size of: ", stringify!(pfr_ktableworkq)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pfr_ktableworkq)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).slh_first) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pfr_ktableworkq), "::", stringify!(slh_first) ) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pfr_ktablehead { pub rbh_root: *mut pfr_ktable, } #[test] fn bindgen_test_layout_pfr_ktablehead() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 8usize, concat!("Size of: ", stringify!(pfr_ktablehead)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pfr_ktablehead)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rbh_root) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pfr_ktablehead), "::", stringify!(rbh_root) ) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pfr_ktable { pub pfrkt_ts: pfr_tstats, pub pfrkt_tree: pfr_ktable__bindgen_ty_1, pub pfrkt_workq: pfr_ktable__bindgen_ty_2, pub pfrkt_ip4: *mut radix_node_head, pub pfrkt_ip6: *mut radix_node_head, pub pfrkt_shadow: *mut pfr_ktable, pub pfrkt_root: *mut pfr_ktable, pub pfrkt_rs: *mut pf_ruleset, pub pfrkt_larg: ::std::os::raw::c_long, pub pfrkt_nflags: ::std::os::raw::c_int, pub pfrkt_refcntcost: u_int64_t, pub pfrkt_gcdweight: u_int16_t, pub pfrkt_maxweight: u_int16_t, } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pfr_ktable__bindgen_ty_1 { pub rbe_left: *mut pfr_ktable, pub rbe_right: *mut pfr_ktable, pub rbe_parent: *mut pfr_ktable, pub rbe_color: ::std::os::raw::c_int, } #[test] fn bindgen_test_layout_pfr_ktable__bindgen_ty_1() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 32usize, concat!("Size of: ", stringify!(pfr_ktable__bindgen_ty_1)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pfr_ktable__bindgen_ty_1)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rbe_left) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pfr_ktable__bindgen_ty_1), "::", stringify!(rbe_left) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rbe_right) as usize - ptr as usize }, 8usize, concat!( "Offset of field: ", stringify!(pfr_ktable__bindgen_ty_1), "::", stringify!(rbe_right) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rbe_parent) as usize - ptr as usize }, 16usize, concat!( "Offset of field: ", stringify!(pfr_ktable__bindgen_ty_1), "::", stringify!(rbe_parent) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rbe_color) as usize - ptr as usize }, 24usize, concat!( "Offset of field: ", stringify!(pfr_ktable__bindgen_ty_1), "::", stringify!(rbe_color) ) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pfr_ktable__bindgen_ty_2 { pub sle_next: *mut pfr_ktable, } #[test] fn bindgen_test_layout_pfr_ktable__bindgen_ty_2() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 8usize, concat!("Size of: ", stringify!(pfr_ktable__bindgen_ty_2)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pfr_ktable__bindgen_ty_2)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).sle_next) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pfr_ktable__bindgen_ty_2), "::", stringify!(sle_next) ) ); } #[test] fn bindgen_test_layout_pfr_ktable() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 1344usize, concat!("Size of: ", stringify!(pfr_ktable)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pfr_ktable)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfrkt_ts) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(pfr_ktable), "::", stringify!(pfrkt_ts)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfrkt_tree) as usize - ptr as usize }, 1232usize, concat!( "Offset of field: ", stringify!(pfr_ktable), "::", stringify!(pfrkt_tree) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfrkt_workq) as usize - ptr as usize }, 1264usize, concat!( "Offset of field: ", stringify!(pfr_ktable), "::", stringify!(pfrkt_workq) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfrkt_ip4) as usize - ptr as usize }, 1272usize, concat!("Offset of field: ", stringify!(pfr_ktable), "::", stringify!(pfrkt_ip4)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfrkt_ip6) as usize - ptr as usize }, 1280usize, concat!("Offset of field: ", stringify!(pfr_ktable), "::", stringify!(pfrkt_ip6)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfrkt_shadow) as usize - ptr as usize }, 1288usize, concat!( "Offset of field: ", stringify!(pfr_ktable), "::", stringify!(pfrkt_shadow) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfrkt_root) as usize - ptr as usize }, 1296usize, concat!( "Offset of field: ", stringify!(pfr_ktable), "::", stringify!(pfrkt_root) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfrkt_rs) as usize - ptr as usize }, 1304usize, concat!("Offset of field: ", stringify!(pfr_ktable), "::", stringify!(pfrkt_rs)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfrkt_larg) as usize - ptr as usize }, 1312usize, concat!( "Offset of field: ", stringify!(pfr_ktable), "::", stringify!(pfrkt_larg) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfrkt_nflags) as usize - ptr as usize }, 1320usize, concat!( "Offset of field: ", stringify!(pfr_ktable), "::", stringify!(pfrkt_nflags) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfrkt_refcntcost) as usize - ptr as usize }, 1328usize, concat!( "Offset of field: ", stringify!(pfr_ktable), "::", stringify!(pfrkt_refcntcost) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfrkt_gcdweight) as usize - ptr as usize }, 1336usize, concat!( "Offset of field: ", stringify!(pfr_ktable), "::", stringify!(pfrkt_gcdweight) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfrkt_maxweight) as usize - ptr as usize }, 1338usize, concat!( "Offset of field: ", stringify!(pfr_ktable), "::", stringify!(pfrkt_maxweight) ) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pf_state_tree_ext_gwy { pub rbh_root: *mut pf_state_key, } #[test] fn bindgen_test_layout_pf_state_tree_ext_gwy() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 8usize, concat!("Size of: ", stringify!(pf_state_tree_ext_gwy)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pf_state_tree_ext_gwy)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rbh_root) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pf_state_tree_ext_gwy), "::", stringify!(rbh_root) ) ); } unsafe extern "C" { pub fn pf_state_tree_ext_gwy_RB_INSERT_COLOR(arg1: *mut pf_state_tree_ext_gwy, arg2: *mut pf_state_key); } unsafe extern "C" { pub fn pf_state_tree_ext_gwy_RB_REMOVE_COLOR( arg1: *mut pf_state_tree_ext_gwy, arg2: *mut pf_state_key, arg3: *mut pf_state_key, ); } unsafe extern "C" { pub fn pf_state_tree_ext_gwy_RB_REMOVE( arg1: *mut pf_state_tree_ext_gwy, arg2: *mut pf_state_key, ) -> *mut pf_state_key; } unsafe extern "C" { pub fn pf_state_tree_ext_gwy_RB_INSERT( arg1: *mut pf_state_tree_ext_gwy, arg2: *mut pf_state_key, ) -> *mut pf_state_key; } unsafe extern "C" { pub fn pf_state_tree_ext_gwy_RB_FIND( arg1: *mut pf_state_tree_ext_gwy, arg2: *mut pf_state_key, ) -> *mut pf_state_key; } unsafe extern "C" { pub fn pf_state_tree_ext_gwy_RB_NFIND( arg1: *mut pf_state_tree_ext_gwy, arg2: *mut pf_state_key, ) -> *mut pf_state_key; } unsafe extern "C" { pub fn pf_state_tree_ext_gwy_RB_NEXT(arg1: *mut pf_state_key) -> *mut pf_state_key; } unsafe extern "C" { pub fn pf_state_tree_ext_gwy_RB_PREV(arg1: *mut pf_state_key) -> *mut pf_state_key; } unsafe extern "C" { pub fn pf_state_tree_ext_gwy_RB_MINMAX( arg1: *mut pf_state_tree_ext_gwy, arg2: ::std::os::raw::c_int, ) -> *mut pf_state_key; } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pfi_ifhead { pub rbh_root: *mut pfi_kif, } #[test] fn bindgen_test_layout_pfi_ifhead() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 8usize, concat!("Size of: ", stringify!(pfi_ifhead)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pfi_ifhead)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rbh_root) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(pfi_ifhead), "::", stringify!(rbh_root)) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pf_state_tree { _unused: [u8; 0], } unsafe extern "C" { pub static mut pf_statetbl: pf_state_tree; } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pfi_kif_cmp { pub pfik_name: [::std::os::raw::c_char; 16usize], } #[test] fn bindgen_test_layout_pfi_kif_cmp() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 16usize, concat!("Size of: ", stringify!(pfi_kif_cmp)) ); assert_eq!( ::std::mem::align_of::(), 1usize, concat!("Alignment of ", stringify!(pfi_kif_cmp)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfik_name) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pfi_kif_cmp), "::", stringify!(pfik_name) ) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct ifnet { _unused: [u8; 0], } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct ifg_group { _unused: [u8; 0], } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pfi_kif { pub pfik_name: [::std::os::raw::c_char; 16usize], pub pfik_tree: pfi_kif__bindgen_ty_1, pub pfik_packets: [[[u_int64_t; 2usize]; 2usize]; 2usize], pub pfik_bytes: [[[u_int64_t; 2usize]; 2usize]; 2usize], pub pfik_tzero: time_t, pub pfik_flags: ::std::os::raw::c_int, pub pfik_flags_new: ::std::os::raw::c_int, pub pfik_ah_cookie: *mut ::std::os::raw::c_void, pub pfik_ifp: *mut ifnet, pub pfik_group: *mut ifg_group, pub pfik_states: ::std::os::raw::c_int, pub pfik_rules: ::std::os::raw::c_int, pub pfik_routes: ::std::os::raw::c_int, pub pfik_srcnodes: ::std::os::raw::c_int, pub pfik_flagrefs: ::std::os::raw::c_int, pub pfik_dynaddrs: pfi_kif__bindgen_ty_2, } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pfi_kif__bindgen_ty_1 { pub rbe_left: *mut pfi_kif, pub rbe_right: *mut pfi_kif, pub rbe_parent: *mut pfi_kif, pub rbe_color: ::std::os::raw::c_int, } #[test] fn bindgen_test_layout_pfi_kif__bindgen_ty_1() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 32usize, concat!("Size of: ", stringify!(pfi_kif__bindgen_ty_1)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pfi_kif__bindgen_ty_1)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rbe_left) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pfi_kif__bindgen_ty_1), "::", stringify!(rbe_left) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rbe_right) as usize - ptr as usize }, 8usize, concat!( "Offset of field: ", stringify!(pfi_kif__bindgen_ty_1), "::", stringify!(rbe_right) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rbe_parent) as usize - ptr as usize }, 16usize, concat!( "Offset of field: ", stringify!(pfi_kif__bindgen_ty_1), "::", stringify!(rbe_parent) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rbe_color) as usize - ptr as usize }, 24usize, concat!( "Offset of field: ", stringify!(pfi_kif__bindgen_ty_1), "::", stringify!(rbe_color) ) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pfi_kif__bindgen_ty_2 { pub tqh_first: *mut pfi_dynaddr, pub tqh_last: *mut *mut pfi_dynaddr, } #[test] fn bindgen_test_layout_pfi_kif__bindgen_ty_2() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 16usize, concat!("Size of: ", stringify!(pfi_kif__bindgen_ty_2)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pfi_kif__bindgen_ty_2)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).tqh_first) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pfi_kif__bindgen_ty_2), "::", stringify!(tqh_first) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).tqh_last) as usize - ptr as usize }, 8usize, concat!( "Offset of field: ", stringify!(pfi_kif__bindgen_ty_2), "::", stringify!(tqh_last) ) ); } #[test] fn bindgen_test_layout_pfi_kif() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 256usize, concat!("Size of: ", stringify!(pfi_kif)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pfi_kif)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfik_name) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(pfi_kif), "::", stringify!(pfik_name)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfik_tree) as usize - ptr as usize }, 16usize, concat!("Offset of field: ", stringify!(pfi_kif), "::", stringify!(pfik_tree)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfik_packets) as usize - ptr as usize }, 48usize, concat!("Offset of field: ", stringify!(pfi_kif), "::", stringify!(pfik_packets)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfik_bytes) as usize - ptr as usize }, 112usize, concat!("Offset of field: ", stringify!(pfi_kif), "::", stringify!(pfik_bytes)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfik_tzero) as usize - ptr as usize }, 176usize, concat!("Offset of field: ", stringify!(pfi_kif), "::", stringify!(pfik_tzero)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfik_flags) as usize - ptr as usize }, 184usize, concat!("Offset of field: ", stringify!(pfi_kif), "::", stringify!(pfik_flags)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfik_flags_new) as usize - ptr as usize }, 188usize, concat!( "Offset of field: ", stringify!(pfi_kif), "::", stringify!(pfik_flags_new) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfik_ah_cookie) as usize - ptr as usize }, 192usize, concat!( "Offset of field: ", stringify!(pfi_kif), "::", stringify!(pfik_ah_cookie) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfik_ifp) as usize - ptr as usize }, 200usize, concat!("Offset of field: ", stringify!(pfi_kif), "::", stringify!(pfik_ifp)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfik_group) as usize - ptr as usize }, 208usize, concat!("Offset of field: ", stringify!(pfi_kif), "::", stringify!(pfik_group)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfik_states) as usize - ptr as usize }, 216usize, concat!("Offset of field: ", stringify!(pfi_kif), "::", stringify!(pfik_states)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfik_rules) as usize - ptr as usize }, 220usize, concat!("Offset of field: ", stringify!(pfi_kif), "::", stringify!(pfik_rules)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfik_routes) as usize - ptr as usize }, 224usize, concat!("Offset of field: ", stringify!(pfi_kif), "::", stringify!(pfik_routes)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfik_srcnodes) as usize - ptr as usize }, 228usize, concat!( "Offset of field: ", stringify!(pfi_kif), "::", stringify!(pfik_srcnodes) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfik_flagrefs) as usize - ptr as usize }, 232usize, concat!( "Offset of field: ", stringify!(pfi_kif), "::", stringify!(pfik_flagrefs) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfik_dynaddrs) as usize - ptr as usize }, 240usize, concat!( "Offset of field: ", stringify!(pfi_kif), "::", stringify!(pfik_dynaddrs) ) ); } pub const pfi_kif_refs_PFI_KIF_REF_NONE: pfi_kif_refs = 0; pub const pfi_kif_refs_PFI_KIF_REF_STATE: pfi_kif_refs = 1; pub const pfi_kif_refs_PFI_KIF_REF_RULE: pfi_kif_refs = 2; pub const pfi_kif_refs_PFI_KIF_REF_ROUTE: pfi_kif_refs = 3; pub const pfi_kif_refs_PFI_KIF_REF_SRCNODE: pfi_kif_refs = 4; pub const pfi_kif_refs_PFI_KIF_REF_FLAG: pfi_kif_refs = 5; pub type pfi_kif_refs = ::std::os::raw::c_uint; #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pf_status { pub counters: [u_int64_t; 17usize], pub lcounters: [u_int64_t; 10usize], pub fcounters: [u_int64_t; 3usize], pub scounters: [u_int64_t; 3usize], pub pcounters: [[[u_int64_t; 3usize]; 2usize]; 2usize], pub bcounters: [[u_int64_t; 2usize]; 2usize], pub stateid: u_int64_t, pub syncookies_inflight: [u_int64_t; 2usize], pub since: time_t, pub running: u_int32_t, pub states: u_int32_t, pub states_halfopen: u_int32_t, pub src_nodes: u_int32_t, pub debug: u_int32_t, pub hostid: u_int32_t, pub reass: u_int32_t, pub syncookies_active: u_int8_t, pub syncookies_mode: u_int8_t, pub pad: [u_int8_t; 2usize], pub ifname: [::std::os::raw::c_char; 16usize], pub pf_chksum: [u_int8_t; 16usize], } #[test] fn bindgen_test_layout_pf_status() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 488usize, concat!("Size of: ", stringify!(pf_status)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pf_status)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).counters) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(pf_status), "::", stringify!(counters)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).lcounters) as usize - ptr as usize }, 136usize, concat!("Offset of field: ", stringify!(pf_status), "::", stringify!(lcounters)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).fcounters) as usize - ptr as usize }, 216usize, concat!("Offset of field: ", stringify!(pf_status), "::", stringify!(fcounters)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).scounters) as usize - ptr as usize }, 240usize, concat!("Offset of field: ", stringify!(pf_status), "::", stringify!(scounters)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pcounters) as usize - ptr as usize }, 264usize, concat!("Offset of field: ", stringify!(pf_status), "::", stringify!(pcounters)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).bcounters) as usize - ptr as usize }, 360usize, concat!("Offset of field: ", stringify!(pf_status), "::", stringify!(bcounters)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).stateid) as usize - ptr as usize }, 392usize, concat!("Offset of field: ", stringify!(pf_status), "::", stringify!(stateid)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).syncookies_inflight) as usize - ptr as usize }, 400usize, concat!( "Offset of field: ", stringify!(pf_status), "::", stringify!(syncookies_inflight) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).since) as usize - ptr as usize }, 416usize, concat!("Offset of field: ", stringify!(pf_status), "::", stringify!(since)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).running) as usize - ptr as usize }, 424usize, concat!("Offset of field: ", stringify!(pf_status), "::", stringify!(running)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).states) as usize - ptr as usize }, 428usize, concat!("Offset of field: ", stringify!(pf_status), "::", stringify!(states)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).states_halfopen) as usize - ptr as usize }, 432usize, concat!( "Offset of field: ", stringify!(pf_status), "::", stringify!(states_halfopen) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).src_nodes) as usize - ptr as usize }, 436usize, concat!("Offset of field: ", stringify!(pf_status), "::", stringify!(src_nodes)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).debug) as usize - ptr as usize }, 440usize, concat!("Offset of field: ", stringify!(pf_status), "::", stringify!(debug)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).hostid) as usize - ptr as usize }, 444usize, concat!("Offset of field: ", stringify!(pf_status), "::", stringify!(hostid)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).reass) as usize - ptr as usize }, 448usize, concat!("Offset of field: ", stringify!(pf_status), "::", stringify!(reass)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).syncookies_active) as usize - ptr as usize }, 452usize, concat!( "Offset of field: ", stringify!(pf_status), "::", stringify!(syncookies_active) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).syncookies_mode) as usize - ptr as usize }, 453usize, concat!( "Offset of field: ", stringify!(pf_status), "::", stringify!(syncookies_mode) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pad) as usize - ptr as usize }, 454usize, concat!("Offset of field: ", stringify!(pf_status), "::", stringify!(pad)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifname) as usize - ptr as usize }, 456usize, concat!("Offset of field: ", stringify!(pf_status), "::", stringify!(ifname)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pf_chksum) as usize - ptr as usize }, 472usize, concat!("Offset of field: ", stringify!(pf_status), "::", stringify!(pf_chksum)) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pf_queue_bwspec { pub absolute: u_int, pub percent: u_int, } #[test] fn bindgen_test_layout_pf_queue_bwspec() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 8usize, concat!("Size of: ", stringify!(pf_queue_bwspec)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(pf_queue_bwspec)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).absolute) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pf_queue_bwspec), "::", stringify!(absolute) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).percent) as usize - ptr as usize }, 4usize, concat!( "Offset of field: ", stringify!(pf_queue_bwspec), "::", stringify!(percent) ) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pf_queue_scspec { pub m1: pf_queue_bwspec, pub m2: pf_queue_bwspec, pub d: u_int, } #[test] fn bindgen_test_layout_pf_queue_scspec() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 20usize, concat!("Size of: ", stringify!(pf_queue_scspec)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(pf_queue_scspec)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).m1) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(pf_queue_scspec), "::", stringify!(m1)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).m2) as usize - ptr as usize }, 8usize, concat!("Offset of field: ", stringify!(pf_queue_scspec), "::", stringify!(m2)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).d) as usize - ptr as usize }, 16usize, concat!("Offset of field: ", stringify!(pf_queue_scspec), "::", stringify!(d)) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pf_queue_fqspec { pub flows: u_int, pub quantum: u_int, pub target: u_int, pub interval: u_int, } #[test] fn bindgen_test_layout_pf_queue_fqspec() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 16usize, concat!("Size of: ", stringify!(pf_queue_fqspec)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(pf_queue_fqspec)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).flows) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pf_queue_fqspec), "::", stringify!(flows) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).quantum) as usize - ptr as usize }, 4usize, concat!( "Offset of field: ", stringify!(pf_queue_fqspec), "::", stringify!(quantum) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).target) as usize - ptr as usize }, 8usize, concat!( "Offset of field: ", stringify!(pf_queue_fqspec), "::", stringify!(target) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).interval) as usize - ptr as usize }, 12usize, concat!( "Offset of field: ", stringify!(pf_queue_fqspec), "::", stringify!(interval) ) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pf_queuespec { pub entries: pf_queuespec__bindgen_ty_1, pub qname: [::std::os::raw::c_char; 64usize], pub parent: [::std::os::raw::c_char; 64usize], pub ifname: [::std::os::raw::c_char; 16usize], pub realtime: pf_queue_scspec, pub linkshare: pf_queue_scspec, pub upperlimit: pf_queue_scspec, pub flowqueue: pf_queue_fqspec, pub kif: *mut pfi_kif, pub flags: u_int, pub qlimit: u_int, pub qid: u_int32_t, pub parent_qid: u_int32_t, } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pf_queuespec__bindgen_ty_1 { pub tqe_next: *mut pf_queuespec, pub tqe_prev: *mut *mut pf_queuespec, } #[test] fn bindgen_test_layout_pf_queuespec__bindgen_ty_1() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 16usize, concat!("Size of: ", stringify!(pf_queuespec__bindgen_ty_1)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pf_queuespec__bindgen_ty_1)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).tqe_next) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pf_queuespec__bindgen_ty_1), "::", stringify!(tqe_next) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).tqe_prev) as usize - ptr as usize }, 8usize, concat!( "Offset of field: ", stringify!(pf_queuespec__bindgen_ty_1), "::", stringify!(tqe_prev) ) ); } #[test] fn bindgen_test_layout_pf_queuespec() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 264usize, concat!("Size of: ", stringify!(pf_queuespec)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pf_queuespec)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).entries) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(pf_queuespec), "::", stringify!(entries)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).qname) as usize - ptr as usize }, 16usize, concat!("Offset of field: ", stringify!(pf_queuespec), "::", stringify!(qname)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).parent) as usize - ptr as usize }, 80usize, concat!("Offset of field: ", stringify!(pf_queuespec), "::", stringify!(parent)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifname) as usize - ptr as usize }, 144usize, concat!("Offset of field: ", stringify!(pf_queuespec), "::", stringify!(ifname)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).realtime) as usize - ptr as usize }, 160usize, concat!( "Offset of field: ", stringify!(pf_queuespec), "::", stringify!(realtime) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).linkshare) as usize - ptr as usize }, 180usize, concat!( "Offset of field: ", stringify!(pf_queuespec), "::", stringify!(linkshare) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).upperlimit) as usize - ptr as usize }, 200usize, concat!( "Offset of field: ", stringify!(pf_queuespec), "::", stringify!(upperlimit) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).flowqueue) as usize - ptr as usize }, 220usize, concat!( "Offset of field: ", stringify!(pf_queuespec), "::", stringify!(flowqueue) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).kif) as usize - ptr as usize }, 240usize, concat!("Offset of field: ", stringify!(pf_queuespec), "::", stringify!(kif)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).flags) as usize - ptr as usize }, 248usize, concat!("Offset of field: ", stringify!(pf_queuespec), "::", stringify!(flags)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).qlimit) as usize - ptr as usize }, 252usize, concat!("Offset of field: ", stringify!(pf_queuespec), "::", stringify!(qlimit)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).qid) as usize - ptr as usize }, 256usize, concat!("Offset of field: ", stringify!(pf_queuespec), "::", stringify!(qid)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).parent_qid) as usize - ptr as usize }, 260usize, concat!( "Offset of field: ", stringify!(pf_queuespec), "::", stringify!(parent_qid) ) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct priq_opts { pub flags: ::std::os::raw::c_int, } #[test] fn bindgen_test_layout_priq_opts() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 4usize, concat!("Size of: ", stringify!(priq_opts)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(priq_opts)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).flags) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(priq_opts), "::", stringify!(flags)) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct hfsc_opts { pub rtsc_m1: u_int, pub rtsc_d: u_int, pub rtsc_m2: u_int, pub lssc_m1: u_int, pub lssc_d: u_int, pub lssc_m2: u_int, pub ulsc_m1: u_int, pub ulsc_d: u_int, pub ulsc_m2: u_int, pub flags: ::std::os::raw::c_int, } #[test] fn bindgen_test_layout_hfsc_opts() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 40usize, concat!("Size of: ", stringify!(hfsc_opts)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(hfsc_opts)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rtsc_m1) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(hfsc_opts), "::", stringify!(rtsc_m1)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rtsc_d) as usize - ptr as usize }, 4usize, concat!("Offset of field: ", stringify!(hfsc_opts), "::", stringify!(rtsc_d)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rtsc_m2) as usize - ptr as usize }, 8usize, concat!("Offset of field: ", stringify!(hfsc_opts), "::", stringify!(rtsc_m2)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).lssc_m1) as usize - ptr as usize }, 12usize, concat!("Offset of field: ", stringify!(hfsc_opts), "::", stringify!(lssc_m1)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).lssc_d) as usize - ptr as usize }, 16usize, concat!("Offset of field: ", stringify!(hfsc_opts), "::", stringify!(lssc_d)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).lssc_m2) as usize - ptr as usize }, 20usize, concat!("Offset of field: ", stringify!(hfsc_opts), "::", stringify!(lssc_m2)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ulsc_m1) as usize - ptr as usize }, 24usize, concat!("Offset of field: ", stringify!(hfsc_opts), "::", stringify!(ulsc_m1)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ulsc_d) as usize - ptr as usize }, 28usize, concat!("Offset of field: ", stringify!(hfsc_opts), "::", stringify!(ulsc_d)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ulsc_m2) as usize - ptr as usize }, 32usize, concat!("Offset of field: ", stringify!(hfsc_opts), "::", stringify!(ulsc_m2)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).flags) as usize - ptr as usize }, 36usize, concat!("Offset of field: ", stringify!(hfsc_opts), "::", stringify!(flags)) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pfq_ops { pub pfq_alloc: ::std::option::Option *mut ::std::os::raw::c_void>, pub pfq_addqueue: ::std::option::Option< unsafe extern "C" fn(arg1: *mut ::std::os::raw::c_void, arg2: *mut pf_queuespec) -> ::std::os::raw::c_int, >, pub pfq_free: ::std::option::Option, pub pfq_qstats: ::std::option::Option< unsafe extern "C" fn( arg1: *mut pf_queuespec, arg2: *mut ::std::os::raw::c_void, arg3: *mut ::std::os::raw::c_int, ) -> ::std::os::raw::c_int, >, pub pfq_qlength: ::std::option::Option ::std::os::raw::c_uint>, pub pfq_enqueue: ::std::option::Option *mut mbuf>, pub pfq_deq_begin: ::std::option::Option< unsafe extern "C" fn( arg1: *mut ::std::os::raw::c_void, arg2: *mut *mut ::std::os::raw::c_void, arg3: *mut mbuf_list, ) -> *mut mbuf, >, pub pfq_deq_commit: ::std::option::Option< unsafe extern "C" fn(arg1: *mut ::std::os::raw::c_void, arg2: *mut mbuf, arg3: *mut ::std::os::raw::c_void), >, pub pfq_purge: ::std::option::Option, } #[test] fn bindgen_test_layout_pfq_ops() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 72usize, concat!("Size of: ", stringify!(pfq_ops)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pfq_ops)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfq_alloc) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(pfq_ops), "::", stringify!(pfq_alloc)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfq_addqueue) as usize - ptr as usize }, 8usize, concat!("Offset of field: ", stringify!(pfq_ops), "::", stringify!(pfq_addqueue)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfq_free) as usize - ptr as usize }, 16usize, concat!("Offset of field: ", stringify!(pfq_ops), "::", stringify!(pfq_free)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfq_qstats) as usize - ptr as usize }, 24usize, concat!("Offset of field: ", stringify!(pfq_ops), "::", stringify!(pfq_qstats)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfq_qlength) as usize - ptr as usize }, 32usize, concat!("Offset of field: ", stringify!(pfq_ops), "::", stringify!(pfq_qlength)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfq_enqueue) as usize - ptr as usize }, 40usize, concat!("Offset of field: ", stringify!(pfq_ops), "::", stringify!(pfq_enqueue)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfq_deq_begin) as usize - ptr as usize }, 48usize, concat!( "Offset of field: ", stringify!(pfq_ops), "::", stringify!(pfq_deq_begin) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfq_deq_commit) as usize - ptr as usize }, 56usize, concat!( "Offset of field: ", stringify!(pfq_ops), "::", stringify!(pfq_deq_commit) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfq_purge) as usize - ptr as usize }, 64usize, concat!("Offset of field: ", stringify!(pfq_ops), "::", stringify!(pfq_purge)) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pf_tagname { pub entries: pf_tagname__bindgen_ty_1, pub name: [::std::os::raw::c_char; 64usize], pub tag: u_int16_t, pub ref_: ::std::os::raw::c_int, } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pf_tagname__bindgen_ty_1 { pub tqe_next: *mut pf_tagname, pub tqe_prev: *mut *mut pf_tagname, } #[test] fn bindgen_test_layout_pf_tagname__bindgen_ty_1() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 16usize, concat!("Size of: ", stringify!(pf_tagname__bindgen_ty_1)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pf_tagname__bindgen_ty_1)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).tqe_next) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pf_tagname__bindgen_ty_1), "::", stringify!(tqe_next) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).tqe_prev) as usize - ptr as usize }, 8usize, concat!( "Offset of field: ", stringify!(pf_tagname__bindgen_ty_1), "::", stringify!(tqe_prev) ) ); } #[test] fn bindgen_test_layout_pf_tagname() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 88usize, concat!("Size of: ", stringify!(pf_tagname)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pf_tagname)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).entries) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(pf_tagname), "::", stringify!(entries)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).name) as usize - ptr as usize }, 16usize, concat!("Offset of field: ", stringify!(pf_tagname), "::", stringify!(name)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).tag) as usize - ptr as usize }, 80usize, concat!("Offset of field: ", stringify!(pf_tagname), "::", stringify!(tag)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ref_) as usize - ptr as usize }, 84usize, concat!("Offset of field: ", stringify!(pf_tagname), "::", stringify!(ref_)) ); } #[repr(C)] #[derive(Copy, Clone)] pub struct pf_divert { pub addr: pf_addr, pub port: u_int16_t, pub rdomain: u_int16_t, pub type_: u_int8_t, } #[test] fn bindgen_test_layout_pf_divert() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 24usize, concat!("Size of: ", stringify!(pf_divert)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(pf_divert)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).addr) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(pf_divert), "::", stringify!(addr)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).port) as usize - ptr as usize }, 16usize, concat!("Offset of field: ", stringify!(pf_divert), "::", stringify!(port)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rdomain) as usize - ptr as usize }, 18usize, concat!("Offset of field: ", stringify!(pf_divert), "::", stringify!(rdomain)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).type_) as usize - ptr as usize }, 20usize, concat!("Offset of field: ", stringify!(pf_divert), "::", stringify!(type_)) ); } pub const pf_divert_types_PF_DIVERT_NONE: pf_divert_types = 0; pub const pf_divert_types_PF_DIVERT_TO: pf_divert_types = 1; pub const pf_divert_types_PF_DIVERT_REPLY: pf_divert_types = 2; pub const pf_divert_types_PF_DIVERT_PACKET: pf_divert_types = 3; pub type pf_divert_types = ::std::os::raw::c_uint; #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pf_pktdelay { pub to: timeout, pub m: *mut mbuf, pub ifidx: u_int, } #[test] fn bindgen_test_layout_pf_pktdelay() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 88usize, concat!("Size of: ", stringify!(pf_pktdelay)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pf_pktdelay)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).to) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(pf_pktdelay), "::", stringify!(to)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).m) as usize - ptr as usize }, 72usize, concat!("Offset of field: ", stringify!(pf_pktdelay), "::", stringify!(m)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ifidx) as usize - ptr as usize }, 80usize, concat!("Offset of field: ", stringify!(pf_pktdelay), "::", stringify!(ifidx)) ); } #[repr(C)] #[derive(Copy, Clone)] pub struct pfioc_rule { pub action: u_int32_t, pub ticket: u_int32_t, pub nr: u_int32_t, pub anchor: [::std::os::raw::c_char; 1024usize], pub anchor_call: [::std::os::raw::c_char; 1024usize], pub rule: pf_rule, } #[test] fn bindgen_test_layout_pfioc_rule() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 3408usize, concat!("Size of: ", stringify!(pfioc_rule)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pfioc_rule)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).action) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(pfioc_rule), "::", stringify!(action)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ticket) as usize - ptr as usize }, 4usize, concat!("Offset of field: ", stringify!(pfioc_rule), "::", stringify!(ticket)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).nr) as usize - ptr as usize }, 8usize, concat!("Offset of field: ", stringify!(pfioc_rule), "::", stringify!(nr)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).anchor) as usize - ptr as usize }, 12usize, concat!("Offset of field: ", stringify!(pfioc_rule), "::", stringify!(anchor)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).anchor_call) as usize - ptr as usize }, 1036usize, concat!( "Offset of field: ", stringify!(pfioc_rule), "::", stringify!(anchor_call) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rule) as usize - ptr as usize }, 2064usize, concat!("Offset of field: ", stringify!(pfioc_rule), "::", stringify!(rule)) ); } #[repr(C)] #[derive(Copy, Clone)] pub struct pfioc_natlook { pub saddr: pf_addr, pub daddr: pf_addr, pub rsaddr: pf_addr, pub rdaddr: pf_addr, pub rdomain: u_int16_t, pub rrdomain: u_int16_t, pub sport: u_int16_t, pub dport: u_int16_t, pub rsport: u_int16_t, pub rdport: u_int16_t, pub af: sa_family_t, pub proto: u_int8_t, pub direction: u_int8_t, } #[test] fn bindgen_test_layout_pfioc_natlook() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 80usize, concat!("Size of: ", stringify!(pfioc_natlook)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(pfioc_natlook)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).saddr) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(pfioc_natlook), "::", stringify!(saddr)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).daddr) as usize - ptr as usize }, 16usize, concat!("Offset of field: ", stringify!(pfioc_natlook), "::", stringify!(daddr)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rsaddr) as usize - ptr as usize }, 32usize, concat!("Offset of field: ", stringify!(pfioc_natlook), "::", stringify!(rsaddr)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rdaddr) as usize - ptr as usize }, 48usize, concat!("Offset of field: ", stringify!(pfioc_natlook), "::", stringify!(rdaddr)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rdomain) as usize - ptr as usize }, 64usize, concat!( "Offset of field: ", stringify!(pfioc_natlook), "::", stringify!(rdomain) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rrdomain) as usize - ptr as usize }, 66usize, concat!( "Offset of field: ", stringify!(pfioc_natlook), "::", stringify!(rrdomain) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).sport) as usize - ptr as usize }, 68usize, concat!("Offset of field: ", stringify!(pfioc_natlook), "::", stringify!(sport)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).dport) as usize - ptr as usize }, 70usize, concat!("Offset of field: ", stringify!(pfioc_natlook), "::", stringify!(dport)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rsport) as usize - ptr as usize }, 72usize, concat!("Offset of field: ", stringify!(pfioc_natlook), "::", stringify!(rsport)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).rdport) as usize - ptr as usize }, 74usize, concat!("Offset of field: ", stringify!(pfioc_natlook), "::", stringify!(rdport)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).af) as usize - ptr as usize }, 76usize, concat!("Offset of field: ", stringify!(pfioc_natlook), "::", stringify!(af)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).proto) as usize - ptr as usize }, 77usize, concat!("Offset of field: ", stringify!(pfioc_natlook), "::", stringify!(proto)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).direction) as usize - ptr as usize }, 78usize, concat!( "Offset of field: ", stringify!(pfioc_natlook), "::", stringify!(direction) ) ); } #[repr(C)] #[derive(Copy, Clone)] pub struct pfioc_state { pub state: pfsync_state, } #[test] fn bindgen_test_layout_pfioc_state() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 264usize, concat!("Size of: ", stringify!(pfioc_state)) ); assert_eq!( ::std::mem::align_of::(), 1usize, concat!("Alignment of ", stringify!(pfioc_state)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).state) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(pfioc_state), "::", stringify!(state)) ); } #[repr(C)] #[derive(Copy, Clone)] pub struct pfioc_src_node_kill { pub psnk_af: sa_family_t, pub psnk_src: pf_rule_addr, pub psnk_dst: pf_rule_addr, pub psnk_killed: u_int, } #[test] fn bindgen_test_layout_pfioc_src_node_kill() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 128usize, concat!("Size of: ", stringify!(pfioc_src_node_kill)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pfioc_src_node_kill)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).psnk_af) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pfioc_src_node_kill), "::", stringify!(psnk_af) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).psnk_src) as usize - ptr as usize }, 8usize, concat!( "Offset of field: ", stringify!(pfioc_src_node_kill), "::", stringify!(psnk_src) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).psnk_dst) as usize - ptr as usize }, 64usize, concat!( "Offset of field: ", stringify!(pfioc_src_node_kill), "::", stringify!(psnk_dst) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).psnk_killed) as usize - ptr as usize }, 120usize, concat!( "Offset of field: ", stringify!(pfioc_src_node_kill), "::", stringify!(psnk_killed) ) ); } #[repr(C)] #[derive(Copy, Clone)] pub struct pfioc_state_kill { pub psk_pfcmp: pf_state_cmp, pub psk_af: sa_family_t, pub psk_proto: ::std::os::raw::c_int, pub psk_src: pf_rule_addr, pub psk_dst: pf_rule_addr, pub psk_ifname: [::std::os::raw::c_char; 16usize], pub psk_label: [::std::os::raw::c_char; 64usize], pub psk_killed: u_int, pub psk_rdomain: u_int16_t, } #[test] fn bindgen_test_layout_pfioc_state_kill() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 224usize, concat!("Size of: ", stringify!(pfioc_state_kill)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pfioc_state_kill)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).psk_pfcmp) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pfioc_state_kill), "::", stringify!(psk_pfcmp) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).psk_af) as usize - ptr as usize }, 16usize, concat!( "Offset of field: ", stringify!(pfioc_state_kill), "::", stringify!(psk_af) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).psk_proto) as usize - ptr as usize }, 20usize, concat!( "Offset of field: ", stringify!(pfioc_state_kill), "::", stringify!(psk_proto) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).psk_src) as usize - ptr as usize }, 24usize, concat!( "Offset of field: ", stringify!(pfioc_state_kill), "::", stringify!(psk_src) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).psk_dst) as usize - ptr as usize }, 80usize, concat!( "Offset of field: ", stringify!(pfioc_state_kill), "::", stringify!(psk_dst) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).psk_ifname) as usize - ptr as usize }, 136usize, concat!( "Offset of field: ", stringify!(pfioc_state_kill), "::", stringify!(psk_ifname) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).psk_label) as usize - ptr as usize }, 152usize, concat!( "Offset of field: ", stringify!(pfioc_state_kill), "::", stringify!(psk_label) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).psk_killed) as usize - ptr as usize }, 216usize, concat!( "Offset of field: ", stringify!(pfioc_state_kill), "::", stringify!(psk_killed) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).psk_rdomain) as usize - ptr as usize }, 220usize, concat!( "Offset of field: ", stringify!(pfioc_state_kill), "::", stringify!(psk_rdomain) ) ); } #[repr(C)] #[derive(Copy, Clone)] pub struct pfioc_states { pub ps_len: usize, pub ps_u: pfioc_states__bindgen_ty_1, } #[repr(C)] #[derive(Copy, Clone)] pub union pfioc_states__bindgen_ty_1 { pub psu_buf: caddr_t, pub psu_states: *mut pfsync_state, } #[test] fn bindgen_test_layout_pfioc_states__bindgen_ty_1() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 8usize, concat!("Size of: ", stringify!(pfioc_states__bindgen_ty_1)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pfioc_states__bindgen_ty_1)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).psu_buf) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pfioc_states__bindgen_ty_1), "::", stringify!(psu_buf) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).psu_states) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pfioc_states__bindgen_ty_1), "::", stringify!(psu_states) ) ); } #[test] fn bindgen_test_layout_pfioc_states() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 16usize, concat!("Size of: ", stringify!(pfioc_states)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pfioc_states)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ps_len) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(pfioc_states), "::", stringify!(ps_len)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ps_u) as usize - ptr as usize }, 8usize, concat!("Offset of field: ", stringify!(pfioc_states), "::", stringify!(ps_u)) ); } #[repr(C)] #[derive(Copy, Clone)] pub struct pfioc_src_nodes { pub psn_len: usize, pub psn_u: pfioc_src_nodes__bindgen_ty_1, } #[repr(C)] #[derive(Copy, Clone)] pub union pfioc_src_nodes__bindgen_ty_1 { pub psu_buf: caddr_t, pub psu_src_nodes: *mut pf_src_node, } #[test] fn bindgen_test_layout_pfioc_src_nodes__bindgen_ty_1() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 8usize, concat!("Size of: ", stringify!(pfioc_src_nodes__bindgen_ty_1)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pfioc_src_nodes__bindgen_ty_1)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).psu_buf) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pfioc_src_nodes__bindgen_ty_1), "::", stringify!(psu_buf) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).psu_src_nodes) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pfioc_src_nodes__bindgen_ty_1), "::", stringify!(psu_src_nodes) ) ); } #[test] fn bindgen_test_layout_pfioc_src_nodes() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 16usize, concat!("Size of: ", stringify!(pfioc_src_nodes)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pfioc_src_nodes)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).psn_len) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pfioc_src_nodes), "::", stringify!(psn_len) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).psn_u) as usize - ptr as usize }, 8usize, concat!( "Offset of field: ", stringify!(pfioc_src_nodes), "::", stringify!(psn_u) ) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pfioc_tm { pub timeout: ::std::os::raw::c_int, pub seconds: ::std::os::raw::c_int, } #[test] fn bindgen_test_layout_pfioc_tm() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 8usize, concat!("Size of: ", stringify!(pfioc_tm)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(pfioc_tm)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).timeout) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(pfioc_tm), "::", stringify!(timeout)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).seconds) as usize - ptr as usize }, 4usize, concat!("Offset of field: ", stringify!(pfioc_tm), "::", stringify!(seconds)) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pfioc_limit { pub index: ::std::os::raw::c_int, pub limit: ::std::os::raw::c_uint, } #[test] fn bindgen_test_layout_pfioc_limit() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 8usize, concat!("Size of: ", stringify!(pfioc_limit)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(pfioc_limit)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).index) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(pfioc_limit), "::", stringify!(index)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).limit) as usize - ptr as usize }, 4usize, concat!("Offset of field: ", stringify!(pfioc_limit), "::", stringify!(limit)) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pfioc_ruleset { pub nr: u_int32_t, pub path: [::std::os::raw::c_char; 1024usize], pub name: [::std::os::raw::c_char; 64usize], } #[test] fn bindgen_test_layout_pfioc_ruleset() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 1092usize, concat!("Size of: ", stringify!(pfioc_ruleset)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(pfioc_ruleset)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).nr) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(pfioc_ruleset), "::", stringify!(nr)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).path) as usize - ptr as usize }, 4usize, concat!("Offset of field: ", stringify!(pfioc_ruleset), "::", stringify!(path)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).name) as usize - ptr as usize }, 1028usize, concat!("Offset of field: ", stringify!(pfioc_ruleset), "::", stringify!(name)) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pfioc_trans { pub size: ::std::os::raw::c_int, pub esize: ::std::os::raw::c_int, pub array: *mut pfioc_trans_pfioc_trans_e, } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pfioc_trans_pfioc_trans_e { pub type_: ::std::os::raw::c_int, pub anchor: [::std::os::raw::c_char; 1024usize], pub ticket: u_int32_t, } #[test] fn bindgen_test_layout_pfioc_trans_pfioc_trans_e() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 1032usize, concat!("Size of: ", stringify!(pfioc_trans_pfioc_trans_e)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(pfioc_trans_pfioc_trans_e)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).type_) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pfioc_trans_pfioc_trans_e), "::", stringify!(type_) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).anchor) as usize - ptr as usize }, 4usize, concat!( "Offset of field: ", stringify!(pfioc_trans_pfioc_trans_e), "::", stringify!(anchor) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ticket) as usize - ptr as usize }, 1028usize, concat!( "Offset of field: ", stringify!(pfioc_trans_pfioc_trans_e), "::", stringify!(ticket) ) ); } #[test] fn bindgen_test_layout_pfioc_trans() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 16usize, concat!("Size of: ", stringify!(pfioc_trans)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pfioc_trans)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).size) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(pfioc_trans), "::", stringify!(size)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).esize) as usize - ptr as usize }, 4usize, concat!("Offset of field: ", stringify!(pfioc_trans), "::", stringify!(esize)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).array) as usize - ptr as usize }, 8usize, concat!("Offset of field: ", stringify!(pfioc_trans), "::", stringify!(array)) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pfioc_queue { pub ticket: u_int32_t, pub nr: u_int, pub queue: pf_queuespec, } #[test] fn bindgen_test_layout_pfioc_queue() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 272usize, concat!("Size of: ", stringify!(pfioc_queue)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pfioc_queue)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ticket) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(pfioc_queue), "::", stringify!(ticket)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).nr) as usize - ptr as usize }, 4usize, concat!("Offset of field: ", stringify!(pfioc_queue), "::", stringify!(nr)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).queue) as usize - ptr as usize }, 8usize, concat!("Offset of field: ", stringify!(pfioc_queue), "::", stringify!(queue)) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pfioc_qstats { pub ticket: u_int32_t, pub nr: u_int32_t, pub queue: pf_queuespec, pub buf: *mut ::std::os::raw::c_void, pub nbytes: ::std::os::raw::c_int, } #[test] fn bindgen_test_layout_pfioc_qstats() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 288usize, concat!("Size of: ", stringify!(pfioc_qstats)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pfioc_qstats)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).ticket) as usize - ptr as usize }, 0usize, concat!("Offset of field: ", stringify!(pfioc_qstats), "::", stringify!(ticket)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).nr) as usize - ptr as usize }, 4usize, concat!("Offset of field: ", stringify!(pfioc_qstats), "::", stringify!(nr)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).queue) as usize - ptr as usize }, 8usize, concat!("Offset of field: ", stringify!(pfioc_qstats), "::", stringify!(queue)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).buf) as usize - ptr as usize }, 272usize, concat!("Offset of field: ", stringify!(pfioc_qstats), "::", stringify!(buf)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).nbytes) as usize - ptr as usize }, 280usize, concat!("Offset of field: ", stringify!(pfioc_qstats), "::", stringify!(nbytes)) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pfioc_table { pub pfrio_table: pfr_table, pub pfrio_buffer: *mut ::std::os::raw::c_void, pub pfrio_esize: ::std::os::raw::c_int, pub pfrio_size: ::std::os::raw::c_int, pub pfrio_size2: ::std::os::raw::c_int, pub pfrio_nadd: ::std::os::raw::c_int, pub pfrio_ndel: ::std::os::raw::c_int, pub pfrio_nchange: ::std::os::raw::c_int, pub pfrio_flags: ::std::os::raw::c_int, pub pfrio_ticket: u_int32_t, } #[test] fn bindgen_test_layout_pfioc_table() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 1104usize, concat!("Size of: ", stringify!(pfioc_table)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pfioc_table)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfrio_table) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pfioc_table), "::", stringify!(pfrio_table) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfrio_buffer) as usize - ptr as usize }, 1064usize, concat!( "Offset of field: ", stringify!(pfioc_table), "::", stringify!(pfrio_buffer) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfrio_esize) as usize - ptr as usize }, 1072usize, concat!( "Offset of field: ", stringify!(pfioc_table), "::", stringify!(pfrio_esize) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfrio_size) as usize - ptr as usize }, 1076usize, concat!( "Offset of field: ", stringify!(pfioc_table), "::", stringify!(pfrio_size) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfrio_size2) as usize - ptr as usize }, 1080usize, concat!( "Offset of field: ", stringify!(pfioc_table), "::", stringify!(pfrio_size2) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfrio_nadd) as usize - ptr as usize }, 1084usize, concat!( "Offset of field: ", stringify!(pfioc_table), "::", stringify!(pfrio_nadd) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfrio_ndel) as usize - ptr as usize }, 1088usize, concat!( "Offset of field: ", stringify!(pfioc_table), "::", stringify!(pfrio_ndel) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfrio_nchange) as usize - ptr as usize }, 1092usize, concat!( "Offset of field: ", stringify!(pfioc_table), "::", stringify!(pfrio_nchange) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfrio_flags) as usize - ptr as usize }, 1096usize, concat!( "Offset of field: ", stringify!(pfioc_table), "::", stringify!(pfrio_flags) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfrio_ticket) as usize - ptr as usize }, 1100usize, concat!( "Offset of field: ", stringify!(pfioc_table), "::", stringify!(pfrio_ticket) ) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pfioc_iface { pub pfiio_name: [::std::os::raw::c_char; 16usize], pub pfiio_buffer: *mut ::std::os::raw::c_void, pub pfiio_esize: ::std::os::raw::c_int, pub pfiio_size: ::std::os::raw::c_int, pub pfiio_nzero: ::std::os::raw::c_int, pub pfiio_flags: ::std::os::raw::c_int, } #[test] fn bindgen_test_layout_pfioc_iface() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 40usize, concat!("Size of: ", stringify!(pfioc_iface)) ); assert_eq!( ::std::mem::align_of::(), 8usize, concat!("Alignment of ", stringify!(pfioc_iface)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfiio_name) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pfioc_iface), "::", stringify!(pfiio_name) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfiio_buffer) as usize - ptr as usize }, 16usize, concat!( "Offset of field: ", stringify!(pfioc_iface), "::", stringify!(pfiio_buffer) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfiio_esize) as usize - ptr as usize }, 24usize, concat!( "Offset of field: ", stringify!(pfioc_iface), "::", stringify!(pfiio_esize) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfiio_size) as usize - ptr as usize }, 28usize, concat!( "Offset of field: ", stringify!(pfioc_iface), "::", stringify!(pfiio_size) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfiio_nzero) as usize - ptr as usize }, 32usize, concat!( "Offset of field: ", stringify!(pfioc_iface), "::", stringify!(pfiio_nzero) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pfiio_flags) as usize - ptr as usize }, 36usize, concat!( "Offset of field: ", stringify!(pfioc_iface), "::", stringify!(pfiio_flags) ) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pfioc_synflwats { pub hiwat: u_int32_t, pub lowat: u_int32_t, } #[test] fn bindgen_test_layout_pfioc_synflwats() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::(), 8usize, concat!("Size of: ", stringify!(pfioc_synflwats)) ); assert_eq!( ::std::mem::align_of::(), 4usize, concat!("Alignment of ", stringify!(pfioc_synflwats)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).hiwat) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(pfioc_synflwats), "::", stringify!(hiwat) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).lowat) as usize - ptr as usize }, 4usize, concat!( "Offset of field: ", stringify!(pfioc_synflwats), "::", stringify!(lowat) ) ); } unsafe extern "C" { pub static mut pf_anchors: pf_anchor_global; } unsafe extern "C" { pub static mut pf_main_anchor: pf_anchor; } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct tcphdr { _unused: [u8; 0], } unsafe extern "C" { pub fn pf_init_ruleset(arg1: *mut pf_ruleset); } unsafe extern "C" { pub fn pf_anchor_setup( arg1: *mut pf_rule, arg2: *const pf_ruleset, arg3: *const ::std::os::raw::c_char, ) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn pf_anchor_copyout( arg1: *const pf_ruleset, arg2: *const pf_rule, arg3: *mut pfioc_rule, ) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn pf_remove_anchor(arg1: *mut pf_rule); } unsafe extern "C" { pub fn pf_remove_if_empty_ruleset(arg1: *mut pf_ruleset); } unsafe extern "C" { pub fn pf_find_anchor(arg1: *const ::std::os::raw::c_char) -> *mut pf_anchor; } unsafe extern "C" { pub fn pf_find_ruleset(arg1: *const ::std::os::raw::c_char) -> *mut pf_ruleset; } unsafe extern "C" { pub fn pf_get_leaf_ruleset( arg1: *mut ::std::os::raw::c_char, arg2: *mut *mut ::std::os::raw::c_char, ) -> *mut pf_ruleset; } unsafe extern "C" { pub fn pf_create_anchor(arg1: *mut pf_anchor, arg2: *const ::std::os::raw::c_char) -> *mut pf_anchor; } unsafe extern "C" { pub fn pf_find_or_create_ruleset(arg1: *const ::std::os::raw::c_char) -> *mut pf_ruleset; } unsafe extern "C" { pub fn pf_rs_initialize(); } unsafe extern "C" { pub fn pf_anchor_rele(arg1: *mut pf_anchor); } unsafe extern "C" { pub fn pf_anchor_take(arg1: *mut pf_anchor) -> *mut pf_anchor; } unsafe extern "C" { pub fn pf_osfp_add(arg1: *mut pf_osfp_ioctl) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn pf_osfp_fingerprint_hdr( arg1: *const ip, arg2: *const ip6_hdr, arg3: *const tcphdr, ) -> *mut pf_os_fingerprint_pf_osfp_enlist; } unsafe extern "C" { pub fn pf_osfp_flush(); } unsafe extern "C" { pub fn pf_osfp_get(arg1: *mut pf_osfp_ioctl) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn pf_osfp_initialize(); } unsafe extern "C" { pub fn pf_osfp_match(arg1: *mut pf_os_fingerprint_pf_osfp_enlist, arg2: pf_osfp_t) -> ::std::os::raw::c_int; } unsafe extern "C" { pub fn pf_osfp_validate() -> *mut pf_os_fingerprint; } pub type __builtin_va_list = [__va_list_tag; 1usize]; #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct __va_list_tag { pub gp_offset: ::std::os::raw::c_uint, pub fp_offset: ::std::os::raw::c_uint, pub overflow_arg_area: *mut ::std::os::raw::c_void, pub reg_save_area: *mut ::std::os::raw::c_void, } #[test] fn bindgen_test_layout___va_list_tag() { const UNINIT: ::std::mem::MaybeUninit<__va_list_tag> = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( ::std::mem::size_of::<__va_list_tag>(), 24usize, concat!("Size of: ", stringify!(__va_list_tag)) ); assert_eq!( ::std::mem::align_of::<__va_list_tag>(), 8usize, concat!("Alignment of ", stringify!(__va_list_tag)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).gp_offset) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", stringify!(__va_list_tag), "::", stringify!(gp_offset) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).fp_offset) as usize - ptr as usize }, 4usize, concat!( "Offset of field: ", stringify!(__va_list_tag), "::", stringify!(fp_offset) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).overflow_arg_area) as usize - ptr as usize }, 8usize, concat!( "Offset of field: ", stringify!(__va_list_tag), "::", stringify!(overflow_arg_area) ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).reg_save_area) as usize - ptr as usize }, 16usize, concat!( "Offset of field: ", stringify!(__va_list_tag), "::", stringify!(reg_save_area) ) ); } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct witness { pub _address: u8, } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct process { pub _address: u8, } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct ifaddr { pub _address: u8, } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct rtentry { pub _address: u8, } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pfi_dynaddr { pub _address: u8, } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pf_state { pub _address: u8, } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct pf_state_key { pub _address: u8, } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct mbuf { _unused: [u8; 0], } ================================================ FILE: crates/shadowsocks-service/src/local/redir/tcprelay/mod.rs ================================================ //! Shadowsocks TCP transparent proxy use std::{ io, net::{IpAddr, SocketAddr}, sync::Arc, time::Duration, }; use log::{debug, error, info, trace}; use shadowsocks::{ServerAddr, lookup_then, net::TcpListener as ShadowTcpListener, relay::socks5::Address}; use tokio::{ net::{TcpListener, TcpStream}, time, }; use crate::{ config::RedirType, local::{ context::ServiceContext, loadbalancing::PingBalancer, net::AutoProxyClientStream, redir::redir_ext::{TcpListenerRedirExt, TcpStreamRedirExt}, utils::{establish_tcp_tunnel, establish_tcp_tunnel_bypassed}, }, net::utils::to_ipv4_mapped, }; #[allow(unused_imports)] mod sys; /// Established Client Transparent Proxy /// /// This method must be called after handshaking with client (for example, socks5 handshaking) async fn establish_client_tcp_redir( context: Arc, balancer: PingBalancer, mut stream: TcpStream, peer_addr: SocketAddr, addr: &Address, ) -> io::Result<()> { if balancer.is_empty() { let mut remote = AutoProxyClientStream::connect_bypassed(context, addr).await?; return establish_tcp_tunnel_bypassed(&mut stream, &mut remote, peer_addr, addr).await; } let server = balancer.best_tcp_server(); let svr_cfg = server.server_config(); let mut remote = AutoProxyClientStream::connect_with_opts(context, &server, addr, server.connect_opts_ref()).await?; establish_tcp_tunnel(svr_cfg, &mut stream, &mut remote, peer_addr, addr).await } async fn handle_redir_client( context: Arc, balancer: PingBalancer, s: TcpStream, peer_addr: SocketAddr, mut daddr: SocketAddr, ) -> io::Result<()> { // Get forward address from socket // // Try to convert IPv4 mapped IPv6 address for dual-stack mode. if let SocketAddr::V6(ref a) = daddr && let Some(v4) = to_ipv4_mapped(a.ip()) { daddr = SocketAddr::new(IpAddr::from(v4), a.port()); } let target_addr = Address::from(daddr); establish_client_tcp_redir(context, balancer, s, peer_addr, &target_addr).await } /// Redir TCP server instance pub struct RedirTcpServer { context: Arc, listener: TcpListener, balancer: PingBalancer, redir_ty: RedirType, } impl RedirTcpServer { pub(crate) async fn new( context: Arc, client_config: &ServerAddr, balancer: PingBalancer, redir_ty: RedirType, ) -> io::Result { let listener = match *client_config { ServerAddr::SocketAddr(ref saddr) => { TcpListener::bind_redir(redir_ty, *saddr, context.accept_opts()).await? } ServerAddr::DomainName(ref dname, port) => { lookup_then!(context.context_ref(), dname, port, |addr| { TcpListener::bind_redir(redir_ty, addr, context.accept_opts()).await })? .1 } }; Ok(Self { context, listener, balancer, redir_ty, }) } /// Get server local address pub fn local_addr(&self) -> io::Result { self.listener.local_addr() } /// Start serving pub async fn run(self) -> io::Result<()> { let listener = ShadowTcpListener::from_listener(self.listener, self.context.accept_opts())?; let actual_local_addr = listener.local_addr().expect("determine port bound to"); info!( "shadowsocks TCP redirect ({}) listening on {}", self.redir_ty, actual_local_addr ); loop { let (socket, peer_addr) = match listener.accept().await { Ok(s) => s, Err(err) => { error!("accept failed with error: {}", err); time::sleep(Duration::from_secs(1)).await; continue; } }; trace!("got connection {}", peer_addr); let context = self.context.clone(); let balancer = self.balancer.clone(); let redir_ty = self.redir_ty; tokio::spawn(async move { let dst_addr = match socket.destination_addr(redir_ty) { Ok(d) => d, Err(err) => { error!( "TCP redirect couldn't get destination, peer: {}, error: {}", peer_addr, err ); return; } }; if let Err(err) = handle_redir_client(context, balancer, socket, peer_addr, dst_addr).await { debug!("TCP redirect client, error: {:?}", err); } }); } } } ================================================ FILE: crates/shadowsocks-service/src/local/redir/tcprelay/sys/mod.rs ================================================ use cfg_if::cfg_if; cfg_if! { if #[cfg(unix)] { mod unix; pub use self::unix::*; } else if #[cfg(windows)] { mod windows; pub use self::windows::*; } } ================================================ FILE: crates/shadowsocks-service/src/local/redir/tcprelay/sys/unix/bsd.rs ================================================ use std::{ io::{self, Error, ErrorKind}, net::SocketAddr, }; use log::warn; use shadowsocks::net::{AcceptOpts, is_dual_stack_addr, set_tcp_fastopen}; use socket2::Protocol; use tokio::net::{TcpListener, TcpSocket, TcpStream}; use crate::{ config::RedirType, local::redir::{ redir_ext::{TcpListenerRedirExt, TcpStreamRedirExt}, sys::set_ipv6_only, }, }; impl TcpListenerRedirExt for TcpListener { async fn bind_redir(ty: RedirType, addr: SocketAddr, accept_opts: AcceptOpts) -> io::Result { match ty { #[cfg(any(target_os = "freebsd", target_os = "openbsd", target_os = "macos", target_os = "ios"))] RedirType::PacketFilter => {} #[cfg(any(target_os = "freebsd", target_os = "macos", target_os = "ios"))] RedirType::IpFirewall => {} _ => { return Err(Error::new( ErrorKind::InvalidInput, "not supported tcp transparent proxy type", )); } } // BSD platform doesn't have any special logic let socket = match addr { SocketAddr::V4(..) => TcpSocket::new_v4()?, SocketAddr::V6(..) => TcpSocket::new_v6()?, }; // On platforms with Berkeley-derived sockets, this allows to quickly // rebind a socket, without needing to wait for the OS to clean up the // previous one. // // On Windows, this allows rebinding sockets which are actively in use, // which allows “socket hijacking”, so we explicitly don't set it here. // https://docs.microsoft.com/en-us/windows/win32/winsock/using-so-reuseaddr-and-so-exclusiveaddruse #[cfg(unix)] socket.set_reuseaddr(true)?; let set_dual_stack = is_dual_stack_addr(&addr); if set_dual_stack { // Try to bind dual-stack address match set_ipv6_only(&socket, false) { Ok(..) => { // bind() if let Err(err) = socket.bind(addr) { warn!( "bind() dual-stack address {} failed, error: {}, fallback to IPV6_V6ONLY=false", addr, err ); if let Err(err) = set_ipv6_only(&socket, true) { warn!( "set IPV6_V6ONLY=true failed, error: {}, bind() to {} directly", err, addr ); } socket.bind(addr)?; } } Err(err) => { warn!( "set IPV6_V6ONLY=false failed, error: {}, bind() to {} directly", err, addr ); socket.bind(addr)?; } } } else { socket.bind(addr)?; } // mio's default backlog is 1024 let listener = socket.listen(1024)?; if accept_opts.tcp.fastopen { set_tcp_fastopen(&listener)?; } Ok(listener) } } impl TcpStreamRedirExt for TcpStream { fn destination_addr(&self, ty: RedirType) -> io::Result { match ty { #[cfg(any(target_os = "freebsd", target_os = "macos", target_os = "ios"))] RedirType::PacketFilter => { use crate::local::redir::sys::bsd_pf::PF; let peer_addr = self.peer_addr()?; let bind_addr = self.local_addr()?; PF.natlook(&bind_addr, &peer_addr, Protocol::TCP) } #[cfg(target_os = "openbsd")] // in OpenBSD, we can get TCP destination address with getsockname() RedirType::PacketFilter => self.local_addr(), #[cfg(any(target_os = "freebsd", target_os = "macos", target_os = "ios"))] RedirType::IpFirewall => { // ## IPFW // // For IPFW, uses getsockname() to retrieve destination address // // FreeBSD: https://www.freebsd.org/doc/handbook/firewalls-ipfw.html self.local_addr() } _ => unreachable!("not supported tcp transparent proxy type"), } } } ================================================ FILE: crates/shadowsocks-service/src/local/redir/tcprelay/sys/unix/linux.rs ================================================ use std::{ io::{self, Error, ErrorKind}, mem, net::SocketAddr, os::unix::io::AsRawFd, }; use log::warn; use shadowsocks::net::{AcceptOpts, is_dual_stack_addr, set_tcp_fastopen}; use socket2::SockAddr; use tokio::net::{TcpListener, TcpSocket, TcpStream}; use crate::{ config::RedirType, local::redir::{ redir_ext::{TcpListenerRedirExt, TcpStreamRedirExt}, sys::set_ipv6_only, }, }; impl TcpListenerRedirExt for TcpListener { async fn bind_redir(ty: RedirType, addr: SocketAddr, accept_opts: AcceptOpts) -> io::Result { match ty { RedirType::Redirect => { // REDIRECT rule doesn't need to set IP_TRANSPARENT let socket = match addr { SocketAddr::V4(..) => TcpSocket::new_v4()?, SocketAddr::V6(..) => TcpSocket::new_v6()?, }; // On platforms with Berkeley-derived sockets, this allows to quickly // rebind a socket, without needing to wait for the OS to clean up the // previous one. // // On Windows, this allows rebinding sockets which are actively in use, // which allows “socket hijacking”, so we explicitly don't set it here. // https://docs.microsoft.com/en-us/windows/win32/winsock/using-so-reuseaddr-and-so-exclusiveaddruse #[cfg(unix)] socket.set_reuseaddr(true)?; let set_dual_stack = is_dual_stack_addr(&addr); if set_dual_stack { // Try to bind dual-stack address match set_ipv6_only(&socket, false) { Ok(..) => { // bind() if let Err(err) = socket.bind(addr) { warn!( "bind() dual-stack address {} failed, error: {}, fallback to IPV6_V6ONLY=true", addr, err ); if let Err(err) = set_ipv6_only(&socket, true) { warn!( "set IPV6_V6ONLY=true failed, error: {}, bind() to {} directly", err, addr ); } socket.bind(addr)?; } } Err(err) => { warn!( "set IPV6_V6ONLY=false failed, error: {}, bind() to {} directly", err, addr ); socket.bind(addr)?; } } } else { // bind, listen as original socket.bind(addr)?; } // mio's default backlog is 1024 let listener = socket.listen(1024)?; if accept_opts.tcp.fastopen { set_tcp_fastopen(&listener)?; } Ok(listener) } RedirType::TProxy => { // TPROXY rule requires IP_TRANSPARENT create_redir_listener(addr, accept_opts).await } _ => Err(Error::new( ErrorKind::InvalidInput, "not supported tcp transparent proxy type", )), } } } impl TcpStreamRedirExt for TcpStream { fn destination_addr(&self, ty: RedirType) -> io::Result { match ty { RedirType::Redirect => get_original_destination_addr(self), RedirType::TProxy => { // For TPROXY, uses getsockname() to retrieve original destination address self.local_addr() } _ => unreachable!("not supported tcp transparent proxy type"), } } } fn get_original_destination_addr(s: &TcpStream) -> io::Result { let fd = s.as_raw_fd(); unsafe { let (_, target_addr) = SockAddr::try_init(|target_addr, target_addr_len| { // No sufficient method to know whether the destination IPv4 or IPv6. // Follow the method in shadowsocks-libev. let ret = libc::getsockopt( fd, libc::SOL_IPV6, libc::IP6T_SO_ORIGINAL_DST, target_addr as *mut _, target_addr_len, // libc::socklen_t ); if ret == 0 { return Ok(()); } else { let err = Error::last_os_error(); match err.raw_os_error() { None => return Err(err), // ENOPROTOOPT, EOPNOTSUPP (ENOTSUP): IP6T_SO_ORIGINAL_DST doesn't exist // ENOENT: Destination address is not IPv6 #[allow(unreachable_patterns)] Some(libc::ENOPROTOOPT) | Some(libc::ENOENT) | Some(libc::EOPNOTSUPP) | Some(libc::ENOTSUP) => {} Some(..) => return Err(err), } } let ret = libc::getsockopt( fd, libc::SOL_IP, libc::SO_ORIGINAL_DST, target_addr as *mut _, target_addr_len, // libc::socklen_t ); if ret != 0 { let err = Error::last_os_error(); return Err(err); } Ok(()) })?; // Convert sockaddr_storage to SocketAddr Ok(target_addr.as_socket().expect("SocketAddr")) } } fn set_ip_transparent(level: libc::c_int, socket: &TcpSocket) -> io::Result<()> { let fd = socket.as_raw_fd(); let opt = match level { libc::IPPROTO_IP => libc::IP_TRANSPARENT, libc::IPPROTO_IPV6 => libc::IPV6_TRANSPARENT, _ => unreachable!("level can only be IPPROTO_IP and IPPROTO_IPV6"), }; let enable: libc::c_int = 1; unsafe { let ret = libc::setsockopt( fd, level, opt, &enable as *const _ as *const _, mem::size_of_val(&enable) as libc::socklen_t, ); if ret != 0 { return Err(Error::last_os_error()); } } Ok(()) } async fn create_redir_listener(addr: SocketAddr, accept_opts: AcceptOpts) -> io::Result { let socket = match addr { SocketAddr::V4(..) => TcpSocket::new_v4()?, SocketAddr::V6(..) => TcpSocket::new_v6()?, }; // For Linux 2.4+ TPROXY // Sockets have to set IP_TRANSPARENT, IPV6_TRANSPARENT for retrieving original destination by getsockname() let level = match addr { SocketAddr::V4(..) => libc::IPPROTO_IP, SocketAddr::V6(..) => libc::IPPROTO_IPV6, }; set_ip_transparent(level, &socket)?; // On platforms with Berkeley-derived sockets, this allows to quickly // rebind a socket, without needing to wait for the OS to clean up the // previous one. // // On Windows, this allows rebinding sockets which are actively in use, // which allows “socket hijacking”, so we explicitly don't set it here. // https://docs.microsoft.com/en-us/windows/win32/winsock/using-so-reuseaddr-and-so-exclusiveaddruse #[cfg(unix)] socket.set_reuseaddr(true)?; let set_dual_stack = is_dual_stack_addr(&addr); if set_dual_stack { // set IP_TRANSPARENT before bind() set_ip_transparent(libc::IPPROTO_IP, &socket)?; // Try to bind dual-stack address match set_ipv6_only(&socket, false) { Ok(..) => { // bind() if let Err(err) = socket.bind(addr) { warn!( "bind() dual-stack address {} failed, error: {}, fallback to IPV6_V6ONLY=true", addr, err ); if let Err(err) = set_ipv6_only(&socket, true) { warn!( "set IPV6_V6ONLY=true failed, error: {}, bind() to {} directly", err, addr ); } socket.bind(addr)?; } } Err(err) => { warn!( "set IPV6_V6ONLY=false failed, error: {}, bind() to {} directly", err, addr ); socket.bind(addr)?; } } } else { // bind, listen as original socket.bind(addr)?; } // listen backlogs = 1024 as mio's default let listener = socket.listen(1024)?; if accept_opts.tcp.fastopen { set_tcp_fastopen(&listener)?; } Ok(listener) } ================================================ FILE: crates/shadowsocks-service/src/local/redir/tcprelay/sys/unix/mod.rs ================================================ use cfg_if::cfg_if; cfg_if! { if #[cfg(any(target_os = "linux", target_os = "android"))] { mod linux; pub use self::linux::*; } else if #[cfg(any(target_os = "macos", target_os = "ios", target_os = "freebsd", target_os = "openbsd"))] { mod bsd; pub use self::bsd::*; } else { mod not_supported; pub use self::not_supported::*; } } ================================================ FILE: crates/shadowsocks-service/src/local/redir/tcprelay/sys/unix/not_supported.rs ================================================ use std::{io, net::SocketAddr}; use shadowsocks::net::AcceptOpts; use tokio::net::{TcpListener, TcpStream}; use crate::{ config::RedirType, local::redir::redir_ext::{TcpListenerRedirExt, TcpStreamRedirExt}, }; impl TcpListenerRedirExt for TcpListener { async fn bind_redir(_ty: RedirType, _addr: SocketAddr, _accept_opts: AcceptOpts) -> io::Result { unimplemented!("TCP transparent proxy is not supported on this platform") } } impl TcpStreamRedirExt for TcpStream { fn destination_addr(&self, _ty: RedirType) -> io::Result { unimplemented!("TCP transparent proxy is not supported on this platform") } } ================================================ FILE: crates/shadowsocks-service/src/local/redir/tcprelay/sys/windows/mod.rs ================================================ use std::{ io::{self, Error, ErrorKind}, net::SocketAddr, }; use shadowsocks::net::AcceptOpts; use tokio::net::{TcpListener, TcpStream}; use crate::{ config::RedirType, local::redir::redir_ext::{TcpListenerRedirExt, TcpStreamRedirExt}, }; impl TcpListenerRedirExt for TcpListener { async fn bind_redir(_ty: RedirType, _addr: SocketAddr, _accept_opts: AcceptOpts) -> io::Result { let err = Error::new( ErrorKind::InvalidInput, "not supported tcp transparent proxy on Windows", ); Err(err) } } impl TcpStreamRedirExt for TcpStream { fn destination_addr(&self, _ty: RedirType) -> io::Result { unreachable!("not supported tcp transparent on Windows") } } ================================================ FILE: crates/shadowsocks-service/src/local/redir/udprelay/mod.rs ================================================ //! UDP transparent proxy use std::{ io::{self, ErrorKind}, net::{IpAddr, SocketAddr}, sync::Arc, time::Duration, }; use log::{debug, error, info, trace, warn}; use lru_time_cache::LruCache; use shadowsocks::{ ServerAddr, lookup_then, net::{ConnectOpts, get_ip_stack_capabilities}, relay::{socks5::Address, udprelay::MAXIMUM_UDP_PAYLOAD_SIZE}, }; use tokio::{sync::Mutex, task::JoinHandle, time}; use crate::{ config::RedirType, local::{ context::ServiceContext, loadbalancing::PingBalancer, net::{UdpAssociationManager, UdpInboundWrite}, redir::redir_ext::{RedirSocketOpts, UdpSocketRedirExt}, }, net::utils::to_ipv4_mapped, }; use self::sys::UdpRedirSocket; mod sys; const INBOUND_SOCKET_CACHE_EXPIRATION: Duration = Duration::from_secs(60); const INBOUND_SOCKET_CACHE_CAPACITY: usize = 256; struct UdpRedirInboundCache { cache: Arc>>>, watcher: JoinHandle<()>, } impl Drop for UdpRedirInboundCache { fn drop(&mut self) { self.watcher.abort(); } } impl UdpRedirInboundCache { fn new() -> Self { let cache = Arc::new(Mutex::new(LruCache::with_expiry_duration_and_capacity( INBOUND_SOCKET_CACHE_EXPIRATION, INBOUND_SOCKET_CACHE_CAPACITY, ))); let watcher = { let cache = cache.clone(); tokio::spawn(async move { loop { tokio::time::sleep(INBOUND_SOCKET_CACHE_EXPIRATION).await; let _ = cache.lock().await.iter(); } }) }; Self { cache, watcher } } } #[derive(Clone)] struct UdpRedirInboundWriter { redir_ty: RedirType, socket_opts: RedirSocketOpts, inbound_cache: Arc, } impl UdpRedirInboundWriter { #[allow(unused_variables, clippy::needless_update)] fn new(redir_ty: RedirType, opts: &ConnectOpts) -> Self { Self { redir_ty, socket_opts: RedirSocketOpts { #[cfg(any(target_os = "linux", target_os = "android"))] fwmark: opts.fwmark, ..Default::default() }, inbound_cache: Arc::new(UdpRedirInboundCache::new()), } } } impl UdpInboundWrite for UdpRedirInboundWriter { async fn send_to(&self, mut peer_addr: SocketAddr, remote_addr: &Address, data: &[u8]) -> io::Result<()> { // If IPv6 Transparent Proxy is supported on the current platform, // then we should always use IPv6 sockets for sending IPv4 packets. let ip_stack_caps = get_ip_stack_capabilities(); let addr = match *remote_addr { Address::SocketAddress(sa) => { match sa { SocketAddr::V4(ref v4) => { // If IPv4-mapped-IPv6 is supported. // Converts IPv4 address to IPv4-mapped-IPv6 // All sockets will be created in IPv6 (nearly all modern OS supports IPv6 sockets) if ip_stack_caps.support_ipv4_mapped_ipv6 { SocketAddr::new(v4.ip().to_ipv6_mapped().into(), v4.port()) } else { sa } } SocketAddr::V6(ref v6) => { // If IPv6 is not supported. Try to map it back to IPv4. if !ip_stack_caps.support_ipv6 || !ip_stack_caps.support_ipv4_mapped_ipv6 { match v6.ip().to_ipv4_mapped() { Some(v4) => SocketAddr::new(v4.into(), v6.port()), None => sa, } } else { sa } } } } Address::DomainNameAddress(..) => { let err = io::Error::new( ErrorKind::InvalidInput, "redir destination must not be an domain name address", ); return Err(err); } }; let inbound = { let mut cache = self.inbound_cache.cache.lock().await; match cache.get(&addr) { Some(socket) => socket.clone(), _ => { // Create a socket binds to destination addr // This only works for systems that supports binding to non-local addresses // // This socket has to set SO_REUSEADDR and SO_REUSEPORT. // Outbound addresses could be connected from different source addresses. let inbound = UdpRedirSocket::bind_nonlocal(self.redir_ty, addr, &self.socket_opts)?; // UDP socket could be shared between threads and is safe to be manipulated by multiple threads let inbound = Arc::new(inbound); cache.insert(addr, inbound.clone()); inbound } } }; // Convert peer_addr (client)'s address family to match remote_addr (target) match (addr, peer_addr) { (SocketAddr::V4(..), SocketAddr::V4(..)) | (SocketAddr::V6(..), SocketAddr::V6(..)) => {} (SocketAddr::V4(..), SocketAddr::V6(v6_peer_addr)) => { if let Some(v4_ip) = v6_peer_addr.ip().to_ipv4_mapped() { peer_addr = SocketAddr::new(v4_ip.into(), v6_peer_addr.port()); } else { warn!( "udp redir send back {} bytes, remote: {}, peer: {}, protocol not match", data.len(), addr, peer_addr ); } } (SocketAddr::V6(..), SocketAddr::V4(v4_peer_addr)) => { peer_addr = SocketAddr::new(v4_peer_addr.ip().to_ipv6_mapped().into(), v4_peer_addr.port()); } } match inbound.send_to(data, peer_addr).await { Ok(n) => { if n < data.len() { warn!( "udp redir send back data (actual: {} bytes, sent: {} bytes), remote: {}, peer: {}", n, data.len(), remote_addr, peer_addr ); } trace!( "udp redir send back data {} bytes, remote: {}, peer: {}, socket_opts: {:?}", n, remote_addr, peer_addr, self.socket_opts ); Ok(()) } Err(err) => Err(err), } } } pub struct RedirUdpServer { context: Arc, redir_ty: RedirType, time_to_live: Option, capacity: Option, listener: UdpRedirSocket, balancer: PingBalancer, } impl RedirUdpServer { pub(crate) async fn new( context: Arc, redir_ty: RedirType, client_config: &ServerAddr, time_to_live: Option, capacity: Option, balancer: PingBalancer, ) -> io::Result { let listener = match *client_config { ServerAddr::SocketAddr(ref saddr) => UdpRedirSocket::listen(redir_ty, *saddr)?, ServerAddr::DomainName(ref dname, port) => { lookup_then!(context.context_ref(), dname, port, |addr| { UdpRedirSocket::listen(redir_ty, addr) })? .1 } }; Ok(Self { context, redir_ty, time_to_live, capacity, listener, balancer, }) } pub async fn run(self) -> io::Result<()> { let local_addr = self.listener.local_addr().expect("determine port bound to"); info!( "shadowsocks UDP redirect ({}) listening on {}", self.redir_ty, local_addr ); #[allow(clippy::needless_update)] let (mut manager, cleanup_interval, mut keepalive_rx) = UdpAssociationManager::new( self.context.clone(), UdpRedirInboundWriter::new(self.redir_ty, self.context.connect_opts_ref()), self.time_to_live, self.capacity, self.balancer, ); let mut pkt_buf = [0u8; MAXIMUM_UDP_PAYLOAD_SIZE]; let mut cleanup_timer = time::interval(cleanup_interval); loop { tokio::select! { _ = cleanup_timer.tick() => { // cleanup expired associations. iter() will remove expired elements manager.cleanup_expired().await; } peer_addr_opt = keepalive_rx.recv() => { let peer_addr = peer_addr_opt.expect("keep-alive channel closed unexpectedly"); manager.keep_alive(&peer_addr).await; } recv_result = self.listener.recv_dest_from(&mut pkt_buf) => { let (recv_len, src, mut dst) = match recv_result { Ok(o) => o, Err(err) => { error!("recv_dest_from failed with err: {}", err); continue; } }; // Packet length is limited by MAXIMUM_UDP_PAYLOAD_SIZE, excess bytes will be discarded. // Copy bytes, because udp_associate runs in another tokio Task let pkt = &pkt_buf[..recv_len]; trace!( "received UDP packet from {}, destination {}, length {} bytes", src, dst, recv_len ); if recv_len == 0 { // For windows, it will generate a ICMP Port Unreachable Message // https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-recvfrom // Which will result in recv_from return 0. // // It cannot be solved here, because `WSAGetLastError` is already set. // // See `relay::udprelay::utils::create_socket` for more detail. continue; } // Try to convert IPv4 mapped IPv6 address for dual-stack mode. if let SocketAddr::V6(ref a) = dst && let Some(v4) = to_ipv4_mapped(a.ip()) { dst = SocketAddr::new(IpAddr::from(v4), a.port()); } if let Err(err) = manager.send_to(src, Address::from(dst), pkt).await { debug!( "udp packet relay {} -> {} with {} bytes failed, error: {}", src, dst, pkt.len(), err ); } } } } } } ================================================ FILE: crates/shadowsocks-service/src/local/redir/udprelay/sys/mod.rs ================================================ use cfg_if::cfg_if; cfg_if! { if #[cfg(unix)] { mod unix; pub use self::unix::*; } else if #[cfg(windows)] { mod windows; pub use self::windows::*; } else { compile_error!("UDP Relay is not supported in current platform"); } } ================================================ FILE: crates/shadowsocks-service/src/local/redir/udprelay/sys/unix/freebsd.rs ================================================ use std::{ io::{self, Error, ErrorKind}, mem, net::{SocketAddr, UdpSocket}, os::unix::io::AsRawFd, ptr, task::{Context, Poll}, }; use futures::{future::poll_fn, ready}; use log::{error, trace, warn}; use shadowsocks::net::is_dual_stack_addr; use socket2::{Domain, Protocol, SockAddr, Socket, Type}; use tokio::io::unix::AsyncFd; use crate::{ config::RedirType, local::redir::{ redir_ext::{RedirSocketOpts, UdpSocketRedir}, sys::set_ipv6_only, }, }; pub struct UdpRedirSocket { io: AsyncFd, } impl UdpRedirSocket { /// Create a new UDP socket binded to `addr` /// /// This will allow listening to `addr` that is not in local host pub fn listen(ty: RedirType, addr: SocketAddr) -> io::Result { UdpRedirSocket::bind(ty, addr, false) } /// Create a new UDP socket binded to `addr` /// /// This will allow binding to `addr` that is not in local host pub fn bind_nonlocal(ty: RedirType, addr: SocketAddr, _: &RedirSocketOpts) -> io::Result { UdpRedirSocket::bind(ty, addr, true) } fn bind(ty: RedirType, addr: SocketAddr, reuse_port: bool) -> io::Result { if ty == RedirType::NotSupported { return Err(Error::new( ErrorKind::InvalidInput, "not supported udp transparent proxy type", )); } let socket = Socket::new(Domain::for_address(addr), Type::DGRAM, Some(Protocol::UDP))?; set_socket_before_bind(&addr, &socket)?; socket.set_nonblocking(true)?; socket.set_reuse_address(true)?; if reuse_port { if let Err(err) = socket.set_reuse_port(true) { if let Some(libc::ENOPROTOOPT) = err.raw_os_error() { trace!("failed to set SO_REUSEPORT, error: {}", err); } else { error!("failed to set SO_REUSEPORT, error: {}", err); return Err(err); } } } let sock_addr = SockAddr::from(addr); if is_dual_stack_addr(&addr) { // set IP_ORIGDSTADDR before bind() // NOTE: FreeBSD doesn't allow setting IPPROTO_IP level on an IPv6 socket // // set_ip_origdstaddr(libc::IPPROTO_IP, &socket)?; // set_disable_ip_fragmentation(libc::IPPROTO_IP, &socket)?; match set_ipv6_only(&socket, false) { Ok(..) => { if let Err(err) = socket.bind(&sock_addr) { warn!( "bind() dual-stack address {} failed, error: {}, fallback to IPV6_V6ONLY=true", addr, err ); if let Err(err) = set_ipv6_only(&socket, true) { warn!( "set IPV6_V6ONLY=true failed, error: {}, bind() to {} directly", err, addr ); } socket.bind(&sock_addr)?; } } Err(err) => { warn!( "set IPV6_V6ONLY=false failed, error: {}, bind() to {} directly", err, addr ); socket.bind(&sock_addr)?; } } } else { socket.bind(&sock_addr)?; } let io = AsyncFd::new(socket.into())?; Ok(UdpRedirSocket { io }) } /// Send data to the socket to the given target address pub async fn send_to(&self, buf: &[u8], target: SocketAddr) -> io::Result { poll_fn(|cx| self.poll_send_to(cx, buf, target)).await } fn poll_send_to(&self, cx: &mut Context<'_>, buf: &[u8], target: SocketAddr) -> Poll> { loop { let mut write_guard = ready!(self.io.poll_write_ready(cx))?; match self.io.get_ref().send_to(buf, target) { Err(ref e) if e.kind() == ErrorKind::WouldBlock => { write_guard.clear_ready(); } x => return Poll::Ready(x), } } } /// Returns the local address that this socket is bound to. pub fn local_addr(&self) -> io::Result { self.io.get_ref().local_addr() } } impl UdpSocketRedir for UdpRedirSocket { fn poll_recv_dest_from( &self, cx: &mut Context<'_>, buf: &mut [u8], ) -> Poll> { loop { let mut read_guard = ready!(self.io.poll_read_ready(cx))?; match recv_dest_from(self.io.get_ref(), buf) { Err(ref e) if e.kind() == ErrorKind::WouldBlock => { read_guard.clear_ready(); } x => return Poll::Ready(x), } } } } fn set_bindany(level: libc::c_int, socket: &Socket) -> io::Result<()> { let fd = socket.as_raw_fd(); let enable: libc::c_int = 1; // https://www.freebsd.org/cgi/man.cgi?query=ip&sektion=4&manpath=FreeBSD+9.0-RELEASE let opt = match level { libc::IPPROTO_IP => libc::IP_BINDANY, libc::IPPROTO_IPV6 => libc::IPV6_BINDANY, _ => unreachable!("level can only be IPPROTO_IP or IPPROTO_IPV6"), }; unsafe { let ret = libc::setsockopt( fd, level, opt, &enable as *const _ as *const _, mem::size_of_val(&enable) as libc::socklen_t, ); if ret != 0 { return Err(Error::last_os_error()); } } Ok(()) } fn set_ip_origdstaddr(level: libc::c_int, socket: &Socket) -> io::Result<()> { // https://www.freebsd.org/cgi/man.cgi?query=ip&sektion=4&manpath=FreeBSD+9.0-RELEASE let fd = socket.as_raw_fd(); let enable: libc::c_int = 1; let opt = match level { libc::IPPROTO_IP => libc::IP_RECVORIGDSTADDR, libc::IPPROTO_IPV6 => libc::IPV6_RECVORIGDSTADDR, _ => unreachable!("level can only be IPPROTO_IP or IPPROTO_IPV6"), }; unsafe { let ret = libc::setsockopt( fd, level, opt, &enable as *const _ as *const _, mem::size_of_val(&enable) as libc::socklen_t, ); if ret != 0 { return Err(Error::last_os_error()); } } Ok(()) } fn set_disable_ip_fragmentation(level: libc::c_int, socket: &Socket) -> io::Result<()> { // https://www.freebsd.org/cgi/man.cgi?query=ip&sektion=4&manpath=FreeBSD+9.0-RELEASE // sys/netinet/in.h // const IP_DONTFRAG: libc::c_int = 67; // don't fragment packet // // sys/netinet6/in6.h // const IPV6_DONTFRAG: libc::c_int = 62; // bool; disable IPv6 fragmentation let enable: libc::c_int = 1; let opt = match level { libc::IPPROTO_IP => libc::IP_DONTFRAG, libc::IPPROTO_IPV6 => libc::IPV6_DONTFRAG, _ => unreachable!("level can only be IPPROTO_IP or IPPROTO_IPV6"), }; unsafe { let ret = libc::setsockopt( socket.as_raw_fd(), level, opt, &enable as *const _ as *const _, mem::size_of_val(&enable) as libc::socklen_t, ); if ret < 0 { return Err(io::Error::last_os_error()); } } Ok(()) } fn set_socket_before_bind(addr: &SocketAddr, socket: &Socket) -> io::Result<()> { // https://www.freebsd.org/cgi/man.cgi?query=ip&sektion=4&manpath=FreeBSD+9.0-RELEASE let level = match *addr { SocketAddr::V4(..) => libc::IPPROTO_IP, SocketAddr::V6(..) => libc::IPPROTO_IPV6, }; // 1. BINDANY set_bindany(level, socket)?; // 2. set ORIGDSTADDR for retrieving original destination address set_ip_origdstaddr(level, socket)?; // 3. disable IP fragmentation set_disable_ip_fragmentation(level, socket)?; Ok(()) } fn get_destination_addr(msg: &libc::msghdr) -> io::Result { // https://www.freebsd.org/cgi/man.cgi?ip(4) // // Called `recvmsg` with `IP_ORIGDSTADDR` set unsafe { let (_, addr) = SockAddr::try_init(|dst_addr, dst_addr_len| { let mut cmsg: *mut libc::cmsghdr = libc::CMSG_FIRSTHDR(msg); while !cmsg.is_null() { let rcmsg = &*cmsg; match (rcmsg.cmsg_level, rcmsg.cmsg_type) { (libc::IPPROTO_IP, libc::IP_ORIGDSTADDR) => { ptr::copy_nonoverlapping( libc::CMSG_DATA(cmsg), dst_addr as *mut _, mem::size_of::(), ); *dst_addr_len = mem::size_of::() as libc::socklen_t; return Ok(()); } (libc::IPPROTO_IPV6, libc::IPV6_ORIGDSTADDR) => { ptr::copy_nonoverlapping( libc::CMSG_DATA(cmsg), dst_addr as *mut _, mem::size_of::(), ); *dst_addr_len = mem::size_of::() as libc::socklen_t; return Ok(()); } _ => {} } cmsg = libc::CMSG_NXTHDR(msg, cmsg); } let err = Error::new(ErrorKind::InvalidData, "missing destination address in msghdr"); Err(err) })?; Ok(addr.as_socket().expect("SocketAddr")) } } fn recv_dest_from(socket: &UdpSocket, buf: &mut [u8]) -> io::Result<(usize, SocketAddr, SocketAddr)> { unsafe { let mut control_buf = [0u8; 64]; let mut src_addr: libc::sockaddr_storage = mem::zeroed(); let mut msg: libc::msghdr = mem::zeroed(); msg.msg_name = &mut src_addr as *mut _ as *mut _; msg.msg_namelen = mem::size_of_val(&src_addr) as libc::socklen_t; let mut iov = libc::iovec { iov_base: buf.as_mut_ptr() as *mut _, iov_len: buf.len() as libc::size_t, }; msg.msg_iov = &mut iov; msg.msg_iovlen = 1; msg.msg_control = control_buf.as_mut_ptr() as *mut _; msg.msg_controllen = control_buf.len() as libc::socklen_t; let fd = socket.as_raw_fd(); let ret = libc::recvmsg(fd, &mut msg, 0); if ret < 0 { return Err(Error::last_os_error()); } let (_, src_saddr) = SockAddr::try_init(|a, l| { ptr::copy_nonoverlapping(msg.msg_name, a as *mut _, msg.msg_namelen as usize); *l = msg.msg_namelen; Ok(()) })?; Ok(( ret as usize, src_saddr.as_socket().expect("SocketAddr"), get_destination_addr(&msg)?, )) } } ================================================ FILE: crates/shadowsocks-service/src/local/redir/udprelay/sys/unix/linux.rs ================================================ use std::{ io::{self, Error, ErrorKind}, mem, net::{SocketAddr, UdpSocket}, os::unix::io::{AsRawFd, RawFd}, ptr, task::{Context, Poll}, }; use cfg_if::cfg_if; use futures::{future::poll_fn, ready}; use log::{error, trace, warn}; use shadowsocks::net::is_dual_stack_addr; use socket2::{Domain, Protocol, SockAddr, Socket, Type}; use tokio::io::unix::AsyncFd; use crate::{ config::RedirType, local::redir::{ redir_ext::{RedirSocketOpts, UdpSocketRedir}, sys::set_ipv6_only, }, }; pub struct UdpRedirSocket { io: AsyncFd, } impl UdpRedirSocket { /// Create a new UDP socket binded to `addr` /// /// This will allow listening to `addr` that is not in local host pub fn listen(ty: RedirType, addr: SocketAddr) -> io::Result { Self::bind(ty, addr, false) } /// Create a new UDP socket binded to `addr` /// /// This will allow binding to `addr` that is not in local host pub fn bind_nonlocal(ty: RedirType, addr: SocketAddr, redir_opts: &RedirSocketOpts) -> io::Result { let socket = Self::bind(ty, addr, true)?; if let Some(mark) = redir_opts.fwmark { let ret = unsafe { libc::setsockopt( socket.as_raw_fd(), libc::SOL_SOCKET, libc::SO_MARK, &mark as *const _ as *const _, mem::size_of_val(&mark) as libc::socklen_t, ) }; if ret != 0 { return Err(Error::last_os_error()); } } Ok(socket) } fn bind(ty: RedirType, addr: SocketAddr, reuse_port: bool) -> io::Result { if ty != RedirType::TProxy { return Err(Error::new( ErrorKind::InvalidInput, "not supported udp transparent proxy type", )); } let socket = Socket::new(Domain::for_address(addr), Type::DGRAM, Some(Protocol::UDP))?; set_socket_before_bind(&addr, &socket)?; socket.set_nonblocking(true)?; socket.set_reuse_address(true)?; if reuse_port && let Err(err) = socket.set_reuse_port(true) { if let Some(libc::ENOPROTOOPT) = err.raw_os_error() { // SO_REUSEPORT is supported after 3.9 trace!("failed to set SO_REUSEPORT, error: {}", err); } else { error!("failed to set SO_REUSEPORT, error: {}", err); return Err(err); } } let sock_addr = SockAddr::from(addr); if is_dual_stack_addr(&addr) { // set IP_TRANSPARENT & IP_RECVORIGDSTADDR before bind() set_ip_transparent(libc::SOL_IP, &socket)?; set_ip_recvorigdstaddr(libc::SOL_IP, &socket)?; set_ip_mtu_discover(libc::IPPROTO_IP, &socket)?; match set_ipv6_only(&socket, false) { Ok(..) => { if let Err(err) = socket.bind(&sock_addr) { warn!( "bind() dual-stack address {} failed, error: {}, fallback to IPV6_V6ONLY=true", addr, err ); if let Err(err) = set_ipv6_only(&socket, true) { warn!( "set IPV6_V6ONLY=true failed, error: {}, bind() to {} directly", err, addr ); } socket.bind(&sock_addr)?; } } Err(err) => { warn!( "set IPV6_V6ONLY=false failed, error: {}, bind() to {} directly", err, addr ); socket.bind(&sock_addr)?; } } } else { socket.bind(&sock_addr)?; } let io = AsyncFd::new(socket.into())?; Ok(Self { io }) } /// Send data to the socket to the given target address pub async fn send_to(&self, buf: &[u8], target: SocketAddr) -> io::Result { poll_fn(|cx| self.poll_send_to(cx, buf, target)).await } fn poll_send_to(&self, cx: &mut Context<'_>, buf: &[u8], target: SocketAddr) -> Poll> { loop { let mut write_guard = ready!(self.io.poll_write_ready(cx))?; match self.io.get_ref().send_to(buf, target) { Err(ref e) if e.kind() == ErrorKind::WouldBlock => { write_guard.clear_ready(); } x => return Poll::Ready(x), } } } /// Returns the local address that this socket is bound to. pub fn local_addr(&self) -> io::Result { self.io.get_ref().local_addr() } } impl UdpSocketRedir for UdpRedirSocket { fn poll_recv_dest_from( &self, cx: &mut Context<'_>, buf: &mut [u8], ) -> Poll> { loop { let mut read_guard = ready!(self.io.poll_read_ready(cx))?; match recv_dest_from(self.io.get_ref(), buf) { Err(ref e) if e.kind() == ErrorKind::WouldBlock => { read_guard.clear_ready(); } x => return Poll::Ready(x), } } } } impl AsRawFd for UdpRedirSocket { fn as_raw_fd(&self) -> RawFd { self.io.as_raw_fd() } } fn set_ip_transparent(level: libc::c_int, socket: &Socket) -> io::Result<()> { let fd = socket.as_raw_fd(); let opt = match level { libc::SOL_IP => libc::IP_TRANSPARENT, libc::SOL_IPV6 => libc::IPV6_TRANSPARENT, _ => unreachable!("invalid sockopt level {}", level), }; let enable: libc::c_int = 1; unsafe { let ret = libc::setsockopt( fd, level, opt, &enable as *const _ as *const _, mem::size_of_val(&enable) as libc::socklen_t, ); if ret != 0 { return Err(Error::last_os_error()); } } Ok(()) } fn set_ip_recvorigdstaddr(level: libc::c_int, socket: &Socket) -> io::Result<()> { let fd = socket.as_raw_fd(); let opt = match level { libc::SOL_IP => libc::IP_RECVORIGDSTADDR, libc::SOL_IPV6 => libc::IPV6_RECVORIGDSTADDR, _ => unreachable!("invalid sockopt level {}", level), }; let enable: libc::c_int = 1; unsafe { let ret = libc::setsockopt( fd, level, opt, &enable as *const _ as *const _, mem::size_of_val(&enable) as libc::socklen_t, ); if ret != 0 { return Err(Error::last_os_error()); } } Ok(()) } fn set_ip_mtu_discover(level: libc::c_int, socket: &Socket) -> io::Result<()> { let fd = socket.as_raw_fd(); let opt = match level { libc::IPPROTO_IP => libc::IP_MTU_DISCOVER, libc::IPPROTO_IPV6 => libc::IPV6_MTU_DISCOVER, _ => unreachable!("invalid sockopt level {}", level), }; let value: libc::c_int = libc::IP_PMTUDISC_DO; unsafe { let ret = libc::setsockopt( fd, level, opt, &value as *const _ as *const _, mem::size_of_val(&value) as libc::socklen_t, ); if ret < 0 { return Err(io::Error::last_os_error()); } } Ok(()) } fn set_socket_before_bind(addr: &SocketAddr, socket: &Socket) -> io::Result<()> { // Set IP_TRANSPARENT, IPV6_TRANSPARENT to allow binding to non-local addresses let level = match *addr { SocketAddr::V4(..) => libc::SOL_IP, SocketAddr::V6(..) => libc::SOL_IPV6, }; set_ip_transparent(level, socket)?; set_ip_recvorigdstaddr(level, socket)?; set_ip_mtu_discover(level, socket)?; Ok(()) } fn get_destination_addr(msg: &libc::msghdr) -> io::Result { unsafe { let (_, addr) = SockAddr::try_init(|dst_addr, dst_addr_len| { let mut cmsg: *mut libc::cmsghdr = libc::CMSG_FIRSTHDR(msg); while !cmsg.is_null() { let rcmsg = &*cmsg; match (rcmsg.cmsg_level, rcmsg.cmsg_type) { (libc::SOL_IP, libc::IP_RECVORIGDSTADDR) => { ptr::copy( libc::CMSG_DATA(cmsg), dst_addr as *mut _, mem::size_of::(), ); *dst_addr_len = mem::size_of::() as libc::socklen_t; return Ok(()); } (libc::SOL_IPV6, libc::IPV6_RECVORIGDSTADDR) => { ptr::copy( libc::CMSG_DATA(cmsg), dst_addr as *mut _, mem::size_of::(), ); *dst_addr_len = mem::size_of::() as libc::socklen_t; return Ok(()); } _ => {} } cmsg = libc::CMSG_NXTHDR(msg, cmsg); } let err = Error::new(ErrorKind::InvalidData, "missing destination address in msghdr"); Err(err) })?; Ok(addr.as_socket().expect("SocketAddr")) } } fn recv_dest_from(socket: &UdpSocket, buf: &mut [u8]) -> io::Result<(usize, SocketAddr, SocketAddr)> { unsafe { let mut control_buf = [0u8; 64]; let mut src_addr: libc::sockaddr_storage = mem::zeroed(); let mut msg: libc::msghdr = mem::zeroed(); msg.msg_name = &mut src_addr as *mut _ as *mut _; msg.msg_namelen = mem::size_of_val(&src_addr) as libc::socklen_t; let mut iov = libc::iovec { iov_base: buf.as_mut_ptr() as *mut _, iov_len: buf.len() as libc::size_t, }; msg.msg_iov = &mut iov; msg.msg_iovlen = 1; msg.msg_control = control_buf.as_mut_ptr() as *mut _; cfg_if! { if #[cfg(any(target_env = "musl", all(target_env = "uclibc", target_arch = "arm")))] { msg.msg_controllen = control_buf.len() as libc::socklen_t; } else { msg.msg_controllen = control_buf.len() as libc::size_t; } } let fd = socket.as_raw_fd(); let ret = libc::recvmsg(fd, &mut msg, 0); if ret < 0 { return Err(Error::last_os_error()); } let (_, src_saddr) = SockAddr::try_init(|a, l| { ptr::copy_nonoverlapping(msg.msg_name, a as *mut _, msg.msg_namelen as usize); *l = msg.msg_namelen; Ok(()) })?; Ok(( ret as usize, src_saddr.as_socket().expect("SocketAddr"), get_destination_addr(&msg)?, )) } } ================================================ FILE: crates/shadowsocks-service/src/local/redir/udprelay/sys/unix/macos.rs ================================================ use std::{ io::{self, Error, ErrorKind}, mem, net::{SocketAddr, UdpSocket}, os::unix::io::AsRawFd, task::{Context, Poll}, }; use futures::{future::poll_fn, ready}; use log::{error, trace, warn}; use shadowsocks::net::is_dual_stack_addr; use socket2::{Domain, Protocol, SockAddr, Socket, Type}; use tokio::io::unix::AsyncFd; use crate::{ config::RedirType, local::redir::{ redir_ext::{RedirSocketOpts, UdpSocketRedir}, sys::{bsd_pf::PF, set_ipv6_only}, }, }; pub struct UdpRedirSocket { io: AsyncFd, } impl UdpRedirSocket { /// Create a new UDP socket binded to `addr` /// /// This will allow listening to `addr` that is not in local host pub fn listen(ty: RedirType, addr: SocketAddr) -> io::Result { UdpRedirSocket::bind(ty, addr, false) } /// Create a new UDP socket binded to `addr` /// /// This will allow binding to `addr` that is not in local host pub fn bind_nonlocal(ty: RedirType, addr: SocketAddr, _: &RedirSocketOpts) -> io::Result { UdpRedirSocket::bind(ty, addr, true) } fn bind(ty: RedirType, addr: SocketAddr, reuse_port: bool) -> io::Result { if ty == RedirType::NotSupported { return Err(Error::new( ErrorKind::InvalidInput, "not supported udp transparent proxy type", )); } let socket = Socket::new(Domain::for_address(addr), Type::DGRAM, Some(Protocol::UDP))?; set_socket_before_bind(&addr, &socket)?; socket.set_nonblocking(true)?; socket.set_reuse_address(true)?; if reuse_port && let Err(err) = socket.set_reuse_port(true) { if let Some(libc::ENOPROTOOPT) = err.raw_os_error() { trace!("failed to set SO_REUSEPORT, error: {}", err); } else { error!("failed to set SO_REUSEPORT, error: {}", err); return Err(err); } } let sock_addr = SockAddr::from(addr); if is_dual_stack_addr(&addr) { // set IP_ORIGDSTADDR before bind() match set_ipv6_only(&socket, false) { Ok(..) => { if let Err(err) = socket.bind(&sock_addr) { warn!( "bind() dual-stack address {} failed, error: {}, fallback to IPV6_V6ONLY=true", addr, err ); if let Err(err) = set_ipv6_only(&socket, true) { warn!( "set IPV6_V6ONLY=true failed, error: {}, bind() to {} directly", err, addr ); } socket.bind(&sock_addr)?; } } Err(err) => { warn!( "set IPV6_V6ONLY=false failed, error: {}, bind() to {} directly", err, addr ); socket.bind(&sock_addr)?; } } } else { socket.bind(&sock_addr)?; } let io = AsyncFd::new(socket.into())?; Ok(UdpRedirSocket { io }) } /// Send data to the socket to the given target address pub async fn send_to(&self, buf: &[u8], target: SocketAddr) -> io::Result { poll_fn(|cx| self.poll_send_to(cx, buf, target)).await } fn poll_send_to(&self, cx: &mut Context<'_>, buf: &[u8], target: SocketAddr) -> Poll> { loop { let mut write_guard = ready!(self.io.poll_write_ready(cx))?; match self.io.get_ref().send_to(buf, target) { Err(ref e) if e.kind() == ErrorKind::WouldBlock => { write_guard.clear_ready(); } x => return Poll::Ready(x), } } } /// Returns the local address that this socket is bound to. pub fn local_addr(&self) -> io::Result { self.io.get_ref().local_addr() } } impl UdpSocketRedir for UdpRedirSocket { fn poll_recv_dest_from( &self, cx: &mut Context<'_>, buf: &mut [u8], ) -> Poll> { loop { let mut read_guard = ready!(self.io.poll_read_ready(cx))?; let (n, peer_addr) = match self.io.get_ref().recv_from(buf) { Err(ref e) if e.kind() == ErrorKind::WouldBlock => { read_guard.clear_ready(); continue; } Err(e) => return Err(e).into(), Ok(x) => x, }; let bind_addr = self.local_addr()?; let actual_addr = PF.natlook(&bind_addr, &peer_addr, Protocol::UDP)?; return Ok((n, peer_addr, actual_addr)).into(); } } } fn set_disable_ip_fragmentation(level: libc::c_int, socket: &Socket) -> io::Result<()> { // https://www.freebsd.org/cgi/man.cgi?query=ip&sektion=4&manpath=FreeBSD+9.0-RELEASE // sys/netinet/in.h // const IP_DONTFRAG: libc::c_int = 67; // don't fragment packet // // sys/netinet6/in6.h // const IPV6_DONTFRAG: libc::c_int = 62; // bool; disable IPv6 fragmentation let enable: libc::c_int = 1; let opt = match level { libc::IPPROTO_IP => libc::IP_DONTFRAG, libc::IPPROTO_IPV6 => libc::IPV6_DONTFRAG, _ => unreachable!("level can only be IPPROTO_IP or IPPROTO_IPV6"), }; unsafe { let ret = libc::setsockopt( socket.as_raw_fd(), level, opt, &enable as *const _ as *const _, mem::size_of_val(&enable) as libc::socklen_t, ); if ret < 0 { return Err(io::Error::last_os_error()); } } Ok(()) } fn set_socket_before_bind(addr: &SocketAddr, socket: &Socket) -> io::Result<()> { // https://www.freebsd.org/cgi/man.cgi?query=ip&sektion=4&manpath=FreeBSD+9.0-RELEASE let level = match *addr { SocketAddr::V4(..) => libc::IPPROTO_IP, SocketAddr::V6(..) => libc::IPPROTO_IPV6, }; // 1. disable IP fragmentation set_disable_ip_fragmentation(level, socket)?; Ok(()) } ================================================ FILE: crates/shadowsocks-service/src/local/redir/udprelay/sys/unix/mod.rs ================================================ use cfg_if::cfg_if; cfg_if! { if #[cfg(any(target_os = "linux", target_os = "android"))] { mod linux; pub use self::linux::*; } else if #[cfg(target_os = "macos")] { mod macos; pub use self::macos::*; } else if #[cfg(any(target_os = "freebsd"))] { mod freebsd; pub use self::freebsd::*; } else if #[cfg(target_os = "openbsd")] { mod openbsd; pub use self::openbsd::*; } else { mod not_supported; pub use self::not_supported::*; } } ================================================ FILE: crates/shadowsocks-service/src/local/redir/udprelay/sys/unix/not_supported.rs ================================================ use std::{ io, net::SocketAddr, task::{Context, Poll}, }; use crate::{ config::RedirType, local::redir::redir_ext::{RedirSocketOpts, UdpSocketRedir}, }; pub struct UdpRedirSocket; impl UdpRedirSocket { /// Create a new UDP socket binded to `addr` /// /// This will allow listening to `addr` that is not in local host pub fn listen(_ty: RedirType, _addr: SocketAddr) -> io::Result { unimplemented!("UDP transparent proxy is not supported on this platform") } /// Create a new UDP socket binded to `addr` /// /// This will allow binding to `addr` that is not in local host pub fn bind_nonlocal( _ty: RedirType, _addr: SocketAddr, _redir_opts: &RedirSocketOpts, ) -> io::Result { unimplemented!("UDP transparent proxy is not supported on this platform") } /// Send data to the socket to the given target address pub async fn send_to(&self, _buf: &[u8], _target: SocketAddr) -> io::Result { unimplemented!("UDP transparent proxy is not supported on this platform") } /// Returns the local address that this socket is bound to. pub fn local_addr(&self) -> io::Result { unimplemented!("UDP transparent proxy is not supported on this platform") } } impl UdpSocketRedir for UdpRedirSocket { fn poll_recv_dest_from( &self, _cx: &mut Context<'_>, _buf: &mut [u8], ) -> Poll> { unimplemented!("UDP transparent proxy is not supported on this platform") } } ================================================ FILE: crates/shadowsocks-service/src/local/redir/udprelay/sys/unix/openbsd.rs ================================================ use std::{ io::{self, Error, ErrorKind}, mem, net::{SocketAddr, UdpSocket}, os::unix::io::AsRawFd, ptr, task::{Context, Poll}, }; use futures::{future::poll_fn, ready}; use log::{error, trace, warn}; use shadowsocks::net::is_dual_stack_addr; use socket2::{Domain, Protocol, SockAddr, Socket, Type}; use tokio::io::unix::AsyncFd; use crate::{ config::RedirType, local::redir::{ redir_ext::{RedirSocketOpts, UdpSocketRedir}, sys::set_ipv6_only, }, }; const IP_RECVDSTPORT: i32 = 33; // Temporary workaround until libc supports this const IPV6_RECVDSTPORT: i32 = 64; // Temporary workaround until libc supports this pub struct UdpRedirSocket { io: AsyncFd, } impl UdpRedirSocket { /// Create a new UDP socket binded to `addr` /// /// This will allow listening to `addr` that is not in local host pub fn listen(ty: RedirType, addr: SocketAddr) -> io::Result { UdpRedirSocket::bind(ty, addr, false) } /// Create a new UDP socket binded to `addr` /// /// This will allow binding to `addr` that is not in local host pub fn bind_nonlocal(ty: RedirType, addr: SocketAddr, _: &RedirSocketOpts) -> io::Result { UdpRedirSocket::bind(ty, addr, true) } fn bind(ty: RedirType, addr: SocketAddr, reuse_port: bool) -> io::Result { if ty == RedirType::NotSupported { return Err(Error::new( ErrorKind::InvalidInput, "not supported udp transparent proxy type", )); } let socket = Socket::new(Domain::for_address(addr), Type::DGRAM, Some(Protocol::UDP))?; set_socket_before_bind(&addr, &socket)?; socket.set_nonblocking(true)?; socket.set_reuse_address(true)?; if reuse_port { if let Err(err) = socket.set_reuse_port(true) { if let Some(libc::ENOPROTOOPT) = err.raw_os_error() { trace!("failed to set SO_REUSEPORT, error: {}", err); } else { error!("failed to set SO_REUSEPORT, error: {}", err); return Err(err); } } } let sock_addr = SockAddr::from(addr); if is_dual_stack_addr(&addr) { // set IP_ORIGDSTADDR before bind() // NOTE: FreeBSD doesn't allow setting IPPROTO_IP level on an IPv6 socket // // set_ip_origdstaddr(libc::IPPROTO_IP, &socket)?; // set_disable_ip_fragmentation(libc::IPPROTO_IP, &socket)?; match set_ipv6_only(&socket, false) { Ok(..) => { if let Err(err) = socket.bind(&sock_addr) { warn!( "bind() dual-stack address {} failed, error: {}, fallback to IPV6_V6ONLY=true", addr, err ); if let Err(err) = set_ipv6_only(&socket, true) { warn!( "set IPV6_V6ONLY=true failed, error: {}, bind() to {} directly", err, addr ); } socket.bind(&sock_addr)?; } } Err(err) => { warn!( "set IPV6_V6ONLY=false failed, error: {}, bind() to {} directly", err, addr ); socket.bind(&sock_addr)?; } } } else { socket.bind(&sock_addr)?; } let io = AsyncFd::new(socket.into())?; Ok(UdpRedirSocket { io }) } /// Send data to the socket to the given target address pub async fn send_to(&self, buf: &[u8], target: SocketAddr) -> io::Result { poll_fn(|cx| self.poll_send_to(cx, buf, target)).await } fn poll_send_to(&self, cx: &mut Context<'_>, buf: &[u8], target: SocketAddr) -> Poll> { loop { let mut write_guard = ready!(self.io.poll_write_ready(cx))?; match self.io.get_ref().send_to(buf, target) { Err(ref e) if e.kind() == ErrorKind::WouldBlock => { write_guard.clear_ready(); } x => return Poll::Ready(x), } } } /// Returns the local address that this socket is bound to. pub fn local_addr(&self) -> io::Result { self.io.get_ref().local_addr() } } impl UdpSocketRedir for UdpRedirSocket { fn poll_recv_dest_from( &self, cx: &mut Context<'_>, buf: &mut [u8], ) -> Poll> { loop { let mut read_guard = ready!(self.io.poll_read_ready(cx))?; match recv_dest_from(self.io.get_ref(), buf) { Err(ref e) if e.kind() == ErrorKind::WouldBlock => { read_guard.clear_ready(); } x => return Poll::Ready(x), } } } } fn set_bindany(_level: libc::c_int, socket: &Socket) -> io::Result<()> { let fd = socket.as_raw_fd(); let enable: libc::c_int = 1; // https://man.openbsd.org/getsockopt.2 unsafe { let ret = libc::setsockopt( fd, libc::SOL_SOCKET, libc::SO_BINDANY, &enable as *const _ as *const _, mem::size_of_val(&enable) as libc::socklen_t, ); if ret != 0 { return Err(Error::last_os_error()); } } Ok(()) } fn set_ip_origdstaddr(level: libc::c_int, socket: &Socket) -> io::Result<()> { // https://man.openbsd.org/pf.conf let fd = socket.as_raw_fd(); let enable: libc::c_int = 1; let opt = match level { libc::IPPROTO_IP => libc::IP_RECVDSTADDR, libc::IPPROTO_IPV6 => libc::IPV6_RECVPKTINFO, _ => unreachable!("level can only be IPPROTO_IP or IPPROTO_IPV6"), }; unsafe { let ret = libc::setsockopt( fd, level, opt, &enable as *const _ as *const _, mem::size_of_val(&enable) as libc::socklen_t, ); if ret != 0 { return Err(Error::last_os_error()); } } let opt2 = match level { libc::IPPROTO_IP => IP_RECVDSTPORT, libc::IPPROTO_IPV6 => IPV6_RECVDSTPORT, _ => unreachable!("level can only be IPPROTO_IP or IPPROTO_IPV6"), }; unsafe { let ret = libc::setsockopt( fd, level, opt2, &enable as *const _ as *const _, mem::size_of_val(&enable) as libc::socklen_t, ); if ret != 0 { return Err(Error::last_os_error()); } } Ok(()) } fn set_socket_before_bind(addr: &SocketAddr, socket: &Socket) -> io::Result<()> { // https://www.freebsd.org/cgi/man.cgi?query=ip&sektion=4&manpath=FreeBSD+9.0-RELEASE let level = match *addr { SocketAddr::V4(..) => libc::IPPROTO_IP, SocketAddr::V6(..) => libc::IPPROTO_IPV6, }; // 1. BINDANY set_bindany(level, socket)?; // 2. set ORIGDSTADDR for retrieving original destination address set_ip_origdstaddr(level, socket)?; Ok(()) } fn get_destination_addr(msg: &libc::msghdr) -> io::Result { unsafe { let (_, addr) = SockAddr::try_init(|dst_addr, dst_addr_len| { let mut cmsg: *mut libc::cmsghdr = libc::CMSG_FIRSTHDR(msg); let mut addr_or_port_received = false; // The address should come first and then the port, but we use a flag just in case. https://github.com/openbsd/src/blob/3d310523b415eeee9db46a5b67eecf8f9fdd5c8f/sys/netinet/udp_usrreq.c#L662-L687 while !cmsg.is_null() { let rcmsg = &*cmsg; match (rcmsg.cmsg_level, rcmsg.cmsg_type) { (libc::IPPROTO_IP, libc::IP_RECVDSTADDR) => { let toaddr_in = &mut *(dst_addr as *mut libc::sockaddr_in); ptr::copy_nonoverlapping( libc::CMSG_DATA(cmsg), &(*toaddr_in).sin_addr as *const _ as *mut _, mem::size_of::(), ); toaddr_in.sin_family = libc::AF_INET as u8; *dst_addr_len = mem::size_of::() as libc::socklen_t; if addr_or_port_received { return Ok(()); } else { addr_or_port_received = true } } (libc::IPPROTO_IP, IP_RECVDSTPORT) => { let toaddr_in = &mut *(dst_addr as *mut libc::sockaddr_in); ptr::copy_nonoverlapping( libc::CMSG_DATA(cmsg), &(*toaddr_in).sin_port as *const _ as *mut _, mem::size_of::(), ); if addr_or_port_received { return Ok(()); } else { addr_or_port_received = true } } (libc::IPPROTO_IPV6, libc::IPV6_PKTINFO) => { let toaddr_in = &mut *(dst_addr as *mut libc::sockaddr_in6); ptr::copy_nonoverlapping( libc::CMSG_DATA(cmsg), &(*toaddr_in).sin6_addr as *const _ as *mut _, mem::size_of::(), ); toaddr_in.sin6_family = libc::AF_INET6 as u8; *dst_addr_len = mem::size_of::() as libc::socklen_t; if addr_or_port_received { return Ok(()); } else { addr_or_port_received = true } } (libc::IPPROTO_IPV6, IPV6_RECVDSTPORT) => { let toaddr_in = &mut *(dst_addr as *mut libc::sockaddr_in6); ptr::copy_nonoverlapping( libc::CMSG_DATA(cmsg), &(*toaddr_in).sin6_port as *const _ as *mut _, mem::size_of::(), ); if addr_or_port_received { return Ok(()); } else { addr_or_port_received = true } } _ => {} } cmsg = libc::CMSG_NXTHDR(msg, cmsg); } let err = Error::new(ErrorKind::InvalidData, "missing destination address in msghdr"); Err(err) })?; Ok(addr.as_socket().expect("SocketAddr")) } } fn recv_dest_from(socket: &UdpSocket, buf: &mut [u8]) -> io::Result<(usize, SocketAddr, SocketAddr)> { unsafe { let mut control_buf = [0u8; 64]; let mut src_addr: libc::sockaddr_storage = mem::zeroed(); let mut msg: libc::msghdr = mem::zeroed(); msg.msg_name = &mut src_addr as *mut _ as *mut _; msg.msg_namelen = mem::size_of_val(&src_addr) as libc::socklen_t; let mut iov = libc::iovec { iov_base: buf.as_mut_ptr() as *mut _, iov_len: buf.len() as libc::size_t, }; msg.msg_iov = &mut iov; msg.msg_iovlen = 1; msg.msg_control = control_buf.as_mut_ptr() as *mut _; msg.msg_controllen = control_buf.len() as libc::socklen_t; let fd = socket.as_raw_fd(); let ret = libc::recvmsg(fd, &mut msg, 0); if ret < 0 { return Err(Error::last_os_error()); } let (_, src_saddr) = SockAddr::try_init(|a, l| { ptr::copy_nonoverlapping(msg.msg_name, a as *mut _, msg.msg_namelen as usize); *l = msg.msg_namelen; Ok(()) })?; Ok(( ret as usize, src_saddr.as_socket().expect("SocketAddr"), get_destination_addr(&msg)?, )) } } ================================================ FILE: crates/shadowsocks-service/src/local/redir/udprelay/sys/windows/mod.rs ================================================ use std::{ io, net::SocketAddr, task::{Context, Poll}, }; use crate::{ config::RedirType, local::redir::redir_ext::{RedirSocketOpts, UdpSocketRedir}, }; pub struct UdpRedirSocket; impl UdpRedirSocket { /// Create a new UDP socket binded to `addr` /// /// This will allow listening to `addr` that is not in local host pub fn listen(ty: RedirType, addr: SocketAddr) -> io::Result { UdpRedirSocket::bind(ty, addr, false) } /// Create a new UDP socket binded to `addr` /// /// This will allow binding to `addr` that is not in local host pub fn bind_nonlocal(ty: RedirType, addr: SocketAddr, _redir_opts: &RedirSocketOpts) -> io::Result { UdpRedirSocket::bind(ty, addr, true) } fn bind(_ty: RedirType, _addr: SocketAddr, _reuse_port: bool) -> io::Result { unimplemented!("UDP transparent proxy is not supported on Windows") } /// Send data to the socket to the given target address pub async fn send_to(&self, _buf: &[u8], _target: SocketAddr) -> io::Result { unimplemented!("UDP transparent proxy is not supported on Windows") } /// Returns the local address that this socket is bound to. pub fn local_addr(&self) -> io::Result { unimplemented!("UDP transparent proxy is not supported on Windows") } } impl UdpSocketRedir for UdpRedirSocket { fn poll_recv_dest_from( &self, _cx: &mut Context<'_>, _buf: &mut [u8], ) -> Poll> { unimplemented!("UDP transparent proxy is not supported on Windows") } } ================================================ FILE: crates/shadowsocks-service/src/local/socks/client/mod.rs ================================================ //! SOCKS clients #[cfg(feature = "local-socks4")] pub use self::socks4::Socks4TcpClient; pub use self::socks5::{Socks5TcpClient, Socks5UdpClient}; #[cfg(feature = "local-socks4")] pub mod socks4; pub mod socks5; ================================================ FILE: crates/shadowsocks-service/src/local/socks/client/socks4/mod.rs ================================================ //! SOCKS 4/4a clients pub use self::tcp_client::Socks4TcpClient; mod tcp_client; ================================================ FILE: crates/shadowsocks-service/src/local/socks/client/socks4/tcp_client.rs ================================================ //! SOCKS 4/4a client implementation use std::{ io, pin::Pin, task::{self, Poll}, }; use log::trace; use pin_project::pin_project; use tokio::{ io::{AsyncRead, AsyncWrite, ReadBuf}, net::{TcpStream, ToSocketAddrs}, }; use crate::local::socks::socks4::{Address, Command, Error, HandshakeRequest, HandshakeResponse, ResultCode}; /// Socks4/4a proxy client #[pin_project] pub struct Socks4TcpClient { #[pin] stream: TcpStream, } impl Socks4TcpClient { /// Connects to `addr` via `proxy` pub async fn connect(addr: A, proxy: P, user_id: U) -> Result where A: Into
, P: ToSocketAddrs, U: Into>, { let mut s = TcpStream::connect(proxy).await?; // 1. handshake let hs = HandshakeRequest { cd: Command::Connect, dst: addr.into(), user_id: user_id.into(), }; trace!("client connected, going to send handshake: {:?}", hs); hs.write_to(&mut s).await?; let hsp = HandshakeResponse::read_from(&mut s).await?; trace!("got handshake response: {:?}", hsp); if hsp.cd != ResultCode::RequestGranted { return Err(Error::Result(hsp.cd)); } Ok(Self { stream: s }) } } impl AsyncRead for Socks4TcpClient { fn poll_read( self: Pin<&mut Self>, cx: &mut task::Context<'_>, buf: &mut ReadBuf<'_>, ) -> Poll> { self.project().stream.poll_read(cx, buf) } } impl AsyncWrite for Socks4TcpClient { fn poll_write(self: Pin<&mut Self>, cx: &mut task::Context<'_>, buf: &[u8]) -> Poll> { self.project().stream.poll_write(cx, buf) } fn poll_flush(self: Pin<&mut Self>, cx: &mut task::Context<'_>) -> Poll> { self.project().stream.poll_flush(cx) } fn poll_shutdown(self: Pin<&mut Self>, cx: &mut task::Context<'_>) -> Poll> { self.project().stream.poll_shutdown(cx) } } ================================================ FILE: crates/shadowsocks-service/src/local/socks/client/socks5/mod.rs ================================================ //! SOCKS5 clients pub use self::{tcp_client::Socks5TcpClient, udp_client::Socks5UdpClient}; pub mod tcp_client; pub mod udp_client; ================================================ FILE: crates/shadowsocks-service/src/local/socks/client/socks5/tcp_client.rs ================================================ //! TCP relay client implementation use std::{ io, pin::Pin, task::{self, Poll}, }; use log::trace; use pin_project::pin_project; use shadowsocks::relay::socks5::{ self, Address, Command, Error, HandshakeRequest, HandshakeResponse, Reply, TcpRequestHeader, TcpResponseHeader, }; use tokio::{ io::{AsyncRead, AsyncWrite, ReadBuf}, net::{TcpStream, ToSocketAddrs}, }; /// Socks5 proxy client #[pin_project] pub struct Socks5TcpClient { #[pin] stream: TcpStream, } impl Socks5TcpClient { /// Connects to `addr` via `proxy` pub async fn connect(addr: A, proxy: P) -> Result where A: Into
, P: ToSocketAddrs, { let mut s = TcpStream::connect(proxy).await?; // 1. Handshake let hs = HandshakeRequest::new(vec![socks5::SOCKS5_AUTH_METHOD_NONE]); trace!("client connected, going to send handshake: {:?}", hs); hs.write_to(&mut s).await?; let hsp = HandshakeResponse::read_from(&mut s).await?; trace!("got handshake response: {:?}", hsp); assert_eq!(hsp.chosen_method, socks5::SOCKS5_AUTH_METHOD_NONE); // 2. Send request header let h = TcpRequestHeader::new(Command::TcpConnect, addr.into()); trace!("going to connect, req: {:?}", h); h.write_to(&mut s).await?; let hp = TcpResponseHeader::read_from(&mut s).await?; trace!("got response: {:?}", hp); match hp.reply { Reply::Succeeded => (), r => return Err(Error::Reply(r)), } Ok(Self { stream: s }) } /// UDP Associate `addr` via `proxy` /// /// According to RFC, `addr` is the address that your UDP socket binds to pub async fn udp_associate(addr: A, proxy: P) -> Result<(Self, Address), Error> where A: Into
, P: ToSocketAddrs, { let mut s = TcpStream::connect(proxy).await?; // 1. Handshake let hs = HandshakeRequest::new(vec![socks5::SOCKS5_AUTH_METHOD_NONE]); trace!("client connected, going to send handshake: {:?}", hs); hs.write_to(&mut s).await?; let hsp = HandshakeResponse::read_from(&mut s).await?; trace!("got handshake response: {:?}", hsp); assert_eq!(hsp.chosen_method, socks5::SOCKS5_AUTH_METHOD_NONE); // 2. Send request header let h = TcpRequestHeader::new(Command::UdpAssociate, addr.into()); trace!("going to connect, req: {:?}", h); h.write_to(&mut s).await?; let hp = TcpResponseHeader::read_from(&mut s).await?; trace!("got response: {:?}", hp); match hp.reply { Reply::Succeeded => (), r => return Err(Error::Reply(r)), } Ok((Self { stream: s }, hp.address)) } } impl AsyncRead for Socks5TcpClient { fn poll_read( self: Pin<&mut Self>, cx: &mut task::Context<'_>, buf: &mut ReadBuf<'_>, ) -> Poll> { self.project().stream.poll_read(cx, buf) } } impl AsyncWrite for Socks5TcpClient { fn poll_write(self: Pin<&mut Self>, cx: &mut task::Context<'_>, buf: &[u8]) -> Poll> { self.project().stream.poll_write(cx, buf) } fn poll_flush(self: Pin<&mut Self>, cx: &mut task::Context<'_>) -> Poll> { self.project().stream.poll_flush(cx) } fn poll_shutdown(self: Pin<&mut Self>, cx: &mut task::Context<'_>) -> Poll> { self.project().stream.poll_shutdown(cx) } } ================================================ FILE: crates/shadowsocks-service/src/local/socks/client/socks5/udp_client.rs ================================================ //! UDP relay client use std::io::{self, Cursor}; use bytes::{BufMut, BytesMut}; use tokio::net::{ToSocketAddrs, UdpSocket}; use shadowsocks::relay::socks5::{Address, Error, UdpAssociateHeader}; use super::tcp_client::Socks5TcpClient; /// Socks5 proxy client pub struct Socks5UdpClient { socket: UdpSocket, // Socks5 protocol requires to keep this TCP connection alive // Theoretically if this connection is broken, the association is broken too, but the UDP Socks5 server in this crate doesn't behave like that #[allow(dead_code)] assoc_client: Option, } impl Socks5UdpClient { /// Create a new UDP associate client binds to a specific address pub async fn bind(addrs: A) -> io::Result where A: ToSocketAddrs, { Ok(Self { socket: UdpSocket::bind(addrs).await?, assoc_client: None, }) } /// Create a new UDP associate to `proxy` pub async fn associate

(&mut self, proxy: P) -> Result<(), Error> where P: ToSocketAddrs, { if self.assoc_client.is_some() { let err = io::Error::other("udp is associated"); return Err(err.into()); } // The actual bind address, tell the proxy that I am going to send packets from this address let local_addr = self.socket.local_addr()?; let (assoc_client, proxy_addr) = Socks5TcpClient::udp_associate(local_addr, proxy).await?; match proxy_addr { Address::SocketAddress(sa) => self.socket.connect(sa).await?, // FIXME: `connect` will use tokio's builtin DNS resolver. // But if we want to use `hickory-dns`, we have to initialize a `Context` instance (for the global `AsyncResolver` instance) Address::DomainNameAddress(ref dname, port) => self.socket.connect((dname.as_str(), port)).await?, } self.assoc_client = Some(assoc_client); Ok(()) } /// Returns a future that sends data on the socket to the given address. pub async fn send_to(&self, frag: u8, buf: &[u8], target: A) -> Result where A: Into

, { self.check_associated()?; let header = UdpAssociateHeader::new(frag, target.into()); let header_len = header.serialized_len(); let mut send_buf = BytesMut::with_capacity(header.serialized_len() + buf.len()); header.write_to_buf(&mut send_buf); send_buf.put_slice(buf); let n = self.socket.send(&send_buf).await?; Ok(n.saturating_sub(header_len)) } /// Returns a future that receives a single datagram on the socket. On success, the future resolves to the number of bytes read and the origin. /// /// The function must be called with valid byte array buf of sufficient size to hold the message bytes. /// If a message is too long to fit in the supplied buffer, excess bytes may be discarded. pub async fn recv_from(&self, recv_buf: &mut [u8]) -> Result<(usize, u8, Address), Error> { self.check_associated()?; let n = self.socket.recv(recv_buf).await?; // Address + Payload let mut cur = Cursor::new(&recv_buf[..n]); let header = UdpAssociateHeader::read_from(&mut cur).await?; let pos = cur.position() as usize; recv_buf.copy_within(pos.., 0); Ok((n - pos, header.frag, header.address)) } fn check_associated(&self) -> io::Result<()> { if self.assoc_client.is_none() { let err = io::Error::other("udp not associated"); return Err(err); } Ok(()) } } ================================================ FILE: crates/shadowsocks-service/src/local/socks/config.rs ================================================ //! SOCK protocol configuration use std::{ collections::HashMap, fs::OpenOptions, io::{self, Read}, path::Path, }; use log::trace; use serde::Deserialize; #[derive(Deserialize, Debug)] struct SSSocks5AuthPasswordUserConfig { user_name: String, password: String, } #[derive(Deserialize, Debug)] struct SSSocks5AuthPasswordConfig { users: Vec, } #[derive(Deserialize, Debug)] struct SSSocks5AuthConfig { #[serde(skip_serializing_if = "Option::is_none")] password: Option, } /// SOCKS5 Authentication method #[derive(Debug, Clone)] pub struct Socks5AuthConfig { pub passwd: Socks5AuthPasswdConfig, } impl Socks5AuthConfig { /// Create a new SOCKS5 Authentication configuration pub fn new() -> Self { Self { passwd: Socks5AuthPasswdConfig::new(), } } /// Load from configuration file /// /// ```json /// { /// "password": { /// "users": [ /// { /// "user_name": "USER_NAME", /// "password": "PASSWORD" /// } /// ] /// } /// } pub fn load_from_file + ?Sized>(filename: &P) -> io::Result { let filename = filename.as_ref(); trace!( "loading socks5 authentication configuration from {}", filename.display() ); let mut reader = OpenOptions::new().read(true).open(filename)?; let mut content = String::new(); reader.read_to_string(&mut content)?; let jconf: SSSocks5AuthConfig = match json5::from_str(&content) { Ok(c) => c, Err(err) => return Err(io::Error::other(err)), }; let mut passwd = Socks5AuthPasswdConfig::new(); if let Some(p) = jconf.password { for user in p.users { passwd.add_user(user.user_name, user.password); } } Ok(Self { passwd }) } /// Check if authentication is required pub fn auth_required(&self) -> bool { self.passwd.total_users() > 0 } } impl Default for Socks5AuthConfig { fn default() -> Self { Self::new() } } /// SOCKS5 server User/Password Authentication configuration /// /// RFC1929 https://datatracker.ietf.org/doc/html/rfc1929 #[derive(Debug, Clone)] pub struct Socks5AuthPasswdConfig { passwd: HashMap, } impl Socks5AuthPasswdConfig { /// Create an empty `Passwd` configuration pub fn new() -> Self { Self { passwd: HashMap::new() } } /// Add a user with password pub fn add_user(&mut self, user_name: U, password: P) where U: Into, P: Into, { self.passwd.insert(user_name.into(), password.into()); } /// Check if `user_name` exists and validate `password` pub fn check_user(&self, user_name: U, password: P) -> bool where U: AsRef, P: AsRef, { match self.passwd.get(user_name.as_ref()) { Some(pwd) => pwd == password.as_ref(), None => false, } } /// Total users pub fn total_users(&self) -> usize { self.passwd.len() } } impl Default for Socks5AuthPasswdConfig { fn default() -> Self { Self::new() } } ================================================ FILE: crates/shadowsocks-service/src/local/socks/mod.rs ================================================ //! Shadowsocks SOCKS (4/4a, 5) Local Server pub use self::server::{Socks, SocksBuilder}; pub mod client; pub mod config; pub mod server; #[cfg(feature = "local-socks4")] pub mod socks4; ================================================ FILE: crates/shadowsocks-service/src/local/socks/server/mod.rs ================================================ //! Shadowsocks SOCKS Local Server use std::{io, sync::Arc, time::Duration}; use futures::{FutureExt, future}; use shadowsocks::{ServerAddr, config::Mode}; use crate::local::{context::ServiceContext, loadbalancing::PingBalancer}; pub use self::server::{SocksTcpServer, SocksTcpServerBuilder, SocksUdpServer}; use self::socks5::Socks5UdpServerBuilder; use super::config::Socks5AuthConfig; #[cfg(feature = "local-http")] use crate::local::http::config::HttpAuthConfig; #[allow(clippy::module_inception)] mod server; #[cfg(feature = "local-socks4")] mod socks4; mod socks5; /// SOCKS4/4a, SOCKS5 Local Server builder pub struct SocksBuilder { context: Arc, mode: Mode, udp_expiry_duration: Option, udp_capacity: Option, udp_bind_addr: Option, udp_associate_addr: Option, socks5_auth: Socks5AuthConfig, client_config: ServerAddr, balancer: PingBalancer, #[cfg(target_os = "macos")] launchd_tcp_socket_name: Option, #[cfg(target_os = "macos")] launchd_udp_socket_name: Option, #[cfg(feature = "local-http")] http_auth: HttpAuthConfig, } impl SocksBuilder { /// Create a new SOCKS server with default configuration pub fn new(client_config: ServerAddr, balancer: PingBalancer) -> Self { let context = ServiceContext::new(); Self::with_context(Arc::new(context), client_config, balancer) } /// Create a new SOCKS server with context pub fn with_context(context: Arc, client_config: ServerAddr, balancer: PingBalancer) -> Self { Self { context, mode: Mode::TcpOnly, udp_expiry_duration: None, udp_capacity: None, udp_bind_addr: None, udp_associate_addr: None, socks5_auth: Socks5AuthConfig::default(), client_config, balancer, #[cfg(target_os = "macos")] launchd_tcp_socket_name: None, #[cfg(target_os = "macos")] launchd_udp_socket_name: None, #[cfg(feature = "local-http")] http_auth: HttpAuthConfig::default(), } } /// Set server mode pub fn set_mode(&mut self, mode: Mode) { self.mode = mode; } /// Set UDP association's expiry duration pub fn set_udp_expiry_duration(&mut self, d: Duration) { self.udp_expiry_duration = Some(d); } /// Set total UDP association to be kept simultaneously in server pub fn set_udp_capacity(&mut self, c: usize) { self.udp_capacity = Some(c); } /// UDP server's bind address /// /// * If `mode` is `tcp_only`, then it will still return this address for `UDP_ASSOCIATE` command /// * Otherwise, UDP relay will bind to this address pub fn set_udp_bind_addr(&mut self, a: ServerAddr) { self.udp_bind_addr = Some(a); } pub fn set_udp_associate_addr(&mut self, a: ServerAddr) { self.udp_associate_addr = Some(a); } /// Set SOCKS5 Username/Password Authentication configuration pub fn set_socks5_auth(&mut self, p: Socks5AuthConfig) { self.socks5_auth = p; } /// Set HTTP Authentication configuration #[cfg(feature = "local-http")] pub fn set_http_auth(&mut self, p: HttpAuthConfig) { self.http_auth = p; } /// macOS launchd activate socket #[cfg(target_os = "macos")] pub fn set_launchd_tcp_socket_name(&mut self, n: String) { self.launchd_tcp_socket_name = Some(n); } /// macOS launchd activate socket #[cfg(target_os = "macos")] pub fn set_launchd_udp_socket_name(&mut self, n: String) { self.launchd_udp_socket_name = Some(n); } pub async fn build(self) -> io::Result { let udp_bind_addr = self.udp_bind_addr.clone().unwrap_or_else(|| self.client_config.clone()); let udp_associate_addr: ServerAddr = self .udp_associate_addr .as_ref() .or(self.udp_bind_addr.as_ref()) .unwrap_or(&self.client_config) .clone(); let mut udp_server = None; if self.mode.enable_udp() { #[allow(unused_mut)] let mut builder = Socks5UdpServerBuilder::new( self.context.clone(), udp_bind_addr, self.udp_expiry_duration, self.udp_capacity, self.balancer.clone(), ); #[cfg(target_os = "macos")] if let Some(s) = self.launchd_udp_socket_name { builder.set_launchd_socket_name(s); } let server = builder.build().await?; udp_server = Some(server); } let mut tcp_server = None; if self.mode.enable_tcp() { #[allow(unused_mut)] let mut builder = SocksTcpServerBuilder::new( self.context.clone(), self.client_config, udp_associate_addr, self.balancer.clone(), self.mode, self.socks5_auth, #[cfg(feature = "local-http")] self.http_auth, ); #[cfg(target_os = "macos")] if let Some(s) = self.launchd_tcp_socket_name { builder.set_launchd_socket_name(s); } let server = builder.build().await?; tcp_server = Some(server); } Ok(Socks { tcp_server, udp_server }) } } /// SOCKS4/4a, SOCKS5 Local Server pub struct Socks { tcp_server: Option, udp_server: Option, } impl Socks { /// TCP server instance pub fn tcp_server(&self) -> Option<&SocksTcpServer> { self.tcp_server.as_ref() } /// UDP server instance pub fn udp_server(&self) -> Option<&SocksUdpServer> { self.udp_server.as_ref() } /// Start serving pub async fn run(self) -> io::Result<()> { let mut vfut = Vec::new(); if let Some(tcp_server) = self.tcp_server { vfut.push(tcp_server.run().boxed()); } if let Some(udp_server) = self.udp_server { // NOTE: SOCKS 5 RFC requires TCP handshake for UDP ASSOCIATE command // But here we can start a standalone UDP SOCKS 5 relay server, for special use cases vfut.push(udp_server.run().boxed()); } let (res, ..) = future::select_all(vfut).await; res } } ================================================ FILE: crates/shadowsocks-service/src/local/socks/server/server.rs ================================================ use std::{io, net::SocketAddr, sync::Arc, time::Duration}; use log::{error, info}; use shadowsocks::{ServerAddr, config::Mode, net::TcpListener as ShadowTcpListener}; use tokio::{net::TcpStream, time}; #[cfg(feature = "local-http")] use crate::local::http::{HttpConnectionHandler, config::HttpAuthConfig}; use crate::local::{ context::ServiceContext, loadbalancing::PingBalancer, net::tcp::listener::create_standard_tcp_listener, socks::config::Socks5AuthConfig, }; #[cfg(feature = "local-socks4")] use super::socks4::Socks4TcpHandler; use super::socks5::{Socks5TcpHandler, Socks5UdpServer}; pub struct SocksTcpServerBuilder { context: Arc, client_config: ServerAddr, udp_associate_addr: ServerAddr, balancer: PingBalancer, mode: Mode, socks5_auth: Arc, #[cfg(target_os = "macos")] launchd_socket_name: Option, #[cfg(feature = "local-http")] http_auth: Arc, } impl SocksTcpServerBuilder { pub(crate) fn new( context: Arc, client_config: ServerAddr, udp_associate_addr: ServerAddr, balancer: PingBalancer, mode: Mode, socks5_auth: Socks5AuthConfig, #[cfg(feature = "local-http")] http_auth: HttpAuthConfig, ) -> Self { Self { context, client_config, udp_associate_addr, balancer, mode, socks5_auth: Arc::new(socks5_auth), #[cfg(target_os = "macos")] launchd_socket_name: None, #[cfg(feature = "local-http")] http_auth: Arc::new(http_auth), } } /// macOS launchd activate socket #[cfg(target_os = "macos")] pub fn set_launchd_socket_name(&mut self, n: String) { self.launchd_socket_name = Some(n); } pub async fn build(self) -> io::Result { cfg_if::cfg_if! { if #[cfg(target_os = "macos")] { let listener = match self.launchd_socket_name { Some(launchd_socket_name) => { use tokio::net::TcpListener as TokioTcpListener; use crate::net::launch_activate_socket::get_launch_activate_tcp_listener; let std_listener = get_launch_activate_tcp_listener(&launchd_socket_name, true)?; let tokio_listener = TokioTcpListener::from_std(std_listener)?; ShadowTcpListener::from_listener(tokio_listener, self.context.accept_opts())? } _ => { create_standard_tcp_listener(&self.context, &self.client_config).await? } }; } else { let listener = create_standard_tcp_listener(&self.context, &self.client_config).await?; } } Ok(SocksTcpServer { context: self.context, listener, udp_associate_addr: self.udp_associate_addr, balancer: self.balancer, mode: self.mode, socks5_auth: self.socks5_auth, #[cfg(feature = "local-http")] http_auth: self.http_auth, }) } } /// SOCKS TCP server instance pub struct SocksTcpServer { context: Arc, listener: ShadowTcpListener, udp_associate_addr: ServerAddr, balancer: PingBalancer, mode: Mode, socks5_auth: Arc, #[cfg(feature = "local-http")] http_auth: Arc, } impl SocksTcpServer { /// Get TCP server local addr pub fn local_addr(&self) -> io::Result { self.listener.local_addr() } /// Start TCP accept loop pub async fn run(self) -> io::Result<()> { info!("shadowsocks socks TCP listening on {}", self.listener.local_addr()?); // If UDP is enabled, SOCK5 UDP_ASSOCIATE command will let client to send requests to this address let udp_associate_addr = Arc::new(self.udp_associate_addr); #[cfg(feature = "local-http")] let http_handler = HttpConnectionHandler::new(self.context.clone(), self.balancer.clone(), self.http_auth.clone()); loop { let (stream, peer_addr) = match self.listener.accept().await { Ok(s) => s, Err(err) => { error!("accept failed with error: {}", err); time::sleep(Duration::from_secs(1)).await; continue; } }; let handler = SocksTcpHandler { context: self.context.clone(), udp_associate_addr: udp_associate_addr.clone(), stream, balancer: self.balancer.clone(), peer_addr, mode: self.mode, socks5_auth: self.socks5_auth.clone(), #[cfg(feature = "local-http")] http_handler: http_handler.clone(), }; tokio::spawn(async move { if let Err(err) = handler.handle_tcp_client().await { error!("socks5 tcp client handler error: {}", err); } }); } } } struct SocksTcpHandler { context: Arc, udp_associate_addr: Arc, stream: TcpStream, balancer: PingBalancer, peer_addr: SocketAddr, mode: Mode, socks5_auth: Arc, #[cfg(feature = "local-http")] http_handler: HttpConnectionHandler, } impl SocksTcpHandler { #[cfg(not(any(feature = "local-socks4", feature = "local-http")))] async fn handle_tcp_client(self) -> io::Result<()> { let handler = Socks5TcpHandler::new( self.context, self.udp_associate_addr, self.balancer, self.mode, self.socks5_auth, ); handler.handle_socks5_client(self.stream, self.peer_addr).await } #[cfg(any(feature = "local-socks4", feature = "local-http"))] async fn handle_tcp_client(self) -> io::Result<()> { use std::io::ErrorKind; let mut version_buffer = [0u8; 1]; let n = self.stream.peek(&mut version_buffer).await?; if n == 0 { return Err(ErrorKind::UnexpectedEof.into()); } match version_buffer[0] { #[cfg(feature = "local-socks4")] 0x04 => { if self.socks5_auth.auth_required() { error!("SOCKS4 disabled when authentication is configured"); Err(io::Error::other("SOCKS4 unsupported")) } else { let handler = Socks4TcpHandler::new(self.context, self.balancer, self.mode); handler.handle_socks4_client(self.stream, self.peer_addr).await } } 0x05 => { let handler = Socks5TcpHandler::new( self.context, self.udp_associate_addr, self.balancer, self.mode, self.socks5_auth, ); handler.handle_socks5_client(self.stream, self.peer_addr).await } #[cfg(feature = "local-http")] b'G' | b'g' | b'H' | b'h' | b'P' | b'p' | b'D' | b'd' | b'C' | b'c' | b'O' | b'o' | b'T' | b't' => { if self.socks5_auth.auth_required() { error!("HTTP disabled when authentication is configured"); Err(io::Error::other("HTTP unsupported")) } else { // GET, HEAD, POST, PUT, DELETE, CONNECT, OPTIONS, TRACE, PATCH match self.http_handler.serve_connection(self.stream, self.peer_addr).await { Ok(..) => Ok(()), Err(err) => { error!("HTTP connection {} handler failed with error: {}", self.peer_addr, err); Err(io::Error::other(err)) } } } } version => { error!("unsupported socks version {:x}", version); let err = io::Error::other("unsupported socks version"); Err(err) } } } } /// SOCKS UDP server pub type SocksUdpServer = Socks5UdpServer; ================================================ FILE: crates/shadowsocks-service/src/local/socks/server/socks4/mod.rs ================================================ //! SOCKS4/4a Local Server pub use self::tcprelay::Socks4TcpHandler; mod tcprelay; ================================================ FILE: crates/shadowsocks-service/src/local/socks/server/socks4/tcprelay.rs ================================================ //! Shadowsocks SOCKS4/4a Local Server use std::{ io::{self, ErrorKind}, net::SocketAddr, sync::Arc, }; use log::{debug, error, trace, warn}; use shadowsocks::config::Mode; use tokio::{ io::{AsyncWriteExt, BufReader}, net::TcpStream, }; use crate::local::{ context::ServiceContext, loadbalancing::PingBalancer, net::AutoProxyClientStream, utils::{establish_tcp_tunnel, establish_tcp_tunnel_bypassed}, }; use crate::local::socks::socks4::{ Address, Command, Error as Socks4Error, HandshakeRequest, HandshakeResponse, ResultCode, }; pub struct Socks4TcpHandler { context: Arc, balancer: PingBalancer, mode: Mode, } impl Socks4TcpHandler { pub fn new(context: Arc, balancer: PingBalancer, mode: Mode) -> Self { Self { context, balancer, mode, } } pub async fn handle_socks4_client(self, stream: TcpStream, peer_addr: SocketAddr) -> io::Result<()> { // 1. Handshake // NOTE: Wraps it with BufReader for reading NULL terminated information in HandshakeRequest let mut s = BufReader::new(stream); let handshake_req = match HandshakeRequest::read_from(&mut s).await { Ok(r) => r, Err(Socks4Error::IoError(ref err)) if err.kind() == ErrorKind::UnexpectedEof => { trace!("socks4 handshake early eof. peer: {}", peer_addr); return Ok(()); } Err(err) => { error!("socks4 handshake error: {}", err); return Err(err.into()); } }; trace!("socks4 {:?} peer: {}", handshake_req, peer_addr); match handshake_req.cd { Command::Connect => { debug!("CONNECT {}", handshake_req.dst); self.handle_socks4_connect(s, peer_addr, handshake_req.dst).await } Command::Bind => { warn!("BIND is not supported"); let handshake_rsp = HandshakeResponse::new(ResultCode::RequestRejectedOrFailed); handshake_rsp.write_to(&mut s).await?; Ok(()) } } } async fn handle_socks4_connect( self, mut stream: BufReader, peer_addr: SocketAddr, target_addr: Address, ) -> io::Result<()> { if !self.mode.enable_tcp() { warn!("TCP CONNECT is disabled"); let handshake_rsp = HandshakeResponse::new(ResultCode::RequestRejectedOrFailed); handshake_rsp.write_to(&mut stream).await?; return Ok(()); } let target_addr = target_addr.into(); let mut server_opt = None; let server_result = if self.balancer.is_empty() { AutoProxyClientStream::connect_bypassed(self.context, &target_addr).await } else { let server = self.balancer.best_tcp_server(); let r = AutoProxyClientStream::connect_with_opts( self.context, &server, &target_addr, server.connect_opts_ref(), ) .await; server_opt = Some(server); r }; let mut remote = match server_result { Ok(remote) => { // Tell the client that we are ready let handshake_rsp = HandshakeResponse::new(ResultCode::RequestGranted); handshake_rsp.write_to(&mut stream).await?; trace!("sent header: {:?}", handshake_rsp); remote } Err(err) => { let result_code = match err.kind() { ErrorKind::ConnectionRefused => ResultCode::RequestRejectedCannotConnect, ErrorKind::ConnectionAborted => ResultCode::RequestRejectedCannotConnect, _ => ResultCode::RequestRejectedOrFailed, }; let handshake_rsp = HandshakeResponse::new(result_code); handshake_rsp.write_to(&mut stream).await?; return Err(err); } }; // NOTE: Transfer all buffered data before unwrap, or these data will be lost let buffer = stream.buffer(); if !buffer.is_empty() { remote.write_all(buffer).await?; } // UNWRAP. let mut stream = stream.into_inner(); match server_opt { Some(server) => { let svr_cfg = server.server_config(); establish_tcp_tunnel(svr_cfg, &mut stream, &mut remote, peer_addr, &target_addr).await } None => establish_tcp_tunnel_bypassed(&mut stream, &mut remote, peer_addr, &target_addr).await, } } } ================================================ FILE: crates/shadowsocks-service/src/local/socks/server/socks5/mod.rs ================================================ //! SOCKS5 Local Server pub use self::{ tcprelay::Socks5TcpHandler, udprelay::{Socks5UdpServer, Socks5UdpServerBuilder}, }; mod tcprelay; mod udprelay; ================================================ FILE: crates/shadowsocks-service/src/local/socks/server/socks5/tcprelay.rs ================================================ //! SOCKS5 TCP Server use std::{ io::{self, ErrorKind}, net::{Ipv4Addr, SocketAddr}, str, sync::Arc, }; use log::{debug, error, trace, warn}; use shadowsocks::{ ServerAddr, config::Mode, relay::socks5::{ self, Address, Command, Error as Socks5Error, HandshakeRequest, HandshakeResponse, PasswdAuthRequest, PasswdAuthResponse, Reply, TcpRequestHeader, TcpResponseHeader, }, }; use tokio::net::TcpStream; use crate::{ local::{ context::ServiceContext, loadbalancing::PingBalancer, net::AutoProxyClientStream, socks::config::Socks5AuthConfig, utils::{establish_tcp_tunnel, establish_tcp_tunnel_bypassed}, }, net::utils::ignore_until_end, }; pub struct Socks5TcpHandler { context: Arc, udp_associate_addr: Arc, balancer: PingBalancer, mode: Mode, auth: Arc, } impl Socks5TcpHandler { pub fn new( context: Arc, udp_associate_addr: Arc, balancer: PingBalancer, mode: Mode, auth: Arc, ) -> Self { Self { context, udp_associate_addr, balancer, mode, auth, } } async fn check_auth(&self, stream: &mut TcpStream, handshake_req: &HandshakeRequest) -> io::Result<()> { use std::io::Error; let allow_none = !self.auth.auth_required(); for method in handshake_req.methods.iter() { match *method { socks5::SOCKS5_AUTH_METHOD_PASSWORD => { let resp = HandshakeResponse::new(socks5::SOCKS5_AUTH_METHOD_PASSWORD); trace!("reply handshake {:?}", resp); resp.write_to(stream).await?; return self.check_auth_password(stream).await; } socks5::SOCKS5_AUTH_METHOD_NONE => { if !allow_none { trace!("none authentication method is not allowed"); } else { let resp = HandshakeResponse::new(socks5::SOCKS5_AUTH_METHOD_NONE); trace!("reply handshake {:?}", resp); resp.write_to(stream).await?; return Ok(()); } } _ => { trace!("unsupported authentication method {}", method); } } } let resp = HandshakeResponse::new(socks5::SOCKS5_AUTH_METHOD_NOT_ACCEPTABLE); resp.write_to(stream).await?; trace!("reply handshake {:?}", resp); Err(Error::other( "currently shadowsocks-rust does not support authentication", )) } async fn check_auth_password(&self, stream: &mut TcpStream) -> io::Result<()> { use std::io::Error; const PASSWORD_AUTH_STATUS_FAILURE: u8 = 255; // Read initiation negotiation let req = match PasswdAuthRequest::read_from(stream).await { Ok(i) => i, Err(err) => { let rsp = PasswdAuthResponse::new(err.as_reply().as_u8()); let _ = rsp.write_to(stream).await; return Err(Error::other(format!( "Username/Password Authentication Initial request failed: {err}" ))); } }; let user_name = match str::from_utf8(&req.uname) { Ok(u) => u, Err(..) => { let rsp = PasswdAuthResponse::new(PASSWORD_AUTH_STATUS_FAILURE); let _ = rsp.write_to(stream).await; return Err(Error::other( "Username/Password Authentication Initial request uname contains invalid characters", )); } }; let password = match str::from_utf8(&req.passwd) { Ok(u) => u, Err(..) => { let rsp = PasswdAuthResponse::new(PASSWORD_AUTH_STATUS_FAILURE); let _ = rsp.write_to(stream).await; return Err(Error::other( "Username/Password Authentication Initial request passwd contains invalid characters", )); } }; if self.auth.passwd.check_user(user_name, password) { trace!( "socks5 authenticated with Username/Password method, user: {}, password: {}", user_name, password ); let rsp = PasswdAuthResponse::new(0); rsp.write_to(stream).await?; Ok(()) } else { let rsp = PasswdAuthResponse::new(PASSWORD_AUTH_STATUS_FAILURE); rsp.write_to(stream).await?; error!( "socks5 rejected Username/Password user: {}, password: {}", user_name, password ); Err(Error::other(format!( "Username/Password Authentication failed, user: {user_name}, password: {password}" ))) } } pub async fn handle_socks5_client(self, mut stream: TcpStream, peer_addr: SocketAddr) -> io::Result<()> { // 1. Handshake let handshake_req = match HandshakeRequest::read_from(&mut stream).await { Ok(r) => r, Err(Socks5Error::IoError(ref err)) if err.kind() == ErrorKind::UnexpectedEof => { trace!("socks5 handshake early eof. peer: {}", peer_addr); return Ok(()); } Err(err) => { error!("socks5 handshake error: {}", err); return Err(err.into()); } }; trace!("socks5 {:?}", handshake_req); self.check_auth(&mut stream, &handshake_req).await?; // 2. Fetch headers let header = match TcpRequestHeader::read_from(&mut stream).await { Ok(h) => h, Err(err) => { error!("failed to get TcpRequestHeader: {}, peer: {}", err, peer_addr); let rh = TcpResponseHeader::new(err.as_reply(), Address::SocketAddress(peer_addr)); rh.write_to(&mut stream).await?; return Err(err.into()); } }; trace!("socks5 {:?} peer: {}", header, peer_addr); let addr = header.address; // 3. Handle Command match header.command { Command::TcpConnect => { debug!("CONNECT {}", addr); self.handle_tcp_connect(stream, peer_addr, addr).await } Command::UdpAssociate => { debug!("UDP ASSOCIATE from {}", addr); self.handle_udp_associate(stream, addr).await } Command::TcpBind => { warn!("BIND is not supported"); let rh = TcpResponseHeader::new(socks5::Reply::CommandNotSupported, addr); rh.write_to(&mut stream).await?; Ok(()) } } } async fn handle_tcp_connect( self, mut stream: TcpStream, peer_addr: SocketAddr, target_addr: Address, ) -> io::Result<()> { if !self.mode.enable_tcp() { warn!("TCP CONNECT is disabled"); let rh = TcpResponseHeader::new(socks5::Reply::CommandNotSupported, target_addr); rh.write_to(&mut stream).await?; return Ok(()); } let mut server_opt = None; let remote_result = if self.balancer.is_empty() { AutoProxyClientStream::connect_bypassed(self.context.clone(), &target_addr).await } else { let server = self.balancer.best_tcp_server(); let r = AutoProxyClientStream::connect_with_opts( self.context, &server, &target_addr, server.connect_opts_ref(), ) .await; server_opt = Some(server); r }; let mut remote = match remote_result { Ok(remote) => { // Tell the client that we are ready let header = TcpResponseHeader::new(socks5::Reply::Succeeded, Address::SocketAddress(remote.local_addr()?)); header.write_to(&mut stream).await?; trace!("sent header: {:?}", header); remote } Err(err) => { let reply = match err.kind() { ErrorKind::ConnectionRefused => Reply::ConnectionRefused, ErrorKind::ConnectionAborted => Reply::HostUnreachable, _ => Reply::NetworkUnreachable, }; let dummy_address = SocketAddr::new(Ipv4Addr::UNSPECIFIED.into(), 0); let header = TcpResponseHeader::new(reply, Address::SocketAddress(dummy_address)); header.write_to(&mut stream).await?; return Err(err); } }; match server_opt { Some(server) => { let svr_cfg = server.server_config(); establish_tcp_tunnel(svr_cfg, &mut stream, &mut remote, peer_addr, &target_addr).await } None => establish_tcp_tunnel_bypassed(&mut stream, &mut remote, peer_addr, &target_addr).await, } } async fn handle_udp_associate(self, mut stream: TcpStream, client_addr: Address) -> io::Result<()> { if !self.mode.enable_udp() { warn!("socks5 udp is disabled"); let rh = TcpResponseHeader::new(socks5::Reply::CommandNotSupported, client_addr); rh.write_to(&mut stream).await?; return Ok(()); } // shadowsocks accepts both TCP and UDP from the same address let rh = TcpResponseHeader::new(socks5::Reply::Succeeded, self.udp_associate_addr.as_ref().into()); rh.write_to(&mut stream).await?; // Hold connection until EOF. let _ = ignore_until_end(&mut stream).await; Ok(()) } } ================================================ FILE: crates/shadowsocks-service/src/local/socks/server/socks5/udprelay.rs ================================================ //! UDP Tunnel server use std::{ io::{self, Cursor}, net::{IpAddr, SocketAddr}, sync::Arc, time::Duration, }; use byte_string::ByteStr; use bytes::{BufMut, BytesMut}; use log::{debug, error, info, trace}; use shadowsocks::{ ServerAddr, relay::{ socks5::{Address, UdpAssociateHeader}, udprelay::MAXIMUM_UDP_PAYLOAD_SIZE, }, }; use tokio::{net::UdpSocket, time}; use crate::{ local::{ context::ServiceContext, loadbalancing::PingBalancer, net::{UdpAssociationManager, UdpInboundWrite, udp::listener::create_standard_udp_listener}, }, net::utils::to_ipv4_mapped, }; pub struct Socks5UdpServerBuilder { context: Arc, client_config: ServerAddr, time_to_live: Option, capacity: Option, balancer: PingBalancer, #[cfg(target_os = "macos")] launchd_socket_name: Option, } impl Socks5UdpServerBuilder { pub(crate) fn new( context: Arc, client_config: ServerAddr, time_to_live: Option, capacity: Option, balancer: PingBalancer, ) -> Self { Self { context, client_config, time_to_live, capacity, balancer, #[cfg(target_os = "macos")] launchd_socket_name: None, } } /// macOS launchd activate socket #[cfg(target_os = "macos")] pub fn set_launchd_socket_name(&mut self, n: String) { self.launchd_socket_name = Some(n); } pub async fn build(self) -> io::Result { cfg_if::cfg_if! { if #[cfg(target_os = "macos")] { let socket = match self.launchd_socket_name { Some(launchd_socket_name) => { use tokio::net::UdpSocket as TokioUdpSocket; use crate::net::launch_activate_socket::get_launch_activate_udp_socket; let std_socket = get_launch_activate_udp_socket(&launchd_socket_name, true)?; TokioUdpSocket::from_std(std_socket)? } _ => { create_standard_udp_listener(&self.context, &self.client_config).await?.into() } }; } else { let socket = create_standard_udp_listener(&self.context, &self.client_config).await?.into(); } } Ok(Socks5UdpServer { context: self.context, time_to_live: self.time_to_live, capacity: self.capacity, listener: Arc::new(socket), balancer: self.balancer, }) } } #[derive(Clone)] struct Socks5UdpInboundWriter { inbound: Arc, } impl UdpInboundWrite for Socks5UdpInboundWriter { async fn send_to(&self, peer_addr: SocketAddr, remote_addr: &Address, data: &[u8]) -> io::Result<()> { let remote_addr = match remote_addr { Address::SocketAddress(sa) => { // Try to convert IPv4 mapped IPv6 address if server is running on dual-stack mode let saddr = match *sa { SocketAddr::V4(..) => *sa, SocketAddr::V6(ref v6) => match to_ipv4_mapped(v6.ip()) { Some(v4) => SocketAddr::new(IpAddr::from(v4), v6.port()), None => *sa, }, }; Address::SocketAddress(saddr) } daddr => daddr.clone(), }; // Reassemble packet let mut payload_buffer = BytesMut::new(); let header = UdpAssociateHeader::new(0, remote_addr.clone()); payload_buffer.reserve(header.serialized_len() + data.len()); header.write_to_buf(&mut payload_buffer); payload_buffer.put_slice(data); self.inbound.send_to(&payload_buffer, peer_addr).await.map(|_| ()) } } /// SOCKS5 UDP server instance pub struct Socks5UdpServer { context: Arc, time_to_live: Option, capacity: Option, listener: Arc, balancer: PingBalancer, } impl Socks5UdpServer { /// Server's listen address pub fn local_addr(&self) -> io::Result { self.listener.local_addr() } /// Run server accept loop pub async fn run(self) -> io::Result<()> { info!("shadowsocks socks5 UDP listening on {}", self.listener.local_addr()?); let (mut manager, cleanup_interval, mut keepalive_rx) = UdpAssociationManager::new( self.context.clone(), Socks5UdpInboundWriter { inbound: self.listener.clone(), }, self.time_to_live, self.capacity, self.balancer, ); let mut buffer = [0u8; MAXIMUM_UDP_PAYLOAD_SIZE]; let mut cleanup_timer = time::interval(cleanup_interval); loop { tokio::select! { _ = cleanup_timer.tick() => { // cleanup expired associations. iter() will remove expired elements manager.cleanup_expired().await; } peer_addr_opt = keepalive_rx.recv() => { let peer_addr = peer_addr_opt.expect("keep-alive channel closed unexpectedly"); manager.keep_alive(&peer_addr).await; } recv_result = self.listener.recv_from(&mut buffer) => { let (n, peer_addr) = match recv_result { Ok(s) => s, Err(err) => { error!("udp server recv_from failed with error: {}", err); time::sleep(Duration::from_secs(1)).await; continue; } }; let data = &buffer[..n]; // PKT = UdpAssociateHeader + PAYLOAD let mut cur = Cursor::new(data); let header = match UdpAssociateHeader::read_from(&mut cur).await { Ok(h) => h, Err(..) => { error!("received invalid UDP associate packet: {:?}", ByteStr::new(data)); continue; } }; if header.frag != 0 { error!("received UDP associate with frag != 0, which is not supported by shadowsocks"); continue; } let pos = cur.position() as usize; let payload = &data[pos..]; trace!( "UDP ASSOCIATE {} -> {}, {} bytes", peer_addr, header.address, payload.len() ); if let Err(err) = manager.send_to(peer_addr, header.address, payload).await { debug!( "udp packet from {} relay {} bytes failed, error: {}", peer_addr, data.len(), err ); } } } } } } ================================================ FILE: crates/shadowsocks-service/src/local/socks/socks4.rs ================================================ //! Socks4a Protocol Definition //! //! #![allow(dead_code)] use std::{ fmt, io::{self, ErrorKind}, net::{Ipv4Addr, SocketAddr, SocketAddrV4}, }; use byteorder::{BigEndian, ByteOrder}; use bytes::{BufMut, BytesMut}; use thiserror::Error; use tokio::io::{AsyncBufRead, AsyncBufReadExt, AsyncRead, AsyncReadExt, AsyncWrite, AsyncWriteExt}; use shadowsocks::relay::socks5; #[rustfmt::skip] mod consts { pub const SOCKS4_VERSION: u8 = 4; pub const SOCKS4_COMMAND_CONNECT: u8 = 1; pub const SOCKS4_COMMAND_BIND: u8 = 2; pub const SOCKS4_RESULT_REQUEST_GRANTED: u8 = 90; pub const SOCKS4_RESULT_REQUEST_REJECTED_OR_FAILED: u8 = 91; pub const SOCKS4_RESULT_REQUEST_REJECTED_CANNOT_CONNECT: u8 = 92; pub const SOCKS4_RESULT_REQUEST_REJECTED_DIFFERENT_USER_ID: u8 = 93; } /// SOCKS4 Command #[derive(Clone, Debug, Copy)] pub enum Command { /// CONNECT command Connect, /// BIND command Bind, } impl Command { #[inline] fn as_u8(self) -> u8 { match self { Self::Connect => consts::SOCKS4_COMMAND_CONNECT, Self::Bind => consts::SOCKS4_COMMAND_BIND, } } #[inline] fn from_u8(code: u8) -> Option { match code { consts::SOCKS4_COMMAND_CONNECT => Some(Self::Connect), consts::SOCKS4_COMMAND_BIND => Some(Self::Bind), _ => None, } } } /// SOCKS4 Result Code #[derive(Clone, Debug, Copy, Eq, PartialEq)] pub enum ResultCode { /// 90: request granted RequestGranted, /// 91: request rejected or failed RequestRejectedOrFailed, /// 92: request rejected because SOCKS server cannot connect to identd on the client RequestRejectedCannotConnect, /// 93: request rejected because the client program and identd report different user-ids RequestRejectedDifferentUserId, /// Other replies Other(u8), } impl ResultCode { #[inline] fn as_u8(self) -> u8 { match self { Self::RequestGranted => consts::SOCKS4_RESULT_REQUEST_GRANTED, Self::RequestRejectedOrFailed => consts::SOCKS4_RESULT_REQUEST_REJECTED_OR_FAILED, Self::RequestRejectedCannotConnect => consts::SOCKS4_RESULT_REQUEST_REJECTED_CANNOT_CONNECT, Self::RequestRejectedDifferentUserId => consts::SOCKS4_RESULT_REQUEST_REJECTED_DIFFERENT_USER_ID, Self::Other(c) => c, } } #[inline] fn from_u8(code: u8) -> Self { match code { consts::SOCKS4_RESULT_REQUEST_GRANTED => Self::RequestGranted, consts::SOCKS4_RESULT_REQUEST_REJECTED_OR_FAILED => Self::RequestRejectedOrFailed, consts::SOCKS4_RESULT_REQUEST_REJECTED_CANNOT_CONNECT => Self::RequestRejectedCannotConnect, consts::SOCKS4_RESULT_REQUEST_REJECTED_DIFFERENT_USER_ID => Self::RequestRejectedDifferentUserId, code => Self::Other(code), } } } impl fmt::Display for ResultCode { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match *self { Self::RequestGranted => f.write_str("request granted"), Self::RequestRejectedOrFailed => f.write_str("request rejected or failed"), Self::RequestRejectedCannotConnect => { f.write_str("request rejected because SOCKS server cannot connect to identd on the client") } Self::RequestRejectedDifferentUserId => { f.write_str("request rejected because the client program and identd report different user-ids") } Self::Other(code) => write!(f, "other result code {code}"), } } } /// SOCKS4 Address type #[derive(Clone, PartialEq, Eq, Hash)] pub enum Address { /// Socket address (IP Address) SocketAddress(SocketAddrV4), /// Domain name address (SOCKS4a) DomainNameAddress(String, u16), } impl fmt::Debug for Address { #[inline] fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { Self::SocketAddress(ref addr) => write!(f, "{addr}"), Self::DomainNameAddress(ref addr, ref port) => write!(f, "{addr}:{port}"), } } } impl fmt::Display for Address { #[inline] fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { Self::SocketAddress(ref addr) => write!(f, "{addr}"), Self::DomainNameAddress(ref addr, ref port) => write!(f, "{addr}:{port}"), } } } impl From for Address { fn from(s: SocketAddrV4) -> Self { Self::SocketAddress(s) } } impl From<(String, u16)> for Address { fn from((dn, port): (String, u16)) -> Self { Self::DomainNameAddress(dn, port) } } impl From<(&str, u16)> for Address { fn from((dn, port): (&str, u16)) -> Self { Self::DomainNameAddress(dn.to_owned(), port) } } impl From<&Self> for Address { fn from(addr: &Self) -> Self { addr.clone() } } impl From
for socks5::Address { fn from(addr: Address) -> Self { match addr { Address::SocketAddress(a) => Self::SocketAddress(SocketAddr::V4(a)), Address::DomainNameAddress(d, p) => Self::DomainNameAddress(d, p), } } } /// Handshake Request /// /// ```plain /// The client connects to the SOCKS server and sends a CONNECT/BIND request when /// it wants to establish a connection to an application server. The client /// includes in the request packet the IP address and the port number of the /// destination host, and userid, in the following format. /// /// +----+----+----+----+----+----+----+----+----+----+....+----+ /// | VN | CD | DSTPORT | DSTIP | USERID |NULL| /// +----+----+----+----+----+----+----+----+----+----+....+----+ /// # of bytes: 1 1 2 4 variable 1 /// /// VN is the SOCKS protocol version number and should be 4. CD is the /// SOCKS command code and should be 1 for CONNECT request, 2 for BIND request. NULL is a byte /// of all zero bits. /// ``` #[derive(Debug, Clone)] pub struct HandshakeRequest { pub cd: Command, pub dst: Address, pub user_id: Vec, } impl HandshakeRequest { /// Read from a reader pub async fn read_from(r: &mut R) -> Result where R: AsyncBufRead + Unpin, { let mut buf = [0u8; 8]; let _ = r.read_exact(&mut buf).await?; let vn = buf[0]; if vn != consts::SOCKS4_VERSION { return Err(Error::UnsupportedSocksVersion(vn)); } let cd = buf[1]; let command = match Command::from_u8(cd) { Some(c) => c, None => { return Err(Error::UnsupportedSocksVersion(cd)); } }; let port = BigEndian::read_u16(&buf[2..4]); let mut user_id = Vec::new(); let _ = r.read_until(b'\0', &mut user_id).await?; if user_id.is_empty() || user_id.last() != Some(&b'\0') { return Err(io::Error::from(ErrorKind::UnexpectedEof).into()); } user_id.pop(); // Pops the last b'\0' let dst = if buf[4] == 0x00 && buf[5] == 0x00 && buf[6] == 0x00 && buf[7] != 0x00 { // SOCKS4a, indicates that it is a HOST address let mut host = Vec::new(); let _ = r.read_until(b'\0', &mut host).await?; if host.is_empty() || host.last() != Some(&b'\0') { return Err(io::Error::from(ErrorKind::UnexpectedEof).into()); } host.pop(); // Pops the last b'\0' match String::from_utf8(host) { Ok(host) => Address::DomainNameAddress(host, port), Err(..) => { return Err(Error::AddressHostInvalidEncoding); } } } else { let ip = Ipv4Addr::new(buf[4], buf[5], buf[6], buf[7]); Address::SocketAddress(SocketAddrV4::new(ip, port)) }; Ok(Self { cd: command, dst, user_id, }) } /// Writes to writer pub async fn write_to(&self, w: &mut W) -> io::Result<()> where W: AsyncWrite + Unpin, { let mut buf = BytesMut::with_capacity(self.serialized_len()); self.write_to_buf(&mut buf); w.write_all(&buf).await } /// Writes to buffer pub fn write_to_buf(&self, buf: &mut B) { debug_assert!( !self.user_id.contains(&b'\0'), "USERID shouldn't contain any NULL characters" ); buf.put_u8(consts::SOCKS4_VERSION); buf.put_u8(self.cd.as_u8()); match self.dst { Address::SocketAddress(ref saddr) => { let port = saddr.port(); buf.put_u16(port); buf.put_slice(&saddr.ip().octets()); buf.put_slice(&self.user_id); buf.put_u8(b'\0'); } Address::DomainNameAddress(ref dname, port) => { buf.put_u16(port); // 0.0.0.x (x != 0) const PLACEHOLDER: [u8; 4] = [0x00, 0x00, 0x00, 0xff]; buf.put_slice(&PLACEHOLDER); buf.put_slice(&self.user_id); buf.put_u8(b'\0'); buf.put_slice(dname.as_bytes()); buf.put_u8(b'\0'); } } } /// Length in bytes #[inline] pub fn serialized_len(&self) -> usize { let mut s = 1 + 1 + 2 + 4 + self.user_id.len() + 1; // USERID.LEN + NULL if let Address::DomainNameAddress(ref dname, _) = self.dst { s += dname.len() + 1; } s } } /// Handshake Response /// /// ```plain /// +----+----+----+----+----+----+----+----+ /// | VN | CD | DSTPORT | DSTIP | /// +----+----+----+----+----+----+----+----+ /// # of bytes: 1 1 2 4 /// ``` #[derive(Debug, Clone)] pub struct HandshakeResponse { pub cd: ResultCode, } impl HandshakeResponse { /// Create a response with code pub fn new(code: ResultCode) -> Self { Self { cd: code } } /// Read from a reader pub async fn read_from(r: &mut R) -> Result where R: AsyncRead + Unpin, { let mut buf = [0u8; 8]; let _ = r.read_exact(&mut buf).await?; let vn = buf[0]; if vn != 0 { return Err(Error::UnsupportedSocksVersion(vn)); } let cd = buf[1]; let result_code = ResultCode::from_u8(cd); // DSTPORT, DSTIP are ignored Ok(Self { cd: result_code }) } /// Write data into a writer pub async fn write_to(&self, w: &mut W) -> io::Result<()> where W: AsyncWrite + Unpin, { let mut buf = BytesMut::with_capacity(self.serialized_len()); self.write_to_buf(&mut buf); w.write_all(&buf).await } /// Writes to buffer pub fn write_to_buf(&self, buf: &mut B) { let Self { ref cd } = *self; buf.put_slice(&[ // VN: Result Code's version, must be 0 0x00, // CD: Result Code cd.as_u8(), // DSTPORT: Ignored 0x00, 0x00, // DSTIP: Ignored 0x00, 0x00, 0x00, 0x00, ]); } /// Length in bytes #[inline] pub fn serialized_len(&self) -> usize { 1 + 1 + 2 + 4 } } /// SOCKS 4/4a Error #[derive(Error, Debug)] pub enum Error { // I/O Error #[error("{0}")] IoError(#[from] io::Error), #[error("host must be UTF-8 encoding")] AddressHostInvalidEncoding, #[error("unsupported socks version {0:#x}")] UnsupportedSocksVersion(u8), #[error("unsupported command {0:#x}")] UnsupportedCommand(u8), #[error("{0}")] Result(ResultCode), } impl From for io::Error { fn from(err: Error) -> Self { match err { Error::IoError(err) => err, e => Self::other(e), } } } ================================================ FILE: crates/shadowsocks-service/src/local/tun/fake_tun.rs ================================================ //! Fake `tun` for those platforms that doesn't support `tun` #![allow(dead_code)] use std::{ io::{self, Read, Write}, net::IpAddr, ops::{Deref, DerefMut}, pin::Pin, task::{Context, Poll}, }; use tokio::io::{AsyncRead, AsyncWrite, ReadBuf}; /// TUN interface OSI layer of operation. #[derive(Clone, Copy, Default, Debug, Eq, PartialEq)] pub enum Layer { L2, #[default] L3, } /// Configuration builder for a TUN interface. #[derive(Clone, Default, Debug)] pub struct Configuration; impl Configuration { /// Set the tun name. /// /// [Note: on macOS, the tun name must be the form `utunx` where `x` is a number, such as `utun3`. -- end note] pub fn tun_name>(&mut self, _tun_name: S) -> &mut Self { self } /// Set the address. pub fn address(&mut self, _value: IpAddr) -> &mut Self { self } /// Set the destination address. pub fn destination(&mut self, _value: IpAddr) -> &mut Self { self } /// Set the broadcast address. pub fn broadcast(&mut self, _value: IpAddr) -> &mut Self { self } /// Set the netmask. pub fn netmask(&mut self, _value: IpAddr) -> &mut Self { self } /// Set the MTU. pub fn mtu(&mut self, _value: u16) -> &mut Self { self } /// Set the interface to be enabled once created. pub fn up(&mut self) -> &mut Self { self } /// Set the interface to be disabled once created. pub fn down(&mut self) -> &mut Self { self } /// Set the OSI layer of operation. pub fn layer(&mut self, _value: Layer) -> &mut Self { self } /// Set the raw fd. #[cfg(unix)] pub fn raw_fd(&mut self, _fd: ::std::os::fd::RawFd) -> &mut Self { self } } /// tun Error type #[derive(thiserror::Error, Debug)] pub enum Error { #[error("not implemented")] NotImplemented, #[error(transparent)] Io(#[from] std::io::Error), } pub type Result = ::std::result::Result; /// A TUN abstract device interface. pub trait AbstractDevice: Read + Write { /// Reconfigure the device. fn configure(&mut self, _config: &Configuration) -> Result<()> { Ok(()) } /// Get the device index. fn tun_index(&self) -> Result; /// Get the device tun name. fn tun_name(&self) -> Result; /// Set the device tun name. fn set_tun_name(&mut self, tun_name: &str) -> Result<()>; /// Turn on or off the interface. fn enabled(&mut self, value: bool) -> Result<()>; /// Get the address. fn address(&self) -> Result; /// Set the address. fn set_address(&mut self, value: IpAddr) -> Result<()>; /// Get the destination address. fn destination(&self) -> Result; /// Set the destination address. fn set_destination(&mut self, value: IpAddr) -> Result<()>; /// Get the broadcast address. fn broadcast(&self) -> Result; /// Set the broadcast address. fn set_broadcast(&mut self, value: IpAddr) -> Result<()>; /// Get the netmask. fn netmask(&self) -> Result; /// Set the netmask. fn set_netmask(&mut self, value: IpAddr) -> Result<()>; /// Get the MTU. fn mtu(&self) -> Result; /// Set the MTU. /// /// [Note: This setting has no effect on the Windows platform due to the mtu of wintun is always 65535. --end note] fn set_mtu(&mut self, value: u16) -> Result<()>; /// Return whether the underlying tun device on the platform has packet information /// /// [Note: This value is not used to specify whether the packets delivered from/to tun have packet information. -- end note] fn packet_information(&self) -> bool; } pub struct FakeQueue; impl Read for FakeQueue { fn read(&mut self, _: &mut [u8]) -> io::Result { Err(io::Error::other("not implemented")) } } impl Write for FakeQueue { fn write(&mut self, _: &[u8]) -> io::Result { Err(io::Error::other("not implemented")) } fn flush(&mut self) -> io::Result<()> { Err(io::Error::other("not implemented")) } } pub struct FakeDevice; impl AbstractDevice for FakeDevice { fn tun_name(&self) -> Result { Err(Error::NotImplemented) } fn tun_index(&self) -> Result { Err(Error::NotImplemented) } fn set_tun_name(&mut self, _: &str) -> Result<()> { Err(Error::NotImplemented) } fn enabled(&mut self, _: bool) -> Result<()> { Err(Error::NotImplemented) } fn address(&self) -> Result { Err(Error::NotImplemented) } fn set_address(&mut self, _: IpAddr) -> Result<()> { Err(Error::NotImplemented) } fn destination(&self) -> Result { Err(Error::NotImplemented) } fn set_destination(&mut self, _: IpAddr) -> Result<()> { Err(Error::NotImplemented) } fn broadcast(&self) -> Result { Err(Error::NotImplemented) } fn set_broadcast(&mut self, _: IpAddr) -> Result<()> { Err(Error::NotImplemented) } fn netmask(&self) -> Result { Err(Error::NotImplemented) } fn set_netmask(&mut self, _: IpAddr) -> Result<()> { Err(Error::NotImplemented) } fn mtu(&self) -> Result { Err(Error::NotImplemented) } fn set_mtu(&mut self, _: u16) -> Result<()> { Err(Error::NotImplemented) } fn packet_information(&self) -> bool { false } } impl Read for FakeDevice { fn read(&mut self, _: &mut [u8]) -> io::Result { Err(io::Error::other("not implemented")) } } impl Write for FakeDevice { fn write(&mut self, _: &[u8]) -> io::Result { Err(io::Error::other("not implemented")) } fn flush(&mut self) -> io::Result<()> { Err(io::Error::other("not implemented")) } } pub struct AsyncDevice(FakeDevice); impl AsRef for AsyncDevice { fn as_ref(&self) -> &FakeDevice { &self.0 } } impl AsMut for AsyncDevice { fn as_mut(&mut self) -> &mut FakeDevice { &mut self.0 } } impl Deref for AsyncDevice { type Target = FakeDevice; fn deref(&self) -> &Self::Target { &self.0 } } impl DerefMut for AsyncDevice { fn deref_mut(&mut self) -> &mut Self::Target { &mut self.0 } } impl AsyncRead for AsyncDevice { fn poll_read(self: Pin<&mut Self>, _cx: &mut Context<'_>, _buf: &mut ReadBuf<'_>) -> Poll> { Err(io::Error::other("not implemented")).into() } } impl AsyncWrite for AsyncDevice { fn poll_write(self: Pin<&mut Self>, _cx: &mut Context<'_>, _buf: &[u8]) -> Poll> { Err(io::Error::other("not implemented")).into() } fn poll_flush(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll> { Err(io::Error::other("not implemented")).into() } fn poll_shutdown(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll> { Err(io::Error::other("not implemented")).into() } } /// Create a TUN device with the given name. pub fn create_as_async(_: &Configuration) -> Result { Err(Error::NotImplemented) } ================================================ FILE: crates/shadowsocks-service/src/local/tun/ip_packet.rs ================================================ //! IP packet encapsulation use std::net::IpAddr; use smoltcp::wire::{IpProtocol, IpVersion, Ipv4Packet, Ipv6Packet}; #[derive(Debug)] pub enum IpPacket> { Ipv4(Ipv4Packet), Ipv6(Ipv6Packet), } impl + Copy> IpPacket { pub fn new_checked(packet: T) -> smoltcp::wire::Result> { let buffer = packet.as_ref(); match IpVersion::of_packet(buffer)? { IpVersion::Ipv4 => Ok(Some(Self::Ipv4(Ipv4Packet::new_checked(packet)?))), IpVersion::Ipv6 => Ok(Some(Self::Ipv6(Ipv6Packet::new_checked(packet)?))), } } pub fn src_addr(&self) -> IpAddr { match *self { Self::Ipv4(ref packet) => IpAddr::from(packet.src_addr()), Self::Ipv6(ref packet) => IpAddr::from(packet.src_addr()), } } pub fn dst_addr(&self) -> IpAddr { match *self { Self::Ipv4(ref packet) => IpAddr::from(packet.dst_addr()), Self::Ipv6(ref packet) => IpAddr::from(packet.dst_addr()), } } pub fn protocol(&self) -> IpProtocol { match *self { Self::Ipv4(ref packet) => packet.next_header(), Self::Ipv6(ref packet) => packet.next_header(), } } } impl<'a, T: AsRef<[u8]> + ?Sized> IpPacket<&'a T> { /// Return a pointer to the payload. #[inline] pub fn payload(&self) -> &'a [u8] { match *self { IpPacket::Ipv4(ref packet) => packet.payload(), IpPacket::Ipv6(ref packet) => packet.payload(), } } } ================================================ FILE: crates/shadowsocks-service/src/local/tun/mod.rs ================================================ //! Shadowsocks Local server serving on a Tun interface #[cfg(unix)] use std::os::unix::io::RawFd; use std::{ io, mem, net::{IpAddr, SocketAddr}, sync::Arc, time::Duration, }; use byte_string::ByteStr; use cfg_if::cfg_if; use ipnet::IpNet; use log::{debug, error, info, trace, warn}; use shadowsocks::config::Mode; use smoltcp::wire::{IpProtocol, TcpPacket, UdpPacket}; use tokio::{ io::{AsyncReadExt, AsyncWriteExt}, sync::mpsc, time, }; cfg_if! { if #[cfg(any(target_os = "ios", target_os = "macos", target_os = "linux", target_os = "android", target_os = "windows", target_os = "freebsd"))] { use tun::{ create_as_async, AsyncDevice, Configuration as TunConfiguration, AbstractDevice, Error as TunError, Layer, }; } else { mod fake_tun; use self::fake_tun::{ AbstractDevice, AsyncDevice, Configuration as TunConfiguration, Error as TunError, Layer, create_as_async, }; } } use crate::local::{context::ServiceContext, loadbalancing::PingBalancer}; use self::{ip_packet::IpPacket, tcp::TcpTun, udp::UdpTun, virt_device::TokenBuffer}; mod ip_packet; mod tcp; mod udp; mod virt_device; /// Tun service builder pub struct TunBuilder { context: Arc, balancer: PingBalancer, tun_config: TunConfiguration, udp_expiry_duration: Option, udp_capacity: Option, mode: Mode, } /// TunConfiguration contains a HANDLE, which is a *mut c_void on Windows. unsafe impl Send for TunBuilder {} impl TunBuilder { /// Create a Tun service builder pub fn new(context: Arc, balancer: PingBalancer) -> Self { Self { context, balancer, tun_config: TunConfiguration::default(), udp_expiry_duration: None, udp_capacity: None, mode: Mode::TcpOnly, } } pub fn address(&mut self, addr: IpNet) { self.tun_config.address(addr.addr()).netmask(addr.netmask()); } pub fn destination(&mut self, addr: IpNet) { self.tun_config.destination(addr.addr()); } pub fn name(&mut self, name: &str) { self.tun_config.tun_name(name); } #[cfg(unix)] pub fn file_descriptor(&mut self, fd: RawFd) { self.tun_config.raw_fd(fd); } pub fn udp_expiry_duration(&mut self, udp_expiry_duration: Duration) { self.udp_expiry_duration = Some(udp_expiry_duration); } pub fn udp_capacity(&mut self, udp_capacity: usize) { self.udp_capacity = Some(udp_capacity); } pub fn mode(&mut self, mode: Mode) { self.mode = mode; } /// Build Tun server pub async fn build(mut self) -> io::Result { self.tun_config.layer(Layer::L3).up(); // XXX: tun2 set IFF_NO_PI by default. // // #[cfg(target_os = "linux")] // self.tun_config.platform_config(|tun_config| { // // IFF_NO_PI preventing excessive buffer reallocating // tun_config.packet_information(false); // }); let device = match create_as_async(&self.tun_config) { Ok(d) => d, Err(TunError::Io(err)) => return Err(err), Err(err) => return Err(io::Error::other(err)), }; let (udp, udp_cleanup_interval, udp_keepalive_rx) = UdpTun::new( self.context.clone(), self.balancer.clone(), self.udp_expiry_duration, self.udp_capacity, ); let tcp = TcpTun::new(self.context, self.balancer, device.mtu().unwrap_or(1500) as u32); Ok(Tun { device, tcp, udp, udp_cleanup_interval, udp_keepalive_rx, mode: self.mode, }) } } /// Tun service pub struct Tun { device: AsyncDevice, tcp: TcpTun, udp: UdpTun, udp_cleanup_interval: Duration, udp_keepalive_rx: mpsc::Receiver, mode: Mode, } impl Tun { /// Start serving pub async fn run(mut self) -> io::Result<()> { info!( "shadowsocks tun device {}, mode {}", self.device.tun_name().or_else(|r| Ok::<_, ()>(r.to_string())).unwrap(), self.mode, ); let address = match self.device.address() { Ok(a) => a, Err(err) => { error!("[TUN] failed to get device address, error: {}", err); return Err(io::Error::other(err)); } }; let netmask = match self.device.netmask() { Ok(n) => n, Err(err) => { error!("[TUN] failed to get device netmask, error: {}", err); return Err(io::Error::other(err)); } }; let address_net = match IpNet::with_netmask(address, netmask) { Ok(n) => n, Err(err) => { error!("[TUN] invalid address {}, netmask {}, error: {}", address, netmask, err); return Err(io::Error::other(err)); } }; trace!( "[TUN] tun device network: {} (address: {}, netmask: {})", address_net, address, netmask ); let address_broadcast = address_net.broadcast(); let create_packet_buffer = || { const PACKET_BUFFER_SIZE: usize = 65536; let mut packet_buffer = TokenBuffer::with_capacity(PACKET_BUFFER_SIZE); unsafe { packet_buffer.set_len(PACKET_BUFFER_SIZE); } packet_buffer }; let mut packet_buffer = create_packet_buffer(); let mut udp_cleanup_timer = time::interval(self.udp_cleanup_interval); loop { tokio::select! { // tun device n = self.device.read(&mut packet_buffer) => { let n = n?; let mut packet_buffer = mem::replace(&mut packet_buffer, create_packet_buffer()); unsafe { packet_buffer.set_len(n); } trace!("[TUN] received IP packet {:?}", ByteStr::new(&packet_buffer)); if let Err(err) = self.handle_tun_frame(&address_broadcast, packet_buffer).await { error!("[TUN] handle IP frame failed, error: {}", err); } } // UDP channel sent back packet = self.udp.recv_packet() => { match self.device.write(&packet).await { Ok(n) => { if n < packet.len() { warn!("[TUN] sent IP packet (UDP), but truncated. sent {} < {}, {:?}", n, packet.len(), ByteStr::new(&packet)); } else { trace!("[TUN] sent IP packet (UDP) {:?}", ByteStr::new(&packet)); } } Err(err) => { error!("[TUN] failed to set packet information, error: {}, {:?}", err, ByteStr::new(&packet)); } } } // UDP cleanup expired associations _ = udp_cleanup_timer.tick() => { self.udp.cleanup_expired().await; } // UDP keep-alive associations peer_addr_opt = self.udp_keepalive_rx.recv() => { let peer_addr = peer_addr_opt.expect("UDP keep-alive channel closed unexpectedly"); self.udp.keep_alive(&peer_addr).await; } // TCP channel sent back packet = self.tcp.recv_packet() => { match self.device.write(&packet).await { Ok(n) => { if n < packet.len() { warn!("[TUN] sent IP packet (TCP), but truncated. sent {} < {}, {:?}", n, packet.len(), ByteStr::new(&packet)); } else { trace!("[TUN] sent IP packet (TCP) {:?}", ByteStr::new(&packet)); } } Err(err) => { error!("[TUN] failed to set packet information, error: {}, {:?}", err, ByteStr::new(&packet)); } } } } } } async fn handle_tun_frame( &mut self, device_broadcast_addr: &IpAddr, frame: TokenBuffer, ) -> smoltcp::wire::Result<()> { let packet = match IpPacket::new_checked(frame.as_ref())? { Some(packet) => packet, None => { warn!("unrecognized IP packet {:?}", ByteStr::new(&frame)); return Ok(()); } }; trace!("[TUN] {:?}", packet); let src_ip_addr = packet.src_addr(); let dst_ip_addr = packet.dst_addr(); let src_non_unicast = src_ip_addr == *device_broadcast_addr || match src_ip_addr { IpAddr::V4(v4) => v4.is_broadcast() || v4.is_multicast() || v4.is_unspecified(), IpAddr::V6(v6) => v6.is_multicast() || v6.is_unspecified(), }; let dst_non_unicast = dst_ip_addr == *device_broadcast_addr || match dst_ip_addr { IpAddr::V4(v4) => v4.is_broadcast() || v4.is_multicast() || v4.is_unspecified(), IpAddr::V6(v6) => v6.is_multicast() || v6.is_unspecified(), }; if src_non_unicast || dst_non_unicast { trace!( "[TUN] IP packet {} (unicast? {}) -> {} (unicast? {}) throwing away", src_ip_addr, !src_non_unicast, dst_ip_addr, !dst_non_unicast ); return Ok(()); } match packet.protocol() { IpProtocol::Tcp => { if !self.mode.enable_tcp() { trace!("received TCP packet but mode is {}, throwing away", self.mode); return Ok(()); } let tcp_packet = match TcpPacket::new_checked(packet.payload()) { Ok(p) => p, Err(err) => { error!( "invalid TCP packet err: {}, src_ip: {}, dst_ip: {}, payload: {:?}", err, packet.src_addr(), packet.dst_addr(), ByteStr::new(packet.payload()) ); return Ok(()); } }; let src_port = tcp_packet.src_port(); let dst_port = tcp_packet.dst_port(); let src_addr = SocketAddr::new(packet.src_addr(), src_port); let dst_addr = SocketAddr::new(packet.dst_addr(), dst_port); trace!( "[TUN] TCP packet {} (unicast? {}) -> {} (unicast? {}) {}", src_addr, !src_non_unicast, dst_addr, !dst_non_unicast, tcp_packet ); // TCP first handshake packet. if let Err(err) = self.tcp.handle_packet(src_addr, dst_addr, &tcp_packet).await { error!( "handle TCP packet failed, error: {}, {} <-> {}, packet: {:?}", err, src_addr, dst_addr, tcp_packet ); } self.tcp.drive_interface_state(frame).await; } IpProtocol::Udp => { if !self.mode.enable_udp() { trace!("received UDP packet but mode is {}, throwing away", self.mode); return Ok(()); } let udp_packet = match UdpPacket::new_checked(packet.payload()) { Ok(p) => p, Err(err) => { error!( "invalid UDP packet err: {}, src_ip: {}, dst_ip: {}, payload: {:?}", err, packet.src_addr(), packet.dst_addr(), ByteStr::new(packet.payload()) ); return Ok(()); } }; let src_port = udp_packet.src_port(); let dst_port = udp_packet.dst_port(); let src_addr = SocketAddr::new(src_ip_addr, src_port); let dst_addr = SocketAddr::new(packet.dst_addr(), dst_port); let payload = udp_packet.payload(); trace!( "[TUN] UDP packet {} (unicast? {}) -> {} (unicast? {}) {}", src_addr, !src_non_unicast, dst_addr, !dst_non_unicast, udp_packet ); if let Err(err) = self.udp.handle_packet(src_addr, dst_addr, payload).await { error!("handle UDP packet failed, err: {}, packet: {:?}", err, udp_packet); } } IpProtocol::Icmp | IpProtocol::Icmpv6 => { // ICMP is handled by TCP's Interface. // smoltcp's interface will always send replies to EchoRequest self.tcp.drive_interface_state(frame).await; } _ => { debug!("IP packet ignored (protocol: {:?})", packet.protocol()); return Ok(()); } } Ok(()) } } ================================================ FILE: crates/shadowsocks-service/src/local/tun/tcp.rs ================================================ use std::{ collections::HashMap, future::Future, io, mem, net::{IpAddr, SocketAddr}, pin::Pin, sync::{ Arc, atomic::{AtomicBool, Ordering}, }, task::{Context, Poll, Waker}, thread::{self, JoinHandle, Thread}, time::Duration, }; use log::{debug, error, trace}; use shadowsocks::{net::TcpSocketOpts, relay::socks5::Address}; use smoltcp::{ iface::{Config as InterfaceConfig, Interface, PollResult, SocketHandle, SocketSet}, phy::{Checksum, DeviceCapabilities, Medium}, socket::tcp::{CongestionControl, Socket as TcpSocket, SocketBuffer as TcpSocketBuffer, State as TcpState}, storage::RingBuffer, time::{Duration as SmolDuration, Instant as SmolInstant}, wire::{HardwareAddress, IpAddress, IpCidr, Ipv4Address, Ipv6Address, TcpPacket}, }; use spin::Mutex as SpinMutex; use tokio::{ io::{AsyncRead, AsyncWrite, ReadBuf}, sync::{mpsc, oneshot}, }; use crate::{ local::{ context::ServiceContext, loadbalancing::PingBalancer, net::AutoProxyClientStream, utils::{establish_tcp_tunnel, establish_tcp_tunnel_bypassed}, }, net::utils::to_ipv4_mapped, }; use super::virt_device::{TokenBuffer, VirtTunDevice}; // NOTE: Default buffer could contain 5 AEAD packets const DEFAULT_TCP_SEND_BUFFER_SIZE: u32 = (0x3FFFu32 * 5).next_power_of_two(); const DEFAULT_TCP_RECV_BUFFER_SIZE: u32 = (0x3FFFu32 * 5).next_power_of_two(); #[derive(Debug, Clone, Copy, Eq, PartialEq)] enum TcpSocketState { Normal, Close, Closing, Closed, } struct TcpSocketControl { send_buffer: RingBuffer<'static, u8>, send_waker: Option, recv_buffer: RingBuffer<'static, u8>, recv_waker: Option, recv_state: TcpSocketState, send_state: TcpSocketState, } struct ManagerNotify { thread: Thread, } impl ManagerNotify { fn new(thread: Thread) -> Self { Self { thread } } fn notify(&self) { self.thread.unpark(); } } struct TcpSocketManager { device: VirtTunDevice, iface: Interface, sockets: HashMap, socket_creation_rx: mpsc::UnboundedReceiver, } type SharedTcpConnectionControl = Arc>; struct TcpSocketCreation { control: SharedTcpConnectionControl, socket: TcpSocket<'static>, socket_created_tx: oneshot::Sender<()>, } struct TcpConnection { control: SharedTcpConnectionControl, manager_notify: Arc, } impl Drop for TcpConnection { fn drop(&mut self) { let mut control = self.control.lock(); if matches!(control.recv_state, TcpSocketState::Normal) { control.recv_state = TcpSocketState::Close; } if matches!(control.send_state, TcpSocketState::Normal) { control.send_state = TcpSocketState::Close; } self.manager_notify.notify(); } } impl TcpConnection { fn new( socket: TcpSocket<'static>, socket_creation_tx: &mpsc::UnboundedSender, manager_notify: Arc, tcp_opts: &TcpSocketOpts, ) -> impl Future + use<> { let send_buffer_size = tcp_opts.send_buffer_size.unwrap_or(DEFAULT_TCP_SEND_BUFFER_SIZE); let recv_buffer_size = tcp_opts.recv_buffer_size.unwrap_or(DEFAULT_TCP_RECV_BUFFER_SIZE); let control = Arc::new(SpinMutex::new(TcpSocketControl { send_buffer: RingBuffer::new(vec![0u8; send_buffer_size as usize]), send_waker: None, recv_buffer: RingBuffer::new(vec![0u8; recv_buffer_size as usize]), recv_waker: None, recv_state: TcpSocketState::Normal, send_state: TcpSocketState::Normal, })); let (tx, rx) = oneshot::channel(); let _ = socket_creation_tx.send(TcpSocketCreation { control: control.clone(), socket, socket_created_tx: tx, }); async move { // waiting socket add to SocketSet let _ = rx.await; Self { control, manager_notify, } } } } impl AsyncRead for TcpConnection { fn poll_read(self: Pin<&mut Self>, cx: &mut Context<'_>, buf: &mut ReadBuf<'_>) -> Poll> { let mut control = self.control.lock(); // Read from buffer if control.recv_buffer.is_empty() { // If socket is already closed / half closed, just return EOF directly. if matches!(control.recv_state, TcpSocketState::Closed) { return Ok(()).into(); } // Nothing could be read. Wait for notify. if let Some(old_waker) = control.recv_waker.replace(cx.waker().clone()) && !old_waker.will_wake(cx.waker()) { old_waker.wake(); } return Poll::Pending; } let recv_buf = unsafe { mem::transmute::<&mut [mem::MaybeUninit], &mut [u8]>(buf.unfilled_mut()) }; let n = control.recv_buffer.dequeue_slice(recv_buf); buf.advance(n); if n > 0 { self.manager_notify.notify(); } Ok(()).into() } } impl AsyncWrite for TcpConnection { fn poll_write(self: Pin<&mut Self>, cx: &mut Context<'_>, buf: &[u8]) -> Poll> { let mut control = self.control.lock(); // If state == Close | Closing | Closed, the TCP stream WR half is closed. if !matches!(control.send_state, TcpSocketState::Normal) { return Err(io::ErrorKind::BrokenPipe.into()).into(); } // Write to buffer if control.send_buffer.is_full() { if let Some(old_waker) = control.send_waker.replace(cx.waker().clone()) && !old_waker.will_wake(cx.waker()) { old_waker.wake(); } return Poll::Pending; } let n = control.send_buffer.enqueue_slice(buf); if n > 0 { self.manager_notify.notify(); } Ok(n).into() } fn poll_flush(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll> { Ok(()).into() } fn poll_shutdown(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { let mut control = self.control.lock(); if matches!(control.send_state, TcpSocketState::Closed) { return Ok(()).into(); } // SHUT_WR if matches!(control.send_state, TcpSocketState::Normal) { control.send_state = TcpSocketState::Close; } if let Some(old_waker) = control.send_waker.replace(cx.waker().clone()) && !old_waker.will_wake(cx.waker()) { old_waker.wake(); } self.manager_notify.notify(); Poll::Pending } } pub struct TcpTun { context: Arc, manager_handle: Option>, manager_notify: Arc, manager_socket_creation_tx: mpsc::UnboundedSender, manager_running: Arc, balancer: PingBalancer, iface_rx: mpsc::UnboundedReceiver, iface_tx: mpsc::UnboundedSender, iface_tx_avail: Arc, } impl Drop for TcpTun { fn drop(&mut self) { self.manager_running.store(false, Ordering::Relaxed); self.manager_notify.notify(); let _ = self.manager_handle.take().unwrap().join(); } } impl TcpTun { pub fn new(context: Arc, balancer: PingBalancer, mtu: u32) -> Self { let mut capabilities = DeviceCapabilities::default(); capabilities.medium = Medium::Ip; capabilities.max_transmission_unit = mtu as usize; capabilities.checksum.ipv4 = Checksum::Tx; capabilities.checksum.tcp = Checksum::Tx; capabilities.checksum.udp = Checksum::Tx; capabilities.checksum.icmpv4 = Checksum::Tx; capabilities.checksum.icmpv6 = Checksum::Tx; let (mut device, iface_rx, iface_tx, iface_tx_avail) = VirtTunDevice::new(capabilities); let mut iface_config = InterfaceConfig::new(HardwareAddress::Ip); iface_config.random_seed = rand::random(); let mut iface = Interface::new(iface_config, &mut device, SmolInstant::now()); iface.update_ip_addrs(|ip_addrs| { ip_addrs .push(IpCidr::new(IpAddress::v4(0, 0, 0, 1), 0)) .expect("iface IPv4"); ip_addrs .push(IpCidr::new(IpAddress::v6(0, 0, 0, 0, 0, 0, 0, 1), 0)) .expect("iface IPv6"); }); iface .routes_mut() .add_default_ipv4_route(Ipv4Address::new(0, 0, 0, 1)) .expect("IPv4 default route"); iface .routes_mut() .add_default_ipv6_route(Ipv6Address::new(0, 0, 0, 0, 0, 0, 0, 1)) .expect("IPv6 default route"); iface.set_any_ip(true); let (manager_socket_creation_tx, manager_socket_creation_rx) = mpsc::unbounded_channel(); let mut manager = TcpSocketManager { device, iface, sockets: HashMap::new(), socket_creation_rx: manager_socket_creation_rx, }; let manager_running = Arc::new(AtomicBool::new(true)); let manager_handle = { let manager_running = manager_running.clone(); thread::Builder::new() .name("smoltcp-poll".to_owned()) .spawn(move || { let TcpSocketManager { ref mut device, ref mut iface, ref mut sockets, ref mut socket_creation_rx, .. } = manager; let mut socket_set = SocketSet::new(vec![]); while manager_running.load(Ordering::Relaxed) { while let Ok(TcpSocketCreation { control, socket, socket_created_tx: socket_create_tx, }) = socket_creation_rx.try_recv() { let handle = socket_set.add(socket); let _ = socket_create_tx.send(()); sockets.insert(handle, control); } let before_poll = SmolInstant::now(); if let PollResult::SocketStateChanged = iface.poll(before_poll, device, &mut socket_set) { trace!("VirtDevice::poll costed {}", SmolInstant::now() - before_poll); } // Check all the sockets' status let mut sockets_to_remove = Vec::new(); for (socket_handle, control) in sockets.iter() { let socket_handle = *socket_handle; let socket = socket_set.get_mut::(socket_handle); let mut control = control.lock(); // Remove the socket only when it is in the closed state. if socket.state() == TcpState::Closed { sockets_to_remove.push(socket_handle); control.send_state = TcpSocketState::Closed; control.recv_state = TcpSocketState::Closed; if let Some(waker) = control.send_waker.take() { waker.wake(); } if let Some(waker) = control.recv_waker.take() { waker.wake(); } trace!("closed TCP connection"); continue; } // SHUT_WR if matches!(control.send_state, TcpSocketState::Close) && socket.send_queue() == 0 && control.send_buffer.is_empty() { trace!("closing TCP Write Half, {:?}", socket.state()); // Close the socket. Set to FIN state socket.close(); control.send_state = TcpSocketState::Closing; // We can still process the pending buffer. } // Check if readable let mut wake_receiver = false; while socket.can_recv() && !control.recv_buffer.is_full() { let result = socket.recv(|buffer| { let n = control.recv_buffer.enqueue_slice(buffer); (n, ()) }); match result { Ok(..) => { wake_receiver = true; } Err(err) => { error!("socket recv error: {:?}, {:?}", err, socket.state()); // Don't know why. Abort the connection. socket.abort(); if matches!(control.recv_state, TcpSocketState::Normal) { control.recv_state = TcpSocketState::Closed; } wake_receiver = true; // The socket will be recycled in the next poll. break; } } } // If socket is not in ESTABLISH, FIN-WAIT-1, FIN-WAIT-2, // the local client have closed our receiver. if matches!(control.recv_state, TcpSocketState::Normal) && !socket.may_recv() && !matches!( socket.state(), TcpState::Listen | TcpState::SynReceived | TcpState::Established | TcpState::FinWait1 | TcpState::FinWait2 ) { trace!("closed TCP Read Half, {:?}", socket.state()); // Let TcpConnection::poll_read returns EOF. control.recv_state = TcpSocketState::Closed; wake_receiver = true; } if wake_receiver && control.recv_waker.is_some() && let Some(waker) = control.recv_waker.take() { waker.wake(); } // Check if writable let mut wake_sender = false; while socket.can_send() && !control.send_buffer.is_empty() { let result = socket.send(|buffer| { let n = control.send_buffer.dequeue_slice(buffer); (n, ()) }); match result { Ok(..) => { wake_sender = true; } Err(err) => { error!("socket send error: {:?}, {:?}", err, socket.state()); // Don't know why. Abort the connection. socket.abort(); if matches!(control.send_state, TcpSocketState::Normal) { control.send_state = TcpSocketState::Closed; } wake_sender = true; // The socket will be recycled in the next poll. break; } } } if wake_sender && control.send_waker.is_some() && let Some(waker) = control.send_waker.take() { waker.wake(); } } for socket_handle in sockets_to_remove { sockets.remove(&socket_handle); socket_set.remove(socket_handle); } if !device.recv_available() { let next_duration = iface .poll_delay(before_poll, &socket_set) .unwrap_or(SmolDuration::from_millis(5)); if next_duration != SmolDuration::ZERO { thread::park_timeout(Duration::from(next_duration)); } } } trace!("VirtDevice::poll thread exited"); }) .unwrap() }; let manager_notify = Arc::new(ManagerNotify::new(manager_handle.thread().clone())); Self { context, manager_handle: Some(manager_handle), manager_notify, manager_socket_creation_tx, manager_running, balancer, iface_rx, iface_tx, iface_tx_avail, } } pub async fn handle_packet( &mut self, src_addr: SocketAddr, dst_addr: SocketAddr, tcp_packet: &TcpPacket<&[u8]>, ) -> io::Result<()> { // TCP first handshake packet, create a new Connection if tcp_packet.syn() && !tcp_packet.ack() { let accept_opts = self.context.accept_opts(); let send_buffer_size = accept_opts.tcp.send_buffer_size.unwrap_or(DEFAULT_TCP_SEND_BUFFER_SIZE); let recv_buffer_size = accept_opts.tcp.recv_buffer_size.unwrap_or(DEFAULT_TCP_RECV_BUFFER_SIZE); let mut socket = TcpSocket::new( TcpSocketBuffer::new(vec![0u8; recv_buffer_size as usize]), TcpSocketBuffer::new(vec![0u8; send_buffer_size as usize]), ); socket.set_keep_alive(accept_opts.tcp.keepalive.map(From::from)); // FIXME: It should follow system's setting. 7200 is Linux's default. socket.set_timeout(Some(SmolDuration::from_secs(7200))); // NO ACK delay // socket.set_ack_delay(None); // Enable Cubic congestion control socket.set_congestion_control(CongestionControl::Cubic); if let Err(err) = socket.listen(dst_addr) { return Err(io::Error::other(format!("listen error: {:?}", err))); } debug!("created TCP connection for {} <-> {}", src_addr, dst_addr); let connection = TcpConnection::new( socket, &self.manager_socket_creation_tx, self.manager_notify.clone(), &accept_opts.tcp, ); // establish a tunnel let context = self.context.clone(); let balancer = self.balancer.clone(); tokio::spawn(async move { let connection = connection.await; if let Err(err) = handle_redir_client(context, balancer, connection, src_addr, dst_addr).await { error!("TCP tunnel failure, {} <-> {}, error: {}", src_addr, dst_addr, err); } }); } Ok(()) } pub async fn drive_interface_state(&mut self, frame: TokenBuffer) { if self.iface_tx.send(frame).is_err() { panic!("interface send channel closed unexpectedly"); } // Wake up and poll the interface. self.iface_tx_avail.store(true, Ordering::Release); self.manager_notify.notify(); } pub async fn recv_packet(&mut self) -> TokenBuffer { match self.iface_rx.recv().await { Some(v) => v, None => unreachable!("channel closed unexpectedly"), } } } /// Established Client Transparent Proxy /// /// This method must be called after handshaking with client (for example, socks5 handshaking) async fn establish_client_tcp_redir( context: Arc, balancer: PingBalancer, mut stream: TcpConnection, peer_addr: SocketAddr, addr: &Address, ) -> io::Result<()> { if balancer.is_empty() { let mut remote = AutoProxyClientStream::connect_bypassed(context, addr).await?; return establish_tcp_tunnel_bypassed(&mut stream, &mut remote, peer_addr, addr).await; } let server = balancer.best_tcp_server(); let svr_cfg = server.server_config(); let mut remote = AutoProxyClientStream::connect_with_opts(context, &server, addr, server.connect_opts_ref()).await?; establish_tcp_tunnel(svr_cfg, &mut stream, &mut remote, peer_addr, addr).await } async fn handle_redir_client( context: Arc, balancer: PingBalancer, s: TcpConnection, peer_addr: SocketAddr, mut daddr: SocketAddr, ) -> io::Result<()> { // Get forward address from socket // // Try to convert IPv4 mapped IPv6 address for dual-stack mode. if let SocketAddr::V6(ref a) = daddr && let Some(v4) = to_ipv4_mapped(a.ip()) { daddr = SocketAddr::new(IpAddr::from(v4), a.port()); } let target_addr = Address::from(daddr); establish_client_tcp_redir(context, balancer, s, peer_addr, &target_addr).await } ================================================ FILE: crates/shadowsocks-service/src/local/tun/udp.rs ================================================ use std::{ io::{self, ErrorKind}, net::{IpAddr, SocketAddr}, sync::Arc, time::Duration, }; use bytes::{BufMut, BytesMut}; use etherparse::PacketBuilder; use log::debug; use shadowsocks::relay::socks5::Address; use tokio::sync::mpsc; use crate::{ local::{ context::ServiceContext, loadbalancing::PingBalancer, net::{UdpAssociationManager, UdpInboundWrite}, }, net::utils::to_ipv4_mapped, }; pub struct UdpTun { tun_rx: mpsc::Receiver, manager: UdpAssociationManager, } impl UdpTun { pub fn new( context: Arc, balancer: PingBalancer, time_to_live: Option, capacity: Option, ) -> (Self, Duration, mpsc::Receiver) { let (tun_tx, tun_rx) = mpsc::channel(64); let (manager, cleanup_interval, keepalive_rx) = UdpAssociationManager::new( context, UdpTunInboundWriter::new(tun_tx), time_to_live, capacity, balancer, ); (Self { tun_rx, manager }, cleanup_interval, keepalive_rx) } pub async fn handle_packet( &mut self, src_addr: SocketAddr, dst_addr: SocketAddr, payload: &[u8], ) -> io::Result<()> { debug!("UDP {} -> {} payload.size: {} bytes", src_addr, dst_addr, payload.len()); if let Err(err) = self.manager.send_to(src_addr, dst_addr.into(), payload).await { debug!( "UDP {} -> {} payload.size: {} bytes failed, error: {}", src_addr, dst_addr, payload.len(), err, ); } Ok(()) } pub async fn recv_packet(&mut self) -> BytesMut { match self.tun_rx.recv().await { Some(b) => b, None => unreachable!("channel closed unexpectedly"), } } #[inline(always)] pub async fn cleanup_expired(&mut self) { self.manager.cleanup_expired().await; } #[inline(always)] pub async fn keep_alive(&mut self, peer_addr: &SocketAddr) { self.manager.keep_alive(peer_addr).await; } } #[derive(Clone)] struct UdpTunInboundWriter { tun_tx: mpsc::Sender, } impl UdpTunInboundWriter { fn new(tun_tx: mpsc::Sender) -> Self { Self { tun_tx } } } impl UdpInboundWrite for UdpTunInboundWriter { async fn send_to(&self, peer_addr: SocketAddr, remote_addr: &Address, data: &[u8]) -> io::Result<()> { let addr = match *remote_addr { Address::SocketAddress(sa) => { // Try to convert IPv4 mapped IPv6 address if server is running on dual-stack mode match (peer_addr, sa) { (SocketAddr::V4(..), SocketAddr::V4(..)) | (SocketAddr::V6(..), SocketAddr::V6(..)) => sa, (SocketAddr::V4(..), SocketAddr::V6(v6)) => { // If peer is IPv4, then remote_addr can only be IPv4-mapped-IPv6 match to_ipv4_mapped(v6.ip()) { Some(v4) => SocketAddr::new(IpAddr::from(v4), v6.port()), None => { return Err(io::Error::new( ErrorKind::InvalidData, "source and destination type unmatch", )); } } } (SocketAddr::V6(..), SocketAddr::V4(v4)) => { // Convert remote_addr to IPv4-mapped-IPv6 SocketAddr::new(IpAddr::from(v4.ip().to_ipv6_mapped()), v4.port()) } } } Address::DomainNameAddress(..) => { let err = io::Error::new( ErrorKind::InvalidInput, "tun destination must not be an domain name address", ); return Err(err); } }; let packet = match (peer_addr, addr) { (SocketAddr::V4(peer), SocketAddr::V4(remote)) => { let builder = PacketBuilder::ipv4(remote.ip().octets(), peer.ip().octets(), 20).udp(remote.port(), peer.port()); let packet = BytesMut::with_capacity(builder.size(data.len())); let mut packet_writer = packet.writer(); builder.write(&mut packet_writer, data).expect("PacketBuilder::write"); packet_writer.into_inner() } (SocketAddr::V6(peer), SocketAddr::V6(remote)) => { let builder = PacketBuilder::ipv6(remote.ip().octets(), peer.ip().octets(), 20).udp(remote.port(), peer.port()); let packet = BytesMut::with_capacity(builder.size(data.len())); let mut packet_writer = packet.writer(); builder.write(&mut packet_writer, data).expect("PacketBuilder::write"); packet_writer.into_inner() } _ => { return Err(io::Error::new( ErrorKind::InvalidData, "source and destination type unmatch", )); } }; self.tun_tx.send(packet).await.expect("tun_tx::send"); Ok(()) } } ================================================ FILE: crates/shadowsocks-service/src/local/tun/virt_device.rs ================================================ //! Virtual Device for receiving packets from tun use std::{ marker::PhantomData, mem, ops::{Deref, DerefMut}, sync::{ Arc, LazyLock, Mutex, atomic::{AtomicBool, Ordering}, }, }; use bytes::BytesMut; use smoltcp::{ phy::{self, Device, DeviceCapabilities}, time::Instant, }; use tokio::sync::mpsc; pub struct VirtTunDevice { capabilities: DeviceCapabilities, in_buf: mpsc::UnboundedReceiver, out_buf: mpsc::UnboundedSender, in_buf_avail: Arc, } impl VirtTunDevice { #[allow(clippy::type_complexity)] pub fn new( capabilities: DeviceCapabilities, ) -> ( Self, mpsc::UnboundedReceiver, mpsc::UnboundedSender, Arc, ) { let (iface_tx, iface_output) = mpsc::unbounded_channel(); let (iface_input, iface_rx) = mpsc::unbounded_channel(); let in_buf_avail = Arc::new(AtomicBool::new(false)); ( Self { capabilities, in_buf: iface_rx, out_buf: iface_tx, in_buf_avail: in_buf_avail.clone(), }, iface_output, iface_input, in_buf_avail, ) } #[inline] pub fn recv_available(&self) -> bool { self.in_buf_avail.load(Ordering::Acquire) } } impl Device for VirtTunDevice { type RxToken<'a> = VirtRxToken<'a>; type TxToken<'a> = VirtTxToken<'a>; fn receive(&mut self, _timestamp: Instant) -> Option<(Self::RxToken<'_>, Self::TxToken<'_>)> { if let Ok(buffer) = self.in_buf.try_recv() { let rx = Self::RxToken { buffer, phantom_device: PhantomData, }; let tx = VirtTxToken(self); return Some((rx, tx)); } self.in_buf_avail.store(false, Ordering::Release); None } fn transmit(&mut self, _timestamp: Instant) -> Option> { Some(VirtTxToken(self)) } fn capabilities(&self) -> DeviceCapabilities { self.capabilities.clone() } } pub struct VirtRxToken<'a> { buffer: TokenBuffer, phantom_device: PhantomData<&'a VirtTunDevice>, } impl phy::RxToken for VirtRxToken<'_> { fn consume(self, f: F) -> R where F: FnOnce(&[u8]) -> R, { f(&self.buffer) } } pub struct VirtTxToken<'a>(&'a mut VirtTunDevice); impl phy::TxToken for VirtTxToken<'_> { fn consume(self, len: usize, f: F) -> R where F: FnOnce(&mut [u8]) -> R, { let mut buffer = TokenBuffer::with_capacity(len); unsafe { buffer.set_len(len); } let result = f(&mut buffer); self.0.out_buf.send(buffer).expect("channel closed unexpectedly"); result } } // Maximum number of TokenBuffer cached globally. // // Each of them has capacity 65536 (defined in tun/mod.rs), so 64 * 65536 = 4MB. const TOKEN_BUFFER_LIST_MAX_SIZE: usize = 64; static TOKEN_BUFFER_LIST: LazyLock>> = LazyLock::new(|| Mutex::new(Vec::new())); pub struct TokenBuffer { buffer: BytesMut, } impl Drop for TokenBuffer { fn drop(&mut self) { let mut list = TOKEN_BUFFER_LIST.lock().unwrap(); if list.len() >= TOKEN_BUFFER_LIST_MAX_SIZE { return; } let empty_buffer = BytesMut::new(); let mut buffer = mem::replace(&mut self.buffer, empty_buffer); buffer.clear(); list.push(buffer); } } impl TokenBuffer { pub fn with_capacity(cap: usize) -> Self { let mut list = TOKEN_BUFFER_LIST.lock().unwrap(); if let Some(mut buffer) = list.pop() { buffer.reserve(cap); return Self { buffer }; } Self { buffer: BytesMut::with_capacity(cap), } } } impl Deref for TokenBuffer { type Target = BytesMut; fn deref(&self) -> &Self::Target { &self.buffer } } impl DerefMut for TokenBuffer { fn deref_mut(&mut self) -> &mut Self::Target { &mut self.buffer } } ================================================ FILE: crates/shadowsocks-service/src/local/tunnel/mod.rs ================================================ //! Shadowsocks Local Tunnel Server pub use self::server::{Tunnel, TunnelBuilder}; pub mod server; mod tcprelay; mod udprelay; ================================================ FILE: crates/shadowsocks-service/src/local/tunnel/server.rs ================================================ //! Shadowsocks Local Tunnel Server use std::{io, sync::Arc, time::Duration}; use futures::{FutureExt, future}; use shadowsocks::{ServerAddr, config::Mode, relay::socks5::Address}; use crate::local::{context::ServiceContext, loadbalancing::PingBalancer}; use super::{ tcprelay::{TunnelTcpServer, TunnelTcpServerBuilder}, udprelay::{TunnelUdpServer, TunnelUdpServerBuilder}, }; pub struct TunnelBuilder { context: Arc, forward_addr: Address, mode: Mode, udp_expiry_duration: Option, udp_capacity: Option, client_addr: ServerAddr, udp_addr: Option, balancer: PingBalancer, #[cfg(target_os = "macos")] launchd_tcp_socket_name: Option, #[cfg(target_os = "macos")] launchd_udp_socket_name: Option, } impl TunnelBuilder { /// Create a new Tunnel server forwarding to `forward_addr` pub fn new(forward_addr: Address, client_addr: ServerAddr, balancer: PingBalancer) -> Self { let context = ServiceContext::new(); Self::with_context(Arc::new(context), forward_addr, client_addr, balancer) } /// Create a new Tunnel server with context pub fn with_context( context: Arc, forward_addr: Address, client_addr: ServerAddr, balancer: PingBalancer, ) -> Self { Self { context, forward_addr, mode: Mode::TcpOnly, udp_expiry_duration: None, udp_capacity: None, client_addr, udp_addr: None, balancer, #[cfg(target_os = "macos")] launchd_tcp_socket_name: None, #[cfg(target_os = "macos")] launchd_udp_socket_name: None, } } /// Set UDP association's expiry duration pub fn set_udp_expiry_duration(&mut self, d: Duration) { self.udp_expiry_duration = Some(d); } /// Set total UDP association to be kept simultaneously in server pub fn set_udp_capacity(&mut self, c: usize) { self.udp_capacity = Some(c); } /// Set server mode pub fn set_mode(&mut self, mode: Mode) { self.mode = mode; } /// Set UDP bind address pub fn set_udp_bind_addr(&mut self, addr: ServerAddr) { self.udp_addr = Some(addr); } /// macOS launchd activate socket #[cfg(target_os = "macos")] pub fn set_launchd_tcp_socket_name(&mut self, n: String) { self.launchd_tcp_socket_name = Some(n); } /// macOS launchd activate socket #[cfg(target_os = "macos")] pub fn set_launchd_udp_socket_name(&mut self, n: String) { self.launchd_udp_socket_name = Some(n); } pub async fn build(self) -> io::Result { let mut tcp_server = None; if self.mode.enable_tcp() { #[allow(unused_mut)] let mut builder = TunnelTcpServerBuilder::new( self.context.clone(), self.client_addr.clone(), self.balancer.clone(), self.forward_addr.clone(), ); #[cfg(target_os = "macos")] if let Some(s) = self.launchd_tcp_socket_name { builder.set_launchd_socket_name(s); } let server = builder.build().await?; tcp_server = Some(server); } let mut udp_server = None; if self.mode.enable_udp() { let udp_addr = self.udp_addr.unwrap_or(self.client_addr); #[allow(unused_mut)] let mut builder = TunnelUdpServerBuilder::new( self.context.clone(), udp_addr, self.udp_expiry_duration, self.udp_capacity, self.balancer, self.forward_addr, ); #[cfg(target_os = "macos")] if let Some(s) = self.launchd_udp_socket_name { builder.set_launchd_socket_name(s); } let server = builder.build().await?; udp_server = Some(server); } Ok(Tunnel { tcp_server, udp_server }) } } /// Tunnel Server pub struct Tunnel { tcp_server: Option, udp_server: Option, } impl Tunnel { /// TCP server instance pub fn tcp_server(&self) -> Option<&TunnelTcpServer> { self.tcp_server.as_ref() } /// UDP server instance pub fn udp_server(&self) -> Option<&TunnelUdpServer> { self.udp_server.as_ref() } /// Start serving pub async fn run(self) -> io::Result<()> { let mut vfut = Vec::new(); if let Some(tcp_server) = self.tcp_server { vfut.push(tcp_server.run().boxed()); } if let Some(udp_server) = self.udp_server { vfut.push(udp_server.run().boxed()); } let (res, ..) = future::select_all(vfut).await; res } } ================================================ FILE: crates/shadowsocks-service/src/local/tunnel/tcprelay.rs ================================================ //! TCP Tunnel Server use std::{io, net::SocketAddr, sync::Arc, time::Duration}; use log::{error, info, trace}; use shadowsocks::{ServerAddr, net::TcpListener as ShadowTcpListener, relay::socks5::Address}; use tokio::{net::TcpStream, time}; use crate::local::{ context::ServiceContext, loadbalancing::PingBalancer, net::{AutoProxyClientStream, tcp::listener::create_standard_tcp_listener}, utils::{establish_tcp_tunnel, establish_tcp_tunnel_bypassed}, }; pub struct TunnelTcpServerBuilder { context: Arc, client_config: ServerAddr, balancer: PingBalancer, forward_addr: Address, #[cfg(target_os = "macos")] launchd_socket_name: Option, } impl TunnelTcpServerBuilder { pub(crate) fn new( context: Arc, client_config: ServerAddr, balancer: PingBalancer, forward_addr: Address, ) -> Self { Self { context, client_config, balancer, forward_addr, #[cfg(target_os = "macos")] launchd_socket_name: None, } } /// macOS launchd activate socket #[cfg(target_os = "macos")] pub fn set_launchd_socket_name(&mut self, n: String) { self.launchd_socket_name = Some(n); } pub async fn build(self) -> io::Result { cfg_if::cfg_if! { if #[cfg(target_os = "macos")] { let listener = match self.launchd_socket_name { Some(launchd_socket_name) => { use tokio::net::TcpListener as TokioTcpListener; use crate::net::launch_activate_socket::get_launch_activate_tcp_listener; let std_listener = get_launch_activate_tcp_listener(&launchd_socket_name, true)?; let tokio_listener = TokioTcpListener::from_std(std_listener)?; ShadowTcpListener::from_listener(tokio_listener, self.context.accept_opts())? } _ => { create_standard_tcp_listener(&self.context, &self.client_config).await? } }; } else { let listener = create_standard_tcp_listener(&self.context, &self.client_config).await?; } } Ok(TunnelTcpServer { context: self.context, listener, balancer: self.balancer, forward_addr: self.forward_addr, }) } } /// TCP Tunnel instance pub struct TunnelTcpServer { context: Arc, listener: ShadowTcpListener, balancer: PingBalancer, forward_addr: Address, } impl TunnelTcpServer { /// Server's local address pub fn local_addr(&self) -> io::Result { self.listener.local_addr() } /// Start serving pub async fn run(self) -> io::Result<()> { info!("shadowsocks TCP tunnel listening on {}", self.listener.local_addr()?); let forward_addr = Arc::new(self.forward_addr); loop { let (stream, peer_addr) = match self.listener.accept().await { Ok(s) => s, Err(err) => { error!("accept failed with error: {}", err); time::sleep(Duration::from_secs(1)).await; continue; } }; tokio::spawn(handle_tcp_client( self.context.clone(), stream, self.balancer.clone(), peer_addr, forward_addr.clone(), )); } } } async fn handle_tcp_client( context: Arc, mut stream: TcpStream, balancer: PingBalancer, peer_addr: SocketAddr, forward_addr: Arc
, ) -> io::Result<()> { let forward_addr: &Address = &forward_addr; if balancer.is_empty() { trace!("establishing tcp tunnel {} <-> {} direct", peer_addr, forward_addr); let mut remote = AutoProxyClientStream::connect_bypassed(context, forward_addr).await?; return establish_tcp_tunnel_bypassed(&mut stream, &mut remote, peer_addr, forward_addr).await; } let server = balancer.best_tcp_server(); let svr_cfg = server.server_config(); trace!( "establishing tcp tunnel {} <-> {} through server {} (outbound: {})", peer_addr, forward_addr, svr_cfg.tcp_external_addr(), svr_cfg.addr(), ); let mut remote = AutoProxyClientStream::connect_proxied_with_opts(context, &server, forward_addr, server.connect_opts_ref()) .await?; establish_tcp_tunnel(svr_cfg, &mut stream, &mut remote, peer_addr, forward_addr).await } ================================================ FILE: crates/shadowsocks-service/src/local/tunnel/udprelay.rs ================================================ //! UDP Tunnel server use std::{io, net::SocketAddr, sync::Arc, time::Duration}; use log::{debug, error, info}; use shadowsocks::{ ServerAddr, relay::{socks5::Address, udprelay::MAXIMUM_UDP_PAYLOAD_SIZE}, }; use tokio::{net::UdpSocket, time}; use crate::local::{ context::ServiceContext, loadbalancing::PingBalancer, net::{UdpAssociationManager, UdpInboundWrite, udp::listener::create_standard_udp_listener}, }; pub struct TunnelUdpServerBuilder { context: Arc, client_config: ServerAddr, time_to_live: Option, capacity: Option, balancer: PingBalancer, forward_addr: Address, #[cfg(target_os = "macos")] launchd_socket_name: Option, } impl TunnelUdpServerBuilder { pub(crate) fn new( context: Arc, client_config: ServerAddr, time_to_live: Option, capacity: Option, balancer: PingBalancer, forward_addr: Address, ) -> Self { Self { context, client_config, time_to_live, capacity, balancer, forward_addr, #[cfg(target_os = "macos")] launchd_socket_name: None, } } /// macOS launchd activate socket #[cfg(target_os = "macos")] pub fn set_launchd_socket_name(&mut self, n: String) { self.launchd_socket_name = Some(n); } pub async fn build(self) -> io::Result { cfg_if::cfg_if! { if #[cfg(target_os = "macos")] { let socket = match self.launchd_socket_name { Some(launchd_socket_name) => { use tokio::net::UdpSocket as TokioUdpSocket; use crate::net::launch_activate_socket::get_launch_activate_udp_socket; let std_socket = get_launch_activate_udp_socket(&launchd_socket_name, true)?; TokioUdpSocket::from_std(std_socket)? } _ => { create_standard_udp_listener(&self.context, &self.client_config).await?.into() } }; } else { let socket = create_standard_udp_listener(&self.context, &self.client_config).await?.into(); } } Ok(TunnelUdpServer { context: self.context, time_to_live: self.time_to_live, capacity: self.capacity, listener: Arc::new(socket), balancer: self.balancer, forward_addr: self.forward_addr, }) } } #[derive(Clone)] struct TunnelUdpInboundWriter { inbound: Arc, } impl UdpInboundWrite for TunnelUdpInboundWriter { async fn send_to(&self, peer_addr: SocketAddr, _remote_addr: &Address, data: &[u8]) -> io::Result<()> { self.inbound.send_to(data, peer_addr).await.map(|_| ()) } } pub struct TunnelUdpServer { context: Arc, time_to_live: Option, capacity: Option, listener: Arc, balancer: PingBalancer, forward_addr: Address, } impl TunnelUdpServer { /// Get server's local address pub fn local_addr(&self) -> io::Result { self.listener.local_addr() } /// Start serving pub async fn run(self) -> io::Result<()> { info!("shadowsocks UDP tunnel listening on {}", self.listener.local_addr()?); let (mut manager, cleanup_interval, mut keepalive_rx) = UdpAssociationManager::new( self.context.clone(), TunnelUdpInboundWriter { inbound: self.listener.clone(), }, self.time_to_live, self.capacity, self.balancer, ); let mut buffer = [0u8; MAXIMUM_UDP_PAYLOAD_SIZE]; let mut cleanup_timer = time::interval(cleanup_interval); loop { tokio::select! { _ = cleanup_timer.tick() => { // cleanup expired associations. iter() will remove expired elements manager.cleanup_expired().await; } peer_addr_opt = keepalive_rx.recv() => { let peer_addr = peer_addr_opt.expect("keep-alive channel closed unexpectedly"); manager.keep_alive(&peer_addr).await; } recv_result = self.listener.recv_from(&mut buffer) => { let (n, peer_addr) = match recv_result { Ok(s) => s, Err(err) => { error!("udp server recv_from failed with error: {}", err); time::sleep(Duration::from_secs(1)).await; continue; } }; if n == 0 { // For windows, it will generate a ICMP Port Unreachable Message // https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-recvfrom // Which will result in recv_from return 0. // // It cannot be solved here, because `WSAGetLastError` is already set. // // See `relay::udprelay::utils::create_socket` for more detail. continue; } let data = &buffer[..n]; if let Err(err) = manager.send_to(peer_addr, self.forward_addr.clone(), data) .await { debug!( "udp packet relay {} -> {} with {} bytes failed, error: {}", peer_addr, self.forward_addr, data.len(), err ); } } } } } } ================================================ FILE: crates/shadowsocks-service/src/local/utils.rs ================================================ //! Shadowsocks Local Utilities use std::{io, net::SocketAddr, time::Duration}; use log::{debug, trace}; use shadowsocks::{ config::ServerConfig, relay::{socks5::Address, tcprelay::utils::copy_encrypted_bidirectional}, }; use tokio::{ io::{AsyncRead, AsyncReadExt, AsyncWrite, AsyncWriteExt, copy_bidirectional}, time, }; use crate::local::net::AutoProxyIo; pub(crate) async fn establish_tcp_tunnel( svr_cfg: &ServerConfig, plain: &mut P, shadow: &mut S, peer_addr: SocketAddr, target_addr: &Address, ) -> io::Result<()> where P: AsyncRead + AsyncWrite + Unpin, S: AsyncRead + AsyncWrite + AutoProxyIo + Unpin, { if shadow.is_proxied() { debug!( "established tcp tunnel {} <-> {} through server {} (outbound: {})", peer_addr, target_addr, svr_cfg.tcp_external_addr(), svr_cfg.addr(), ); } else { return establish_tcp_tunnel_bypassed(plain, shadow, peer_addr, target_addr).await; } // https://github.com/shadowsocks/shadowsocks-rust/issues/232 // // Protocols like FTP, clients will wait for servers to send Welcome Message without sending anything. // // Wait at most 500ms, and then sends handshake packet to remote servers. { let mut buffer = [0u8; 8192]; match time::timeout(Duration::from_millis(500), plain.read(&mut buffer)).await { Ok(Ok(0)) => { // EOF. Just terminate right here. return Ok(()); } Ok(Ok(n)) => { // Send the first packet. shadow.write_all(&buffer[..n]).await?; } Ok(Err(err)) => return Err(err), Err(..) => { // Timeout. Send handshake to server. let _ = shadow.write(&[]).await?; trace!( "tcp tunnel {} -> {} (proxied) sent handshake without data", peer_addr, target_addr ); } } } match copy_encrypted_bidirectional(svr_cfg.method(), shadow, plain).await { Ok((wn, rn)) => { trace!( "tcp tunnel {} <-> {} (proxied) closed, L2R {} bytes, R2L {} bytes", peer_addr, target_addr, rn, wn ); } Err(err) => { trace!( "tcp tunnel {} <-> {} (proxied) closed with error: {}", peer_addr, target_addr, err ); } } Ok(()) } pub(crate) async fn establish_tcp_tunnel_bypassed( plain: &mut P, shadow: &mut S, peer_addr: SocketAddr, target_addr: &Address, ) -> io::Result<()> where P: AsyncRead + AsyncWrite + Unpin, S: AsyncRead + AsyncWrite + Unpin, { debug!("established tcp tunnel {} <-> {} bypassed", peer_addr, target_addr); match copy_bidirectional(plain, shadow).await { Ok((rn, wn)) => { trace!( "tcp tunnel {} <-> {} (bypassed) closed, L2R {} bytes, R2L {} bytes", peer_addr, target_addr, rn, wn ); } Err(err) => { trace!( "tcp tunnel {} <-> {} (bypassed) closed with error: {}", peer_addr, target_addr, err ); } } Ok(()) } ================================================ FILE: crates/shadowsocks-service/src/manager/mod.rs ================================================ //! Shadowsocks manager service //! //! Service for managing multiple relay servers. [Manage Multiple Users](https://github.com/shadowsocks/shadowsocks/wiki/Manage-Multiple-Users) use std::{io, net::SocketAddr, sync::Arc}; use log::trace; use shadowsocks::net::{AcceptOpts, ConnectOpts}; use crate::{ config::{Config, ConfigType}, dns::build_dns_resolver, server::SERVER_DEFAULT_KEEPALIVE_TIMEOUT, }; pub use self::server::{Manager, ManagerBuilder}; pub mod server; /// Starts a manager server pub async fn run(config: Config) -> io::Result<()> { assert_eq!(config.config_type, ConfigType::Manager); trace!("{:?}", config); #[cfg(all(unix, not(target_os = "android")))] if let Some(nofile) = config.nofile { use crate::sys::set_nofile; if let Err(err) = set_nofile(nofile) { log::warn!("set_nofile {} failed, error: {}", nofile, err); } } let mut manager_builder = ManagerBuilder::new(config.manager.expect("missing manager config")); let mut connect_opts = ConnectOpts { #[cfg(any(target_os = "linux", target_os = "android"))] fwmark: config.outbound_fwmark, #[cfg(target_os = "freebsd")] user_cookie: config.outbound_user_cookie, #[cfg(target_os = "android")] vpn_protect_path: config.outbound_vpn_protect_path, bind_local_addr: config.outbound_bind_addr.map(|ip| SocketAddr::new(ip, 0)), bind_interface: config.outbound_bind_interface, ..Default::default() }; connect_opts.tcp.send_buffer_size = config.outbound_send_buffer_size; connect_opts.tcp.recv_buffer_size = config.outbound_recv_buffer_size; connect_opts.tcp.nodelay = config.no_delay; connect_opts.tcp.fastopen = config.fast_open; connect_opts.tcp.keepalive = config.keep_alive.or(Some(SERVER_DEFAULT_KEEPALIVE_TIMEOUT)); connect_opts.tcp.mptcp = config.mptcp; connect_opts.udp.mtu = config.udp_mtu; connect_opts.udp.allow_fragmentation = config.outbound_udp_allow_fragmentation; let mut accept_opts = AcceptOpts { ipv6_only: config.ipv6_only, ..Default::default() }; accept_opts.tcp.send_buffer_size = config.inbound_send_buffer_size; accept_opts.tcp.recv_buffer_size = config.inbound_recv_buffer_size; accept_opts.tcp.nodelay = config.no_delay; accept_opts.tcp.fastopen = config.fast_open; accept_opts.tcp.keepalive = config.keep_alive.or(Some(SERVER_DEFAULT_KEEPALIVE_TIMEOUT)); accept_opts.tcp.mptcp = config.mptcp; accept_opts.udp.mtu = config.udp_mtu; if let Some(resolver) = build_dns_resolver(config.dns, config.ipv6_first, config.dns_cache_size, &connect_opts).await { manager_builder.set_dns_resolver(Arc::new(resolver)); } manager_builder.set_ipv6_first(config.ipv6_first); manager_builder.set_connect_opts(connect_opts); manager_builder.set_accept_opts(accept_opts); if let Some(c) = config.udp_max_associations { manager_builder.set_udp_capacity(c); } if let Some(d) = config.udp_timeout { manager_builder.set_udp_expiry_duration(d); } if let Some(acl) = config.acl { manager_builder.set_acl(Arc::new(acl)); } let manager = manager_builder.build().await?; for svr_inst in config.server { manager.add_server(svr_inst.config).await; } manager.run().await } ================================================ FILE: crates/shadowsocks-service/src/manager/server.rs ================================================ //! Shadowsocks Manager server #[cfg(unix)] use std::path::PathBuf; use std::{collections::HashMap, io, net::SocketAddr, sync::Arc, time::Duration}; use cfg_if::cfg_if; use log::{error, info, trace}; use shadowsocks::{ ManagerListener, ServerAddr, config::{Mode, ServerConfig, ServerType, ServerUser, ServerUserManager}, context::{Context, SharedContext}, crypto::CipherKind, dns_resolver::DnsResolver, manager::{ datagram::ManagerSocketAddr, protocol::{ self, AddRequest, AddResponse, ErrorResponse, ListResponse, ManagerRequest, PingResponse, RemoveRequest, RemoveResponse, ServerUserConfig, StatRequest, }, }, net::{AcceptOpts, ConnectOpts}, plugin::PluginConfig, }; use tokio::{sync::Mutex, task::JoinHandle}; use crate::{ acl::AccessControl, config::{ManagerConfig, ManagerServerHost, ManagerServerMode, SecurityConfig}, net::FlowStat, server::ServerBuilder, }; enum ServerInstanceMode { Builtin { flow_stat: Arc, abortable: JoinHandle>, }, #[cfg(unix)] Standalone { flow_stat: u64 }, } struct ServerInstance { mode: ServerInstanceMode, svr_cfg: ServerConfig, } impl Drop for ServerInstance { fn drop(&mut self) { #[allow(irrefutable_let_patterns)] if let ServerInstanceMode::Builtin { ref abortable, .. } = self.mode { abortable.abort(); } } } impl ServerInstance { fn flow_stat(&self) -> u64 { match self.mode { ServerInstanceMode::Builtin { ref flow_stat, .. } => flow_stat.tx() + flow_stat.rx(), #[cfg(unix)] ServerInstanceMode::Standalone { flow_stat } => flow_stat, } } } /// Manager server builder pub struct ManagerBuilder { context: SharedContext, svr_cfg: ManagerConfig, connect_opts: ConnectOpts, accept_opts: AcceptOpts, udp_expiry_duration: Option, udp_capacity: Option, acl: Option>, ipv6_first: bool, security: SecurityConfig, } impl ManagerBuilder { /// Create a new manager server builder from configuration pub fn new(svr_cfg: ManagerConfig) -> Self { Self::with_context(svr_cfg, Context::new_shared(ServerType::Server)) } /// Create a new manager server builder with context and configuration pub(crate) fn with_context(svr_cfg: ManagerConfig, context: SharedContext) -> Self { Self { context, svr_cfg, connect_opts: ConnectOpts::default(), accept_opts: AcceptOpts::default(), udp_expiry_duration: None, udp_capacity: None, acl: None, ipv6_first: false, security: SecurityConfig::default(), } } /// Set `ConnectOpts` pub fn set_connect_opts(&mut self, opts: ConnectOpts) { self.connect_opts = opts; } /// Set `AcceptOpts` pub fn set_accept_opts(&mut self, opts: AcceptOpts) { self.accept_opts = opts; } /// Set UDP association's expiry duration pub fn set_udp_expiry_duration(&mut self, d: Duration) { self.udp_expiry_duration = Some(d); } /// Set total UDP associations to be kept in one server pub fn set_udp_capacity(&mut self, c: usize) { self.udp_capacity = Some(c); } /// Get the manager's configuration pub fn config(&self) -> &ManagerConfig { &self.svr_cfg } /// Get customized DNS resolver pub fn set_dns_resolver(&mut self, resolver: Arc) { let context = Arc::get_mut(&mut self.context).expect("cannot set DNS resolver on a shared context"); context.set_dns_resolver(resolver) } /// Set access control list pub fn set_acl(&mut self, acl: Arc) { self.acl = Some(acl); } /// Try to connect IPv6 addresses first if hostname could be resolved to both IPv4 and IPv6 pub fn set_ipv6_first(&mut self, ipv6_first: bool) { self.ipv6_first = ipv6_first; } /// Set security config pub fn set_security_config(&mut self, security: SecurityConfig) { self.security = security; } /// Build the manager server instance pub async fn build(self) -> io::Result { let listener = ManagerListener::bind(&self.context, &self.svr_cfg.addr).await?; Ok(Manager { context: self.context, servers: Mutex::new(HashMap::new()), svr_cfg: self.svr_cfg, connect_opts: self.connect_opts, accept_opts: self.accept_opts, udp_expiry_duration: self.udp_expiry_duration, udp_capacity: self.udp_capacity, acl: self.acl, ipv6_first: self.ipv6_first, security: self.security, listener, }) } } /// Manager server pub struct Manager { context: SharedContext, servers: Mutex>, svr_cfg: ManagerConfig, connect_opts: ConnectOpts, accept_opts: AcceptOpts, udp_expiry_duration: Option, udp_capacity: Option, acl: Option>, ipv6_first: bool, security: SecurityConfig, listener: ManagerListener, } impl Manager { /// Manager server's configuration pub fn manager_config(&self) -> &ManagerConfig { &self.svr_cfg } /// Manager server's listen address pub fn local_addr(&self) -> io::Result { self.listener.local_addr() } /// Start serving pub async fn run(mut self) -> io::Result<()> { let local_addr = self.listener.local_addr()?; info!("shadowsocks manager server listening on {}", local_addr); loop { let (req, peer_addr) = match self.listener.recv_from().await { Ok(r) => r, Err(err) => { error!("manager recv_from error: {}", err); continue; } }; trace!("received {:?} from {:?}", req, peer_addr); match req { ManagerRequest::Add(ref req) => match self.handle_add(req).await { Ok(rsp) => { let _ = self.listener.send_to(&rsp, &peer_addr).await; } Err(err) => { error!("add server_port: {} failed, error: {}", req.server_port, err); let rsp = ErrorResponse(err); let _ = self.listener.send_to(&rsp, &peer_addr).await; } }, ManagerRequest::Remove(ref req) => { let rsp = self.handle_remove(req).await; let _ = self.listener.send_to(&rsp, &peer_addr).await; } ManagerRequest::List(..) => { let rsp = self.handle_list().await; let _ = self.listener.send_to(&rsp, &peer_addr).await; } ManagerRequest::Ping(..) => { let rsp = self.handle_ping().await; let _ = self.listener.send_to(&rsp, &peer_addr).await; } ManagerRequest::Stat(ref stat) => self.handle_stat(stat).await, } } } /// Add a server programmatically pub async fn add_server(&self, svr_cfg: ServerConfig) { match self.svr_cfg.server_mode { ManagerServerMode::Builtin => self.add_server_builtin(svr_cfg).await, #[cfg(unix)] ManagerServerMode::Standalone => self.add_server_standalone(svr_cfg).await, } } async fn add_server_builtin(&self, svr_cfg: ServerConfig) { // Each server should use a separate Context, but shares // // * AccessControlList // * DNS Resolver let mut server_builder = ServerBuilder::new(svr_cfg.clone()); server_builder.set_connect_opts(self.connect_opts.clone()); server_builder.set_accept_opts(self.accept_opts.clone()); server_builder.set_dns_resolver(self.context.dns_resolver().clone()); if let Some(d) = self.udp_expiry_duration { server_builder.set_udp_expiry_duration(d); } if let Some(c) = self.udp_capacity { server_builder.set_udp_capacity(c); } if let Some(ref acl) = self.acl { server_builder.set_acl(acl.clone()); } if self.ipv6_first { server_builder.set_ipv6_first(self.ipv6_first); } server_builder.set_security_config(&self.security); let server_port = server_builder.server_config().addr().port(); let mut servers = self.servers.lock().await; // Close existed server if let Some(v) = servers.remove(&server_port) { info!( "closed managed server listening on {}, inbound address {}", v.svr_cfg.addr(), v.svr_cfg.tcp_external_addr() ); } let flow_stat = server_builder.flow_stat(); let server = match server_builder.build().await { Ok(s) => s, Err(err) => { error!("failed to start server ({}), error: {}", svr_cfg.addr(), err); return; } }; let abortable = tokio::spawn(async move { server.run().await }); servers.insert( server_port, ServerInstance { mode: ServerInstanceMode::Builtin { flow_stat, abortable }, svr_cfg, }, ); } #[cfg(unix)] fn server_pid_path(&self, port: u16) -> PathBuf { let pid_file_name = format!("shadowsocks-server-{port}.pid"); let mut pid_path = self.svr_cfg.server_working_directory.clone(); pid_path.push(&pid_file_name); pid_path } #[cfg(unix)] fn server_config_path(&self, port: u16) -> PathBuf { let config_file_name = format!("shadowsocks-server-{port}.json"); let mut config_file_path = self.svr_cfg.server_working_directory.clone(); config_file_path.push(&config_file_name); config_file_path } #[cfg(unix)] fn kill_standalone_server(&self, port: u16) { use log::{debug, warn}; use std::{ fs::{self, File}, io::Read, }; let pid_path = self.server_pid_path(port); if pid_path.exists() && let Ok(mut pid_file) = File::open(&pid_path) { let mut pid_content = String::new(); if pid_file.read_to_string(&mut pid_content).is_ok() { let pid_content = pid_content.trim(); match pid_content.parse::() { Ok(pid) => { let _ = unsafe { libc::kill(pid, libc::SIGTERM) }; debug!("killed standalone server port {}, pid: {}", port, pid); } Err(..) => { warn!("failed to read pid from {}", pid_path.display()); } } } } let server_config_path = self.server_config_path(port); let _ = fs::remove_file(pid_path); let _ = fs::remove_file(server_config_path); } #[cfg(unix)] async fn add_server_standalone(&self, svr_cfg: ServerConfig) { use std::{ fs::{self, OpenOptions}, io::Write, }; use tokio::process::Command; use crate::config::{Config, ConfigType, ServerInstanceConfig}; // Lock the map first incase there are multiple requests to create one server instance let mut servers = self.servers.lock().await; // Check if working_directory exists if !self.svr_cfg.server_working_directory.exists() { fs::create_dir_all(&self.svr_cfg.server_working_directory).expect("create working_directory"); } let port = svr_cfg.addr().port(); // Check if there is already a running process self.kill_standalone_server(port); // Create configuration file for server let config_file_path = self.server_config_path(port); let pid_path = self.server_pid_path(port); let server_instance = ServerInstanceConfig { config: svr_cfg.clone(), acl: None, // Set with --acl command line argument #[cfg(any(target_os = "linux", target_os = "android"))] outbound_fwmark: None, #[cfg(target_os = "freebsd")] outbound_user_cookie: None, outbound_bind_addr: None, outbound_bind_interface: None, outbound_udp_allow_fragmentation: None, }; let mut config = Config::new(ConfigType::Server); config.server.push(server_instance); trace!("created standalone server with config {:?}", config); let config_file_content = format!("{config}"); match OpenOptions::new() .write(true) .create(true) .truncate(true) .open(&config_file_path) { Err(err) => { error!( "failed to open {} for writing, error: {}", config_file_path.display(), err ); return; } Ok(mut file) => { if let Err(err) = file.write_all(config_file_content.as_bytes()) { error!("failed to write {}, error: {}", config_file_path.display(), err); return; } let _ = file.sync_data(); } } let manager_addr = self.svr_cfg.addr.to_string(); // Start server process let mut child_command = Command::new(&self.svr_cfg.server_program); child_command .arg("-c") .arg(&config_file_path) .arg("--daemonize") .arg("--daemonize-pid") .arg(&pid_path) .arg("--manager-addr") .arg(&manager_addr); if let Some(ref acl) = self.acl { child_command.arg("--acl").arg(acl.file_path().to_str().expect("acl")); } let child_result = child_command.kill_on_drop(false).spawn(); if let Err(err) = child_result { error!( "failed to spawn process of {}, error: {}", self.svr_cfg.server_program, err ); return; } // Greate. Record into the map servers.insert( port, ServerInstance { mode: ServerInstanceMode::Standalone { flow_stat: 0 }, svr_cfg, }, ); } async fn handle_add(&self, req: &AddRequest) -> io::Result { let addr = match self.svr_cfg.server_host { ManagerServerHost::Domain(ref dname) => ServerAddr::DomainName(dname.clone(), req.server_port), ManagerServerHost::Ip(ip) => ServerAddr::SocketAddr(SocketAddr::new(ip, req.server_port)), }; let method = match req.method { Some(ref m) => match m.parse::() { Ok(method) => method, Err(..) => { error!("unrecognized method \"{}\", req: {:?}", m, req); let err = format!("unrecognized method \"{m}\""); return Ok(AddResponse(err)); } }, None => match self.svr_cfg.method { Some(m) => m, None => { cfg_if! { if #[cfg(feature = "aead-cipher")] { // If AEAD cipher is enabled, use chacha20-poly1305 as default method // NOTE: This behavior is defined in shadowsocks-libev's `manager.c` CipherKind::CHACHA20_POLY1305 } else { // AEAD cipher is disabled, default method is not defined in any standard or implementations. // TODO: Complete this after discussion. return Ok(AddResponse("method is required".to_string())); } } } }, }; let mut svr_cfg = match ServerConfig::new(addr, req.password.clone(), method) { Ok(svr_cfg) => svr_cfg, Err(err) => { error!("failed to create ServerConfig, error: {}", err); return Ok(AddResponse("invalid server".to_string())); } }; if let Some(ref plugin) = req.plugin { let p = PluginConfig { plugin: plugin.clone(), plugin_opts: req.plugin_opts.clone(), plugin_args: Vec::new(), plugin_mode: match req.plugin_mode { None => Mode::TcpOnly, Some(ref mode) => match mode.parse::() { Ok(m) => m, Err(..) => { error!("unrecognized plugin_mode \"{}\", req: {:?}", mode, req); let err = format!("unrecognized plugin_mode \"{}\"", mode); return Ok(AddResponse(err)); } }, }, }; svr_cfg.set_plugin(p); } else if let Some(ref plugin) = self.svr_cfg.plugin { svr_cfg.set_plugin(plugin.clone()); } let mode = match req.mode { None => None, Some(ref mode) => match mode.parse::() { Ok(m) => Some(m), Err(..) => { error!("unrecognized mode \"{}\", req: {:?}", mode, req); let err = format!("unrecognized mode \"{mode}\""); return Ok(AddResponse(err)); } }, }; svr_cfg.set_mode(mode.unwrap_or(self.svr_cfg.mode)); if let Some(ref users) = req.users { let mut user_manager = ServerUserManager::new(); for user in users.iter() { let user = match ServerUser::with_encoded_key(&user.name, &user.password) { Ok(u) => u, Err(..) => { error!( "users[].password must be encoded with base64, but found: {}", user.password ); return Err(io::Error::other("users[].password must be encoded with base64")); } }; user_manager.add_user(user); } svr_cfg.set_user_manager(user_manager); } self.add_server(svr_cfg).await; Ok(AddResponse("ok".to_owned())) } async fn handle_remove(&self, req: &RemoveRequest) -> RemoveResponse { let mut servers = self.servers.lock().await; servers.remove(&req.server_port); #[cfg(unix)] if self.svr_cfg.server_mode == ManagerServerMode::Standalone { self.kill_standalone_server(req.server_port); } RemoveResponse("ok".to_owned()) } async fn handle_list(&self) -> ListResponse { let instances = self.servers.lock().await; let mut servers = Vec::new(); for (_, server) in instances.iter() { let svr_cfg = &server.svr_cfg; let mut users = None; if let Some(user_manager) = server.svr_cfg.user_manager() { let mut vu = Vec::with_capacity(user_manager.user_count()); for user in user_manager.users_iter() { vu.push(ServerUserConfig { name: user.name().to_owned(), password: user.encoded_key(), }); } users = Some(vu); } let sc = protocol::ServerConfig { server_port: svr_cfg.addr().port(), password: svr_cfg.password().to_owned(), method: None, no_delay: None, plugin: None, plugin_opts: None, plugin_mode: None, mode: None, users, }; servers.push(sc); } ListResponse { servers } } async fn handle_ping(&self) -> PingResponse { let instances = self.servers.lock().await; let mut stat = HashMap::new(); for (port, server) in instances.iter() { stat.insert(*port, server.flow_stat()); } PingResponse { stat } } #[cfg(not(unix))] async fn handle_stat(&self, _: &StatRequest) {} #[cfg(unix)] async fn handle_stat(&self, stat: &StatRequest) { use log::warn; use std::collections::hash_map::Entry; use crate::config::{Config, ConfigType}; // `stat` is only supported for Standalone mode if self.svr_cfg.server_mode != ManagerServerMode::Standalone { return; } let mut instances = self.servers.lock().await; // Get or create a new instance then record the data statistic numbers for (port, flow) in stat.stat.iter() { match instances.entry(*port) { Entry::Occupied(mut occ) => match occ.get_mut().mode { ServerInstanceMode::Builtin { .. } => { error!("received `stat` for port {} that is running a builtin server", *port) } ServerInstanceMode::Standalone { ref mut flow_stat } => *flow_stat = *flow, }, Entry::Vacant(vac) => { // Read config from file let server_config_path = self.server_config_path(*port); if !server_config_path.exists() { warn!( "received `stat` for port {} but file {} doesn't exist", *port, server_config_path.display() ); continue; } match Config::load_from_file(&server_config_path, ConfigType::Server) { Err(err) => { error!( "failed to load {} for server port {}, error: {}", server_config_path.display(), *port, err ); continue; } Ok(config) => { trace!( "loaded {} for server port {}, {:?}", server_config_path.display(), *port, config ); if config.server.len() != 1 { error!( "invalid config {} for server port {}, containing {} servers", server_config_path.display(), *port, config.server.len() ); continue; } let svr_cfg = config.server[0].config.clone(); vac.insert(ServerInstance { mode: ServerInstanceMode::Standalone { flow_stat: *flow }, svr_cfg, }); } } } } } } } ================================================ FILE: crates/shadowsocks-service/src/net/flow.rs ================================================ //! Server flow statistic use std::sync::atomic::Ordering; #[cfg(target_has_atomic = "64")] type FlowCounter = std::sync::atomic::AtomicU64; #[cfg(not(target_has_atomic = "64"))] type FlowCounter = std::sync::atomic::AtomicU32; /// Connection flow statistic pub struct FlowStat { tx: FlowCounter, rx: FlowCounter, } impl Default for FlowStat { fn default() -> Self { Self { tx: FlowCounter::new(0), rx: FlowCounter::new(0), } } } impl FlowStat { /// Create an empty flow statistic pub fn new() -> Self { Self::default() } /// Transmitted bytes count pub fn tx(&self) -> u64 { self.tx.load(Ordering::Relaxed) as _ } /// Increase transmitted bytes pub fn incr_tx(&self, n: u64) { self.tx.fetch_add(n as _, Ordering::AcqRel); } /// Received bytes count pub fn rx(&self) -> u64 { self.rx.load(Ordering::Relaxed) as _ } /// Increase received bytes pub fn incr_rx(&self, n: u64) { self.rx.fetch_add(n as _, Ordering::AcqRel); } } ================================================ FILE: crates/shadowsocks-service/src/net/launch_activate_socket.rs ================================================ //! macOS launch activate socket //! //! //! use std::{ io, net::{TcpListener, UdpSocket}, os::unix::io::FromRawFd, }; use log::debug; use crate::sys::get_launch_activate_socket; /// Get a macOS launch active socket as a `TcpListener` pub fn get_launch_activate_tcp_listener(name: &str, nonblock: bool) -> io::Result { let fd = get_launch_activate_socket(name)?; debug!("created TCP listener from launch activate socket {}", fd); let listener = unsafe { TcpListener::from_raw_fd(fd) }; if nonblock { listener.set_nonblocking(true)?; } Ok(listener) } /// Get a macOS launch activate socket as a `UdpSocket` pub fn get_launch_activate_udp_socket(name: &str, nonblock: bool) -> io::Result { let fd = get_launch_activate_socket(name)?; debug!("created UDP socket from launch activate socket {}", fd); let socket = unsafe { UdpSocket::from_raw_fd(fd) }; if nonblock { socket.set_nonblocking(true)?; } Ok(socket) } ================================================ FILE: crates/shadowsocks-service/src/net/mod.rs ================================================ //! Shadowsocks Service Network Utilities pub use self::{flow::FlowStat, mon_socket::MonProxySocket, mon_stream::MonProxyStream}; pub mod flow; #[cfg(target_os = "macos")] pub mod launch_activate_socket; pub mod mon_socket; pub mod mon_stream; pub mod packet_window; pub mod utils; /// Packet size for all UDP associations' send queue pub const UDP_ASSOCIATION_SEND_CHANNEL_SIZE: usize = 1024; /// Keep-alive channel size for UDP associations' manager pub const UDP_ASSOCIATION_KEEP_ALIVE_CHANNEL_SIZE: usize = 64; ================================================ FILE: crates/shadowsocks-service/src/net/mon_socket.rs ================================================ //! UDP socket with flow statistic monitored use std::{io, net::SocketAddr, sync::Arc}; use shadowsocks::{ ProxySocket, relay::{ socks5::Address, udprelay::{DatagramReceive, DatagramSend, options::UdpSocketControlData}, }, }; use super::flow::FlowStat; /// Monitored `ProxySocket` pub struct MonProxySocket { socket: ProxySocket, flow_stat: Arc, } impl MonProxySocket { /// Create a new socket with flow monitor pub fn from_socket(socket: ProxySocket, flow_stat: Arc) -> Self { Self { socket, flow_stat } } /// Get the underlying `ProxySocket` immutable reference #[inline] pub fn get_ref(&self) -> &ProxySocket { &self.socket } /// Get the flow statistic data #[inline] pub fn flow_stat(&self) -> &FlowStat { &self.flow_stat } } impl MonProxySocket where S: DatagramSend, { /// Send a UDP packet to addr through proxy #[inline] pub async fn send(&self, addr: &Address, payload: &[u8]) -> io::Result<()> { let n = self.socket.send(addr, payload).await?; self.flow_stat.incr_tx(n as u64); Ok(()) } /// Send a UDP packet to addr through proxy #[inline] pub async fn send_with_ctrl( &self, addr: &Address, control: &UdpSocketControlData, payload: &[u8], ) -> io::Result<()> { let n = self.socket.send_with_ctrl(addr, control, payload).await?; self.flow_stat.incr_tx(n as u64); Ok(()) } /// Send a UDP packet to target from proxy #[inline] pub async fn send_to(&self, target: SocketAddr, addr: &Address, payload: &[u8]) -> io::Result<()> { let n = self.socket.send_to(target, addr, payload).await?; self.flow_stat.incr_tx(n as u64); Ok(()) } /// Send a UDP packet to target from proxy #[inline] pub async fn send_to_with_ctrl( &self, target: SocketAddr, addr: &Address, control: &UdpSocketControlData, payload: &[u8], ) -> io::Result<()> { let n = self.socket.send_to_with_ctrl(target, addr, control, payload).await?; self.flow_stat.incr_tx(n as u64); Ok(()) } } impl MonProxySocket where S: DatagramReceive, { /// Receive packet from Shadowsocks' UDP server /// /// This function will use `recv_buf` to store intermediate data, so it has to be big enough to store the whole shadowsocks' packet /// /// It is recommended to allocate a buffer to have at least 65536 bytes. #[inline] pub async fn recv(&self, recv_buf: &mut [u8]) -> io::Result<(usize, Address)> { let (n, addr, recv_n) = self.socket.recv(recv_buf).await?; self.flow_stat.incr_rx(recv_n as u64); Ok((n, addr)) } /// Receive packet from Shadowsocks' UDP server /// /// This function will use `recv_buf` to store intermediate data, so it has to be big enough to store the whole shadowsocks' packet /// /// It is recommended to allocate a buffer to have at least 65536 bytes. #[inline] pub async fn recv_with_ctrl( &self, recv_buf: &mut [u8], ) -> io::Result<(usize, Address, Option)> { let (n, addr, recv_n, control) = self.socket.recv_with_ctrl(recv_buf).await?; self.flow_stat.incr_rx(recv_n as u64); Ok((n, addr, control)) } /// Receive packet from Shadowsocks' UDP server /// /// This function will use `recv_buf` to store intermediate data, so it has to be big enough to store the whole shadowsocks' packet /// /// It is recommended to allocate a buffer to have at least 65536 bytes. #[inline] pub async fn recv_from(&self, recv_buf: &mut [u8]) -> io::Result<(usize, SocketAddr, Address)> { let (n, peer_addr, addr, recv_n) = self.socket.recv_from(recv_buf).await?; self.flow_stat.incr_rx(recv_n as u64); Ok((n, peer_addr, addr)) } /// Receive packet from Shadowsocks' UDP server /// /// This function will use `recv_buf` to store intermediate data, so it has to be big enough to store the whole shadowsocks' packet /// /// It is recommended to allocate a buffer to have at least 65536 bytes. #[inline] pub async fn recv_from_with_ctrl( &self, recv_buf: &mut [u8], ) -> io::Result<(usize, SocketAddr, Address, Option)> { let (n, peer_addr, addr, recv_n, control) = self.socket.recv_from_with_ctrl(recv_buf).await?; self.flow_stat.incr_rx(recv_n as u64); Ok((n, peer_addr, addr, control)) } } ================================================ FILE: crates/shadowsocks-service/src/net/mon_stream.rs ================================================ //! TCP stream with flow statistic monitored use std::{ io::{self, IoSlice}, pin::Pin, sync::Arc, task::{Context, Poll}, }; use pin_project::pin_project; use tokio::io::{AsyncRead, AsyncWrite, ReadBuf}; use super::flow::FlowStat; /// Monitored `ProxyStream` #[pin_project] pub struct MonProxyStream { #[pin] stream: S, flow_stat: Arc, } impl MonProxyStream { #[inline] pub fn from_stream(stream: S, flow_stat: Arc) -> Self { Self { stream, flow_stat } } #[inline] pub fn get_ref(&self) -> &S { &self.stream } #[inline] pub fn get_mut(&mut self) -> &mut S { &mut self.stream } #[inline] pub fn into_inner(self) -> S { self.stream } } impl AsyncRead for MonProxyStream where S: AsyncRead + Unpin, { #[inline] fn poll_read(self: Pin<&mut Self>, cx: &mut Context<'_>, buf: &mut ReadBuf<'_>) -> Poll> { let this = self.project(); match this.stream.poll_read(cx, buf) { Poll::Pending => Poll::Pending, Poll::Ready(Ok(())) => { let n = buf.filled().len(); this.flow_stat.incr_rx(n as u64); Poll::Ready(Ok(())) } Poll::Ready(Err(err)) => Poll::Ready(Err(err)), } } } impl AsyncWrite for MonProxyStream where S: AsyncWrite + Unpin, { #[inline] fn poll_write(self: Pin<&mut Self>, cx: &mut Context<'_>, buf: &[u8]) -> Poll> { let this = self.project(); match this.stream.poll_write(cx, buf) { Poll::Pending => Poll::Pending, Poll::Ready(Ok(n)) => { this.flow_stat.incr_tx(n as u64); Poll::Ready(Ok(n)) } Poll::Ready(Err(err)) => Poll::Ready(Err(err)), } } #[inline] fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { self.project().stream.poll_flush(cx) } #[inline] fn poll_shutdown(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { self.project().stream.poll_shutdown(cx) } #[inline] fn poll_write_vectored( self: Pin<&mut Self>, cx: &mut Context<'_>, bufs: &[IoSlice<'_>], ) -> Poll> { self.project().stream.poll_write_vectored(cx, bufs) } } ================================================ FILE: crates/shadowsocks-service/src/net/packet_window.rs ================================================ // SPDX-License-Identifier: MIT // // Copyright (C) 2017-2021 WireGuard LLC. All Rights Reserved. //! Packet window //! //! https://github.com/WireGuard/wireguard-go/blob/master/replay/replay.go const BLOCK_BIT_LOG: u64 = 6; // 1<<6 == 64 bits const BLOCK_BITS: u64 = 1 << BLOCK_BIT_LOG; // must be power of 2 const RING_BLOCKS: u64 = 1 << 7; // must be power of 2 const WINDOW_SIZE: u64 = (RING_BLOCKS - 1) * BLOCK_BITS; const BLOCK_MASK: u64 = RING_BLOCKS - 1; const BIT_MASK: u64 = BLOCK_BITS - 1; /// Packet window for checking `packet_id` is in the sliding window #[derive(Debug, Clone)] pub struct PacketWindowFilter { last_packet_id: u64, packet_ring: [u64; RING_BLOCKS as usize], } impl Default for PacketWindowFilter { fn default() -> Self { Self::new() } } impl PacketWindowFilter { /// Create an empty filter pub fn new() -> Self { Self { last_packet_id: 0, packet_ring: [0u64; RING_BLOCKS as usize], } } /// Reset filter to the initial state pub fn reset(&mut self) { self.last_packet_id = 0; self.packet_ring[0] = 0; } /// Check and remember the `packet_id` /// /// Overlimit `packet_id >= limit` are always rejected pub fn validate_packet_id(&mut self, packet_id: u64, limit: u64) -> bool { if packet_id >= limit { return false; } let mut index_block = packet_id >> BLOCK_BIT_LOG; if packet_id > self.last_packet_id { // Move the window forward let current = self.last_packet_id >> BLOCK_BIT_LOG; let mut diff = index_block - current; if diff > RING_BLOCKS { // Clear the whole filter diff = RING_BLOCKS; } for d in 1..=diff { let i = current + d; self.packet_ring[(i & BLOCK_MASK) as usize] = 0; } self.last_packet_id = packet_id; } else if self.last_packet_id - packet_id > WINDOW_SIZE { // Behind the current window return false; } // Check and set bit index_block &= BLOCK_MASK; let index_bit = packet_id & BIT_MASK; let old = self.packet_ring[index_block as usize]; let new = old | (1 << index_bit); self.packet_ring[index_block as usize] = new; old != new } } #[cfg(test)] mod test { use super::*; use std::cell::RefCell; #[test] fn test_packet_window() { const REJECT_AFTER_MESSAGES: u64 = u64::MAX - (1u64 << 13); let filter = RefCell::new(PacketWindowFilter::new()); let test_number = RefCell::new(0); #[allow(non_snake_case)] let T = |n: u64, expected: bool| { *(test_number.borrow_mut()) += 1; if filter.borrow_mut().validate_packet_id(n, REJECT_AFTER_MESSAGES) != expected { panic!("Test {} failed, {} {}", test_number.borrow(), n, expected); } }; const T_LIM: u64 = WINDOW_SIZE + 1; T(0, true); // 1 T(1, true); // 2 T(1, false); // 3 T(9, true); // 4 T(8, true); // 5 T(7, true); // 6 T(7, false); // 7 T(T_LIM, true); // 8 T(T_LIM - 1, true); // 9 T(T_LIM - 1, false); // 10 T(T_LIM - 2, true); // 11 T(2, true); // 12 T(2, false); // 13 T(T_LIM + 16, true); // 14 T(3, false); // 15 T(T_LIM + 16, false); // 16 T(T_LIM * 4, true); // 17 T(T_LIM * 4 - (T_LIM - 1), true); // 18 T(10, false); // 19 T(T_LIM * 4 - T_LIM, false); // 20 T(T_LIM * 4 - (T_LIM + 1), false); // 21 T(T_LIM * 4 - (T_LIM - 2), true); // 22 T(T_LIM * 4 + 1 - T_LIM, false); // 23 T(0, false); // 24 T(REJECT_AFTER_MESSAGES, false); // 25 T(REJECT_AFTER_MESSAGES - 1, true); // 26 T(REJECT_AFTER_MESSAGES, false); // 27 T(REJECT_AFTER_MESSAGES - 1, false); // 28 T(REJECT_AFTER_MESSAGES - 2, true); // 29 T(REJECT_AFTER_MESSAGES + 1, false); // 30 T(REJECT_AFTER_MESSAGES + 2, false); // 31 T(REJECT_AFTER_MESSAGES - 2, false); // 32 T(REJECT_AFTER_MESSAGES - 3, true); // 33 T(0, false); // 34 println!("Bulk test 1"); filter.borrow_mut().reset(); *(test_number.borrow_mut()) = 0; for i in 1..=WINDOW_SIZE { T(i, true); } T(0, true); T(0, false); println!("Bulk test 2"); filter.borrow_mut().reset(); *(test_number.borrow_mut()) = 0; for i in 2..=WINDOW_SIZE + 1 { T(i, true); } T(1, true); T(0, false); println!("Bulk test 3"); filter.borrow_mut().reset(); *(test_number.borrow_mut()) = 0; for i in (1..=WINDOW_SIZE + 1).rev() { T(i, true); } println!("Bulk test 4"); filter.borrow_mut().reset(); *(test_number.borrow_mut()) = 0; for i in (2..=WINDOW_SIZE + 2).rev() { T(i, true); } T(0, false); println!("Bulk test 5"); filter.borrow_mut().reset(); *(test_number.borrow_mut()) = 0; for i in (1..=WINDOW_SIZE).rev() { T(i, true); } T(WINDOW_SIZE + 1, true); T(0, false); println!("Bulk test 6"); filter.borrow_mut().reset(); *(test_number.borrow_mut()) = 0; for i in (1..=WINDOW_SIZE).rev() { T(i, true); } T(0, true); T(WINDOW_SIZE + 1, true); } } ================================================ FILE: crates/shadowsocks-service/src/net/utils.rs ================================================ //! Network Utilities use std::{ io, net::{Ipv4Addr, Ipv6Addr}, }; use tokio::io::{AsyncRead, AsyncReadExt}; /// Consumes all data from `reader` and throws away until EOF pub async fn ignore_until_end(reader: &mut R) -> io::Result<()> where R: AsyncRead + Unpin, { let mut buffer = [0u8; 2048]; loop { let n = reader.read(&mut buffer).await?; if n == 0 { break; } } Ok(()) } /// Helper function for converting IPv4 mapped IPv6 address /// /// This is the same as `Ipv6Addr::to_ipv4_mapped`, but it is still unstable in the current libstd #[allow(unused)] pub(crate) fn to_ipv4_mapped(ipv6: &Ipv6Addr) -> Option { match ipv6.octets() { [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff, a, b, c, d] => Some(Ipv4Addr::new(a, b, c, d)), _ => None, } } ================================================ FILE: crates/shadowsocks-service/src/server/context.rs ================================================ //! Shadowsocks Local Server Context use std::{net::SocketAddr, sync::Arc}; use shadowsocks::{ config::ServerType, context::{Context, SharedContext}, dns_resolver::DnsResolver, net::ConnectOpts, relay::Address, }; use crate::{acl::AccessControl, config::SecurityConfig, net::FlowStat}; /// Server Service Context #[derive(Clone)] pub struct ServiceContext { context: SharedContext, connect_opts: ConnectOpts, // Access Control acl: Option>, // Flow statistic report flow_stat: Arc, } impl Default for ServiceContext { fn default() -> Self { Self { context: Context::new_shared(ServerType::Server), connect_opts: ConnectOpts::default(), acl: None, flow_stat: Arc::new(FlowStat::new()), } } } impl ServiceContext { /// Create a new `ServiceContext` pub fn new() -> Self { Self::default() } /// Get cloned `shadowsocks` Context pub fn context(&self) -> SharedContext { self.context.clone() } /// Get `shadowsocks` Context reference pub fn context_ref(&self) -> &Context { self.context.as_ref() } /// Set `ConnectOpts` pub fn set_connect_opts(&mut self, connect_opts: ConnectOpts) { self.connect_opts = connect_opts; } /// Get `ConnectOpts` reference pub fn connect_opts_ref(&self) -> &ConnectOpts { &self.connect_opts } /// Set Access Control List pub fn set_acl(&mut self, acl: Arc) { self.acl = Some(acl); } /// Get Access Control List reference pub fn acl(&self) -> Option<&AccessControl> { self.acl.as_deref() } /// Get cloned flow statistic pub fn flow_stat(&self) -> Arc { self.flow_stat.clone() } /// Get flow statistic reference pub fn flow_stat_ref(&self) -> &FlowStat { self.flow_stat.as_ref() } /// Set customized DNS resolver pub fn set_dns_resolver(&mut self, resolver: Arc) { let context = Arc::get_mut(&mut self.context).expect("cannot set DNS resolver on a shared context"); context.set_dns_resolver(resolver) } /// Get reference of DNS resolver pub fn dns_resolver(&self) -> &DnsResolver { self.context.dns_resolver() } /// Check if target should be bypassed pub async fn check_outbound_blocked(&self, addr: &Address) -> bool { match self.acl { None => false, Some(ref acl) => acl.check_outbound_blocked(&self.context, addr).await, } } /// Check if client should be blocked pub fn check_client_blocked(&self, addr: &SocketAddr) -> bool { match self.acl { None => false, Some(ref acl) => acl.check_client_blocked(addr), } } /// Try to connect IPv6 addresses first if hostname could be resolved to both IPv4 and IPv6 pub fn set_ipv6_first(&mut self, ipv6_first: bool) { let context = Arc::get_mut(&mut self.context).expect("cannot set ipv6_first on a shared context"); context.set_ipv6_first(ipv6_first); } /// Set security config pub fn set_security_config(&mut self, security: &SecurityConfig) { let context = Arc::get_mut(&mut self.context).expect("cannot set security on a shared context"); context.set_replay_attack_policy(security.replay_attack.policy); } } ================================================ FILE: crates/shadowsocks-service/src/server/mod.rs ================================================ //! Shadowsocks server use std::{io, net::SocketAddr, sync::Arc, time::Duration}; use futures::future; use log::trace; use shadowsocks::net::{AcceptOpts, ConnectOpts, UdpSocketOpts}; use crate::{ config::{Config, ConfigType}, dns::build_dns_resolver, utils::ServerHandle, }; pub use self::{ server::{Server, ServerBuilder}, tcprelay::TcpServer, udprelay::UdpServer, }; pub mod context; #[allow(clippy::module_inception)] pub mod server; mod tcprelay; mod udprelay; /// Default TCP Keep Alive timeout /// /// This is borrowed from Go's `net` library's default setting pub(crate) const SERVER_DEFAULT_KEEPALIVE_TIMEOUT: Duration = Duration::from_secs(15); /// Starts a shadowsocks server pub async fn run(config: Config) -> io::Result<()> { assert_eq!(config.config_type, ConfigType::Server); assert!(!config.server.is_empty()); trace!("{:?}", config); // Warning for Stream Ciphers #[cfg(feature = "stream-cipher")] for inst in config.server.iter() { let server = &inst.config; if server.method().is_stream() { log::warn!( "stream cipher {} for server {} have inherent weaknesses (see discussion in https://github.com/shadowsocks/shadowsocks-org/issues/36). \ DO NOT USE. It will be removed in the future.", server.method(), server.addr() ); } } #[cfg(all(unix, not(target_os = "android")))] if let Some(nofile) = config.nofile { use crate::sys::set_nofile; if let Err(err) = set_nofile(nofile) { log::warn!("set_nofile {} failed, error: {}", nofile, err); } } let mut servers = Vec::new(); let mut connect_opts = ConnectOpts { #[cfg(any(target_os = "linux", target_os = "android"))] fwmark: config.outbound_fwmark, #[cfg(target_os = "freebsd")] user_cookie: config.outbound_user_cookie, #[cfg(target_os = "android")] vpn_protect_path: config.outbound_vpn_protect_path, bind_local_addr: config.outbound_bind_addr.map(|ip| SocketAddr::new(ip, 0)), bind_interface: config.outbound_bind_interface, udp: UdpSocketOpts { allow_fragmentation: config.outbound_udp_allow_fragmentation, ..Default::default() }, ..Default::default() }; connect_opts.tcp.send_buffer_size = config.outbound_send_buffer_size; connect_opts.tcp.recv_buffer_size = config.outbound_recv_buffer_size; connect_opts.tcp.nodelay = config.no_delay; connect_opts.tcp.fastopen = config.fast_open; connect_opts.tcp.keepalive = config.keep_alive.or(Some(SERVER_DEFAULT_KEEPALIVE_TIMEOUT)); connect_opts.tcp.mptcp = config.mptcp; connect_opts.udp.mtu = config.udp_mtu; let mut accept_opts = AcceptOpts { ipv6_only: config.ipv6_only, ..Default::default() }; accept_opts.tcp.send_buffer_size = config.inbound_send_buffer_size; accept_opts.tcp.recv_buffer_size = config.inbound_recv_buffer_size; accept_opts.tcp.nodelay = config.no_delay; accept_opts.tcp.fastopen = config.fast_open; accept_opts.tcp.keepalive = config.keep_alive.or(Some(SERVER_DEFAULT_KEEPALIVE_TIMEOUT)); accept_opts.tcp.mptcp = config.mptcp; accept_opts.udp.mtu = config.udp_mtu; let resolver = build_dns_resolver(config.dns, config.ipv6_first, config.dns_cache_size, &connect_opts) .await .map(Arc::new); let acl = config.acl.map(Arc::new); for inst in config.server { let svr_cfg = inst.config; let mut server_builder = ServerBuilder::new(svr_cfg); if let Some(ref r) = resolver { server_builder.set_dns_resolver(r.clone()); } let mut connect_opts = connect_opts.clone(); let accept_opts = accept_opts.clone(); #[cfg(any(target_os = "linux", target_os = "android"))] if let Some(fwmark) = inst.outbound_fwmark { connect_opts.fwmark = Some(fwmark); } #[cfg(target_os = "freebsd")] if let Some(user_cookie) = inst.outbound_user_cookie { connect_opts.user_cookie = Some(user_cookie); } if let Some(bind_local_addr) = inst.outbound_bind_addr { connect_opts.bind_local_addr = Some(SocketAddr::new(bind_local_addr, 0)); } if let Some(bind_interface) = inst.outbound_bind_interface { connect_opts.bind_interface = Some(bind_interface); } if let Some(udp_allow_fragmentation) = inst.outbound_udp_allow_fragmentation { connect_opts.udp.allow_fragmentation = udp_allow_fragmentation; } server_builder.set_connect_opts(connect_opts); server_builder.set_accept_opts(accept_opts); if let Some(c) = config.udp_max_associations { server_builder.set_udp_capacity(c); } if let Some(d) = config.udp_timeout { server_builder.set_udp_expiry_duration(d); } if let Some(ref m) = config.manager { server_builder.set_manager_addr(m.addr.clone()); } match inst.acl { Some(acl) => server_builder.set_acl(Arc::new(acl)), None => { if let Some(ref acl) = acl { server_builder.set_acl(acl.clone()); } } } if config.ipv6_first { server_builder.set_ipv6_first(config.ipv6_first); } server_builder.set_security_config(&config.security); let server = server_builder.build().await?; servers.push(server); } if servers.len() == 1 { let server = servers.pop().unwrap(); return server.run().await; } let mut vfut = Vec::with_capacity(servers.len()); for server in servers { vfut.push(ServerHandle(tokio::spawn(async move { server.run().await }))); } let (res, ..) = future::select_all(vfut).await; res } ================================================ FILE: crates/shadowsocks-service/src/server/server.rs ================================================ //! Shadowsocks Server instance use std::{collections::HashMap, io, sync::Arc, time::Duration}; use futures::future; use log::{error, trace}; use shadowsocks::{ ManagerClient, config::{ManagerAddr, ServerConfig}, dns_resolver::DnsResolver, net::{AcceptOpts, ConnectOpts}, plugin::{Plugin, PluginMode}, }; use tokio::time; use crate::{acl::AccessControl, config::SecurityConfig, net::FlowStat, utils::ServerHandle}; use super::{context::ServiceContext, tcprelay::TcpServer, udprelay::UdpServer}; /// Shadowsocks Server Builder pub struct ServerBuilder { context: ServiceContext, svr_cfg: ServerConfig, udp_expiry_duration: Option, udp_capacity: Option, manager_addr: Option, accept_opts: AcceptOpts, } impl ServerBuilder { /// Create a new server builder from configuration pub fn new(svr_cfg: ServerConfig) -> Self { Self::with_context(ServiceContext::new(), svr_cfg) } /// Create a new server builder with context fn with_context(context: ServiceContext, svr_cfg: ServerConfig) -> Self { Self { context, svr_cfg, udp_expiry_duration: None, udp_capacity: None, manager_addr: None, accept_opts: AcceptOpts::default(), } } /// Get flow statistic pub fn flow_stat(&self) -> Arc { self.context.flow_stat() } /// Get flow statistic reference pub fn flow_stat_ref(&self) -> &FlowStat { self.context.flow_stat_ref() } /// Set `ConnectOpts` pub fn set_connect_opts(&mut self, opts: ConnectOpts) { self.context.set_connect_opts(opts) } /// Set UDP association's expiry duration pub fn set_udp_expiry_duration(&mut self, d: Duration) { self.udp_expiry_duration = Some(d); } /// Set total UDP associations to be kept in one server pub fn set_udp_capacity(&mut self, c: usize) { self.udp_capacity = Some(c); } /// Set manager's address to report `stat` pub fn set_manager_addr(&mut self, manager_addr: ManagerAddr) { self.manager_addr = Some(manager_addr); } /// Get server's configuration pub fn server_config(&self) -> &ServerConfig { &self.svr_cfg } /// Set customized DNS resolver pub fn set_dns_resolver(&mut self, resolver: Arc) { self.context.set_dns_resolver(resolver) } /// Set access control list pub fn set_acl(&mut self, acl: Arc) { self.context.set_acl(acl); } /// Set `AcceptOpts` for accepting new connections pub fn set_accept_opts(&mut self, opts: AcceptOpts) { self.accept_opts = opts; } /// Try to connect IPv6 addresses first if hostname could be resolved to both IPv4 and IPv6 pub fn set_ipv6_first(&mut self, ipv6_first: bool) { self.context.set_ipv6_first(ipv6_first); } /// Set security config pub fn set_security_config(&mut self, security: &SecurityConfig) { self.context.set_security_config(security) } /// Start the server /// /// 1. Starts plugin (subprocess) /// 2. Starts TCP server (listener) /// 3. Starts UDP server (listener) pub async fn build(mut self) -> io::Result { let context = Arc::new(self.context); let mut plugin = None; if let Some(plugin_cfg) = self.svr_cfg.plugin() { let plugin_process = Plugin::start(plugin_cfg, self.svr_cfg.addr(), PluginMode::Server)?; self.svr_cfg.set_plugin_addr(plugin_process.local_addr().into()); plugin = Some(plugin_process); } let mut tcp_server = None; if self.svr_cfg.mode().enable_tcp() { let server = TcpServer::new(context.clone(), self.svr_cfg.clone(), self.accept_opts.clone()).await?; tcp_server = Some(server); } let mut udp_server = None; if self.svr_cfg.mode().enable_udp() { let server = UdpServer::new( context.clone(), self.svr_cfg.clone(), self.udp_expiry_duration, self.udp_capacity, self.accept_opts.clone(), ) .await?; udp_server = Some(server); } Ok(Server { context, svr_cfg: self.svr_cfg, tcp_server, udp_server, manager_addr: self.manager_addr, plugin, }) } } /// Shadowsocks Server instance pub struct Server { context: Arc, svr_cfg: ServerConfig, tcp_server: Option, udp_server: Option, manager_addr: Option, plugin: Option, } impl Server { /// Get Server's configuration pub fn server_config(&self) -> &ServerConfig { &self.svr_cfg } /// Get TCP server instance pub fn tcp_server(&self) -> Option<&TcpServer> { self.tcp_server.as_ref() } /// Get UDP server instance pub fn udp_server(&self) -> Option<&UdpServer> { self.udp_server.as_ref() } /// Start serving pub async fn run(self) -> io::Result<()> { let mut vfut = Vec::new(); if let Some(plugin) = self.plugin { vfut.push(ServerHandle(tokio::spawn(async move { match plugin.join().await { Ok(status) => { error!("plugin exited with status: {}", status); Ok(()) } Err(err) => { error!("plugin exited with error: {}", err); Err(err) } } }))); } if let Some(tcp_server) = self.tcp_server { vfut.push(ServerHandle(tokio::spawn(tcp_server.run()))); } if let Some(udp_server) = self.udp_server { vfut.push(ServerHandle(tokio::spawn(udp_server.run()))); } if let Some(manager_addr) = self.manager_addr { vfut.push(ServerHandle(tokio::spawn(async move { loop { match ManagerClient::connect( self.context.context_ref(), &manager_addr, self.context.connect_opts_ref(), ) .await { Err(err) => { error!("failed to connect manager {}, error: {}", manager_addr, err); } Ok(mut client) => { use shadowsocks::manager::protocol::StatRequest; let mut stat = HashMap::new(); let flow = self.context.flow_stat_ref(); stat.insert(self.svr_cfg.addr().port(), flow.tx() + flow.rx()); let req = StatRequest { stat }; match client.stat(&req).await { Err(err) => { error!( "failed to send stat to manager {}, error: {}, {:?}", manager_addr, err, req ); } _ => { trace!("report to manager {}, {:?}", manager_addr, req); } } } } // Report every 10 seconds time::sleep(Duration::from_secs(10)).await; } }))); } if let (Err(err), ..) = future::select_all(vfut).await { error!("servers exited with error: {}", err); } let err = io::Error::other("server exited unexpectedly"); Err(err) } } ================================================ FILE: crates/shadowsocks-service/src/server/tcprelay.rs ================================================ //! Shadowsocks TCP server use std::{ future::Future, io::{self, ErrorKind}, net::SocketAddr, sync::Arc, time::Duration, }; use log::{debug, error, info, trace, warn}; use shadowsocks::{ ProxyListener, ServerConfig, crypto::CipherKind, net::{AcceptOpts, TcpStream as OutboundTcpStream}, relay::tcprelay::{ProxyServerStream, utils::copy_encrypted_bidirectional}, }; use tokio::{ io::{AsyncReadExt, AsyncWriteExt}, net::TcpStream as TokioTcpStream, time, }; use crate::net::{MonProxyStream, utils::ignore_until_end}; use super::context::ServiceContext; /// TCP server instance pub struct TcpServer { context: Arc, svr_cfg: ServerConfig, listener: ProxyListener, } impl TcpServer { pub(crate) async fn new( context: Arc, svr_cfg: ServerConfig, accept_opts: AcceptOpts, ) -> io::Result { let listener = ProxyListener::bind_with_opts(context.context(), &svr_cfg, accept_opts).await?; Ok(Self { context, svr_cfg, listener, }) } /// Server's configuration pub fn server_config(&self) -> &ServerConfig { &self.svr_cfg } /// Server's listen address pub fn local_addr(&self) -> io::Result { self.listener.local_addr() } /// Start server's accept loop pub async fn run(self) -> io::Result<()> { info!( "shadowsocks tcp server listening on {}, inbound address {}", self.listener.local_addr().expect("listener.local_addr"), self.svr_cfg.addr() ); loop { let flow_stat = self.context.flow_stat(); let (local_stream, peer_addr) = match self .listener .accept_map(|s| MonProxyStream::from_stream(s, flow_stat)) .await { Ok(s) => s, Err(err) => { error!("tcp server accept failed with error: {}", err); time::sleep(Duration::from_secs(1)).await; continue; } }; if self.context.check_client_blocked(&peer_addr) { warn!("access denied from {} by ACL rules", peer_addr); continue; } let client = TcpServerClient { context: self.context.clone(), method: self.svr_cfg.method(), peer_addr, stream: local_stream, timeout: self.svr_cfg.timeout(), }; tokio::spawn(async move { if let Err(err) = client.serve().await { debug!("tcp server stream aborted with error: {}", err); } }); } } } #[inline] async fn timeout_fut(duration: Option, f: F) -> io::Result where F: Future>, { match duration { None => f.await, Some(d) => match time::timeout(d, f).await { Ok(o) => o, Err(..) => Err(ErrorKind::TimedOut.into()), }, } } struct TcpServerClient { context: Arc, method: CipherKind, peer_addr: SocketAddr, stream: ProxyServerStream>, timeout: Option, } impl TcpServerClient { async fn serve(mut self) -> io::Result<()> { // let target_addr = match Address::read_from(&mut self.stream).await { let target_addr = match timeout_fut(self.timeout, self.stream.handshake()).await { Ok(a) => a, // Err(Socks5Error::IoError(ref err)) if err.kind() == ErrorKind::UnexpectedEof => { // debug!( // "handshake failed, received EOF before a complete target Address, peer: {}", // self.peer_addr // ); // return Ok(()); // } Err(err) if err.kind() == ErrorKind::UnexpectedEof => { debug!( "tcp handshake failed, received EOF before a complete target Address, peer: {}", self.peer_addr ); return Ok(()); } Err(err) if err.kind() == ErrorKind::TimedOut => { debug!( "tcp handshake failed, timeout before a complete target Address, peer: {}", self.peer_addr ); return Ok(()); } Err(err) => { // https://github.com/shadowsocks/shadowsocks-rust/issues/292 // // Keep connection open. Except AEAD-2022 warn!("tcp handshake failed. peer: {}, {}", self.peer_addr, err); #[cfg(feature = "aead-cipher-2022")] if self.method.is_aead_2022() { // Set SO_LINGER(0) for misbehave clients, which will eventually receive RST. (ECONNRESET) // This will also prevent the socket entering TIME_WAIT state. let stream = self.stream.into_inner().into_inner(); // tokio's TcpStream.set_linger was marked as deprecated. // But we set linger(0), which won't block the thread when close() the socket. let _ = socket2::SockRef::from(&stream).set_linger(Some(Duration::ZERO)); return Ok(()); } debug!("tcp silent-drop peer: {}", self.peer_addr); // Unwrap and get the plain stream. // Otherwise it will keep reporting decryption error before reaching EOF. // // Note: This will drop all data in the decryption buffer, which is no going back. let mut stream = self.stream.into_inner(); let res = ignore_until_end(&mut stream).await; trace!( "tcp silent-drop peer: {} is now closing with result {:?}", self.peer_addr, res ); return Ok(()); } }; trace!( "accepted tcp client connection {}, establishing tunnel to {}", self.peer_addr, target_addr ); if self.context.check_outbound_blocked(&target_addr).await { error!( "tcp client {} outbound {} blocked by ACL rules", self.peer_addr, target_addr ); return Ok(()); } let mut remote_stream = match timeout_fut( self.timeout, OutboundTcpStream::connect_remote_with_opts( self.context.context_ref(), &target_addr, self.context.connect_opts_ref(), ), ) .await { Ok(s) => s, Err(err) => { error!( "tcp tunnel {} -> {} connect failed, error: {}", self.peer_addr, target_addr, err ); return Err(err); } }; // https://github.com/shadowsocks/shadowsocks-rust/issues/232 // // Protocols like FTP, clients will wait for servers to send Welcome Message without sending anything. // // Wait at most 500ms, and then sends handshake packet to remote servers. if self.context.connect_opts_ref().tcp.fastopen { let mut buffer = [0u8; 8192]; match time::timeout(Duration::from_millis(500), self.stream.read(&mut buffer)).await { Ok(Ok(0)) => { // EOF. Just terminate right here. return Ok(()); } Ok(Ok(n)) => { // Send the first packet. timeout_fut(self.timeout, remote_stream.write_all(&buffer[..n])).await?; } Ok(Err(err)) => return Err(err), Err(..) => { // Timeout. Send handshake to server. timeout_fut(self.timeout, remote_stream.write(&[])).await?; trace!( "tcp tunnel {} -> {} sent TFO connect without data", self.peer_addr, target_addr ); } } } debug!( "established tcp tunnel {} <-> {} with {:?}", self.peer_addr, target_addr, self.context.connect_opts_ref() ); match copy_encrypted_bidirectional(self.method, &mut self.stream, &mut remote_stream).await { Ok((rn, wn)) => { trace!( "tcp tunnel {} <-> {} closed, L2R {} bytes, R2L {} bytes", self.peer_addr, target_addr, rn, wn ); } Err(err) => { trace!( "tcp tunnel {} <-> {} closed with error: {}", self.peer_addr, target_addr, err ); } } Ok(()) } } ================================================ FILE: crates/shadowsocks-service/src/server/udprelay.rs ================================================ //! Shadowsocks UDP server use std::{cell::RefCell, io, net::SocketAddr, sync::Arc, time::Duration}; use bytes::Bytes; use futures::future; use log::{debug, error, info, trace, warn}; use lru_time_cache::LruCache; use rand::{RngExt, rngs::SmallRng}; use shadowsocks::{ ServerConfig, config::ServerUser, crypto::CipherCategory, lookup_then, net::{ AcceptOpts, AddrFamily, UdpSocket as OutboundUdpSocket, UdpSocket as InboundUdpSocket, get_ip_stack_capabilities, }, relay::{ socks5::Address, udprelay::{MAXIMUM_UDP_PAYLOAD_SIZE, ProxySocket, options::UdpSocketControlData}, }, }; use tokio::{runtime::Handle, sync::mpsc, task::JoinHandle, time}; use crate::net::{ MonProxySocket, UDP_ASSOCIATION_KEEP_ALIVE_CHANNEL_SIZE, UDP_ASSOCIATION_SEND_CHANNEL_SIZE, packet_window::PacketWindowFilter, utils::to_ipv4_mapped, }; use super::context::ServiceContext; #[derive(Debug, Clone, Copy)] enum NatKey { PeerAddr(SocketAddr), #[cfg(feature = "aead-cipher-2022")] SessionId(u64), } type AssociationMap = LruCache; #[cfg(feature = "aead-cipher-2022")] type SessionMap = LruCache; enum NatMap { Association(AssociationMap), #[cfg(feature = "aead-cipher-2022")] Session(SessionMap), } impl NatMap { fn cleanup_expired(&mut self) { match *self { Self::Association(ref mut m) => { m.iter(); } #[cfg(feature = "aead-cipher-2022")] Self::Session(ref mut m) => { m.iter(); } } } fn keep_alive(&mut self, key: &NatKey) { match (self, key) { (Self::Association(m), NatKey::PeerAddr(peer_addr)) => { m.get(peer_addr); } #[cfg(feature = "aead-cipher-2022")] (Self::Session(m), NatKey::SessionId(session_id)) => { m.get(session_id); } #[allow(unreachable_patterns)] _ => unreachable!("NatMap & NatKey mismatch"), } } } /// UDP server instance pub struct UdpServer { context: Arc, assoc_map: NatMap, keepalive_tx: mpsc::Sender, keepalive_rx: mpsc::Receiver, time_to_live: Duration, listener: Arc>, svr_cfg: ServerConfig, } impl UdpServer { pub(crate) async fn new( context: Arc, svr_cfg: ServerConfig, time_to_live: Option, capacity: Option, accept_opts: AcceptOpts, ) -> io::Result { let time_to_live = time_to_live.unwrap_or(crate::DEFAULT_UDP_EXPIRY_DURATION); fn create_assoc_map(time_to_live: Duration, capacity: Option) -> LruCache where K: Ord + Clone, { match capacity { Some(capacity) => LruCache::with_expiry_duration_and_capacity(time_to_live, capacity), None => LruCache::with_expiry_duration(time_to_live), } } let assoc_map = match svr_cfg.method().category() { CipherCategory::None => NatMap::Association(create_assoc_map(time_to_live, capacity)), #[cfg(feature = "aead-cipher")] CipherCategory::Aead => NatMap::Association(create_assoc_map(time_to_live, capacity)), #[cfg(feature = "stream-cipher")] CipherCategory::Stream => NatMap::Association(create_assoc_map(time_to_live, capacity)), #[cfg(feature = "aead-cipher-2022")] CipherCategory::Aead2022 => NatMap::Session(create_assoc_map(time_to_live, capacity)), }; let (keepalive_tx, keepalive_rx) = mpsc::channel(UDP_ASSOCIATION_KEEP_ALIVE_CHANNEL_SIZE); let socket = ProxySocket::bind_with_opts(context.context(), &svr_cfg, accept_opts).await?; let socket = MonProxySocket::from_socket(socket, context.flow_stat()); let listener = Arc::new(socket); Ok(Self { context, assoc_map, keepalive_tx, keepalive_rx, time_to_live, listener, svr_cfg, }) } /// Server's configuration pub fn server_config(&self) -> &ServerConfig { &self.svr_cfg } /// Server's listen address pub fn local_addr(&self) -> io::Result { self.listener.get_ref().local_addr() } /// Start server's accept loop pub async fn run(mut self) -> io::Result<()> { info!( "shadowsocks udp server listening on {}, inbound address {}", self.local_addr().expect("listener.local_addr"), self.svr_cfg.addr(), ); let mut cleanup_timer = time::interval(self.time_to_live); let mut orx_opt = None; let cpus = Handle::current().metrics().num_workers(); let mut other_receivers = Vec::new(); if cpus > 1 { let (otx, orx) = mpsc::channel((cpus - 1) * 16); orx_opt = Some(orx); other_receivers.reserve(cpus - 1); trace!("udp server starting extra {} recv workers", cpus - 1); for _ in 1..cpus { let otx = otx.clone(); let listener = self.listener.clone(); let context = self.context.clone(); other_receivers.push(tokio::spawn(async move { let mut buffer = [0u8; MAXIMUM_UDP_PAYLOAD_SIZE]; loop { let (n, peer_addr, target_addr, control) = match Self::recv_one_packet(&context, &listener, &mut buffer).await { Some(s) => s, None => continue, }; if (otx .send((peer_addr, target_addr, control, Bytes::copy_from_slice(&buffer[..n]))) .await) .is_err() { // If Result is error, the channel receiver is closed. We should exit the task. break; } } })); } } struct MulticoreTaskGuard<'a> { tasks: &'a mut Vec>, } impl Drop for MulticoreTaskGuard<'_> { fn drop(&mut self) { for task in self.tasks.iter_mut() { task.abort(); } } } let _guard = MulticoreTaskGuard { tasks: &mut other_receivers, }; type QueuedDataType = (SocketAddr, Address, Option, Bytes); #[inline] async fn multicore_recv(orx_opt: &mut Option>) -> QueuedDataType { match orx_opt { None => future::pending().await, Some(orx) => match orx.recv().await { Some(t) => t, None => unreachable!("multicore sender should keep at least 1"), }, } } let mut buffer = [0u8; MAXIMUM_UDP_PAYLOAD_SIZE]; // Make a clone to self.listener to avoid borrowing self let listener = self.listener.clone(); loop { tokio::select! { _ = cleanup_timer.tick() => { // cleanup expired associations. iter() will remove expired elements self.assoc_map.cleanup_expired(); } peer_addr_opt = self.keepalive_rx.recv() => { let peer_addr = peer_addr_opt.expect("keep-alive channel closed unexpectedly"); self.assoc_map.keep_alive(&peer_addr); } recv_result = Self::recv_one_packet(&self.context, &listener, &mut buffer) => { let (n, peer_addr, target_addr, control) = match recv_result { Some(s) => s, None => continue, }; let data = &buffer[..n]; if let Err(err) = self.send_packet(&listener, peer_addr, target_addr, control, Bytes::copy_from_slice(data)).await { debug!( "udp packet relay {} with {} bytes failed, error: {}", peer_addr, data.len(), err ); } } recv_result = multicore_recv(&mut orx_opt), if orx_opt.is_some() => { let (peer_addr, target_addr, control, data) = recv_result; let data_len = data.len(); if let Err(err) = self.send_packet(&listener, peer_addr, target_addr, control, data).await { debug!( "udp packet relay {} with {} bytes failed, error: {}", peer_addr, data_len, err ); } } } } } async fn recv_one_packet( context: &ServiceContext, l: &MonProxySocket, buffer: &mut [u8], ) -> Option<(usize, SocketAddr, Address, Option)> { let (n, peer_addr, target_addr, control) = match l.recv_from_with_ctrl(buffer).await { Ok(s) => s, Err(err) => { error!("udp server recv packet failed. {}", err); return None; } }; if n == 0 { // For windows, it will generate a ICMP Port Unreachable Message // https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-recvfrom // Which will result in recv_from return 0. // // It cannot be solved here, because `WSAGetLastError` is already set. // // See `relay::udprelay::utils::create_socket` for more detail. return None; } if context.check_client_blocked(&peer_addr) { warn!( "udp client {} outbound {} access denied by ACL rules", peer_addr, target_addr ); return None; } if context.check_outbound_blocked(&target_addr).await { warn!("udp client {} outbound {} blocked by ACL rules", peer_addr, target_addr); return None; } Some((n, peer_addr, target_addr, control)) } async fn send_packet( &mut self, listener: &Arc>, peer_addr: SocketAddr, target_addr: Address, control: Option, data: Bytes, ) -> io::Result<()> { match self.assoc_map { NatMap::Association(ref mut m) => { if let Some(assoc) = m.get(&peer_addr) { return assoc.try_send((peer_addr, target_addr, data, control)); } let assoc = UdpAssociation::new_association( self.context.clone(), listener.clone(), peer_addr, self.keepalive_tx.clone(), ); debug!("created udp association for {}", peer_addr); assoc.try_send((peer_addr, target_addr, data, control))?; m.insert(peer_addr, assoc); } #[cfg(feature = "aead-cipher-2022")] NatMap::Session(ref mut m) => { let xcontrol = match control { None => { error!("control is required for session based NAT, from {}", peer_addr); return Err(io::Error::other("control data missing in packet")); } Some(ref c) => c, }; let client_session_id = xcontrol.client_session_id; if let Some(assoc) = m.get(&client_session_id) { return assoc.try_send((peer_addr, target_addr, data, control)); } let assoc = UdpAssociation::new_session( self.context.clone(), listener.clone(), peer_addr, self.keepalive_tx.clone(), client_session_id, ); debug!( "created udp association for {} with session {}", peer_addr, client_session_id ); assoc.try_send((peer_addr, target_addr, data, control))?; m.insert(client_session_id, assoc); } } Ok(()) } } type UdpAssociationSendMessage = (SocketAddr, Address, Bytes, Option); struct UdpAssociation { assoc_handle: JoinHandle<()>, sender: mpsc::Sender, } impl Drop for UdpAssociation { fn drop(&mut self) { self.assoc_handle.abort(); } } impl UdpAssociation { fn new_association( context: Arc, inbound: Arc>, peer_addr: SocketAddr, keepalive_tx: mpsc::Sender, ) -> Self { let (assoc_handle, sender) = UdpAssociationContext::create(context, inbound, peer_addr, keepalive_tx, None); Self { assoc_handle, sender } } #[cfg(feature = "aead-cipher-2022")] fn new_session( context: Arc, inbound: Arc>, peer_addr: SocketAddr, keepalive_tx: mpsc::Sender, client_session_id: u64, ) -> Self { let (assoc_handle, sender) = UdpAssociationContext::create(context, inbound, peer_addr, keepalive_tx, Some(client_session_id)); Self { assoc_handle, sender } } fn try_send(&self, data: UdpAssociationSendMessage) -> io::Result<()> { if self.sender.try_send(data).is_err() { let err = io::Error::other("udp relay channel full"); return Err(err); } Ok(()) } } struct ClientSessionContext { client_session_id: u64, packet_window_filter: PacketWindowFilter, client_user: Option>, } impl ClientSessionContext { fn new(client_session_id: u64) -> Self { Self { client_session_id, packet_window_filter: PacketWindowFilter::new(), client_user: None, } } } struct UdpAssociationContext { context: Arc, peer_addr: SocketAddr, outbound_ipv4_socket: Option, outbound_ipv6_socket: Option, keepalive_tx: mpsc::Sender, keepalive_flag: bool, inbound: Arc>, // AEAD 2022 client_session: Option, server_session_id: u64, server_packet_id: u64, } impl Drop for UdpAssociationContext { fn drop(&mut self) { debug!("udp association for {} is closed", self.peer_addr); } } thread_local! { static CLIENT_SESSION_RNG: RefCell = RefCell::new(rand::make_rng()); } #[inline] fn generate_server_session_id() -> u64 { loop { let id = CLIENT_SESSION_RNG.with(|rng| rng.borrow_mut().random()); if id != 0 { break id; } } } impl UdpAssociationContext { fn create( context: Arc, inbound: Arc>, peer_addr: SocketAddr, keepalive_tx: mpsc::Sender, client_session_id: Option, ) -> (JoinHandle<()>, mpsc::Sender) { // Pending packets UDP_ASSOCIATION_SEND_CHANNEL_SIZE for each association should be good enough for a server. // If there are plenty of packets stuck in the channel, dropping excessive packets is a good way to protect the server from // being OOM. let (sender, receiver) = mpsc::channel(UDP_ASSOCIATION_SEND_CHANNEL_SIZE); let mut assoc = Self { context, peer_addr, outbound_ipv4_socket: None, outbound_ipv6_socket: None, keepalive_tx, keepalive_flag: false, inbound, client_session: client_session_id.map(ClientSessionContext::new), // server_session_id must be generated randomly server_session_id: generate_server_session_id(), server_packet_id: 0, }; let handle = tokio::spawn(async move { assoc.dispatch_packet(receiver).await }); (handle, sender) } async fn dispatch_packet(&mut self, mut receiver: mpsc::Receiver) { let mut outbound_ipv4_buffer = Vec::new(); let mut outbound_ipv6_buffer = Vec::new(); let mut keepalive_interval = time::interval(Duration::from_secs(1)); loop { tokio::select! { packet_received_opt = receiver.recv() => { let (peer_addr, target_addr, data, control) = match packet_received_opt { Some(d) => d, None => { trace!("udp association for {} -> ... channel closed", self.peer_addr); break; } }; self.dispatch_received_packet(peer_addr, &target_addr, &data, &control).await; } received_opt = receive_from_outbound_opt(&self.outbound_ipv4_socket, &mut outbound_ipv4_buffer), if self.outbound_ipv4_socket.is_some() => { let (n, addr) = match received_opt { Ok(r) => r, Err(err) => { error!("udp relay {} <- ... failed, error: {}", self.peer_addr, err); // Socket failure. Reset for recreation. self.outbound_ipv4_socket = None; continue; } }; let addr = Address::from(addr); self.send_received_respond_packet(addr, &outbound_ipv4_buffer[..n]).await; } received_opt = receive_from_outbound_opt(&self.outbound_ipv6_socket, &mut outbound_ipv6_buffer), if self.outbound_ipv6_socket.is_some() => { let (n, addr) = match received_opt { Ok(r) => r, Err(err) => { error!("udp relay {} <- ... failed, error: {}", self.peer_addr, err); // Socket failure. Reset for recreation. self.outbound_ipv6_socket = None; continue; } }; let addr = Address::from(addr); self.send_received_respond_packet(addr, &outbound_ipv6_buffer[..n]).await; } _ = keepalive_interval.tick() => { if self.keepalive_flag { let nat_key = match self.client_session { None => NatKey::PeerAddr(self.peer_addr), #[cfg(feature = "aead-cipher-2022")] Some(ref s) => NatKey::SessionId(s.client_session_id), #[cfg(not(feature = "aead-cipher-2022"))] Some(..) => unreachable!("client_session_id is not None but aead-cipher-2022 is not enabled"), }; if self.keepalive_tx.try_send(nat_key).is_err() { debug!("udp relay {:?} keep-alive failed, channel full or closed", nat_key); } else { self.keepalive_flag = false; } } } } } #[inline] async fn receive_from_outbound_opt( socket: &Option, buf: &mut Vec, ) -> io::Result<(usize, SocketAddr)> { match *socket { None => future::pending().await, Some(ref s) => { if buf.is_empty() { buf.resize(MAXIMUM_UDP_PAYLOAD_SIZE, 0); } s.recv_from(buf).await } } } } async fn dispatch_received_packet( &mut self, peer_addr: SocketAddr, target_addr: &Address, data: &[u8], control: &Option, ) { if let Some(ref mut session) = self.client_session && peer_addr != self.peer_addr { debug!( "udp relay for {} changed to {}, session: {:?}", self.peer_addr, peer_addr, session.client_session_id ); self.peer_addr = peer_addr; } trace!( "udp relay {} -> {} with {} bytes, control: {:?}", self.peer_addr, target_addr, data.len(), control, ); if self.context.check_outbound_blocked(target_addr).await { error!( "udp client {} outbound {} blocked by ACL rules", self.peer_addr, target_addr ); return; } if let Some(control) = control { // Check if Packet ID is in the window let session_context = self .client_session .get_or_insert_with(|| ClientSessionContext::new(control.client_session_id)); let packet_id = control.packet_id; if !session_context .packet_window_filter .validate_packet_id(packet_id, u64::MAX) { error!("udp client {} packet_id {} out of window", self.peer_addr, packet_id); return; } session_context.client_user.clone_from(&control.user); } if let Err(err) = self.dispatch_received_outbound_packet(target_addr, data).await { error!( "udp relay {} -> {} with {} bytes, error: {}", self.peer_addr, target_addr, data.len(), err ); } } async fn dispatch_received_outbound_packet(&mut self, target_addr: &Address, data: &[u8]) -> io::Result<()> { match *target_addr { Address::SocketAddress(sa) => self.send_received_outbound_packet(sa, data).await, Address::DomainNameAddress(ref dname, port) => { lookup_then!(self.context.context_ref(), dname, port, |sa| { self.send_received_outbound_packet(sa, data).await }) .map(|_| ()) } } } async fn send_received_outbound_packet(&mut self, original_target_addr: SocketAddr, data: &[u8]) -> io::Result<()> { let ip_stack_caps = get_ip_stack_capabilities(); let target_addr = match original_target_addr { SocketAddr::V4(ref v4) => { // If IPv4-mapped-IPv6 is supported. // Converts IPv4 address to IPv4-mapped-IPv6 // All sockets will be created in IPv6 (nearly all modern OS supports IPv6 sockets) if ip_stack_caps.support_ipv4_mapped_ipv6 { SocketAddr::new(v4.ip().to_ipv6_mapped().into(), v4.port()) } else { original_target_addr } } SocketAddr::V6(ref v6) => { // If IPv6 is not supported. Try to map it back to IPv4. if !ip_stack_caps.support_ipv6 || !ip_stack_caps.support_ipv4_mapped_ipv6 { match v6.ip().to_ipv4_mapped() { Some(v4) => SocketAddr::new(v4.into(), v6.port()), None => original_target_addr, } } else { original_target_addr } } }; let socket = match target_addr { SocketAddr::V4(..) => match self.outbound_ipv4_socket { Some(ref mut socket) => socket, None => { let socket = OutboundUdpSocket::connect_any_with_opts(AddrFamily::Ipv4, self.context.connect_opts_ref()) .await?; self.outbound_ipv4_socket.insert(socket) } }, SocketAddr::V6(..) => match self.outbound_ipv6_socket { Some(ref mut socket) => socket, None => { let socket = OutboundUdpSocket::connect_any_with_opts(AddrFamily::Ipv6, self.context.connect_opts_ref()) .await?; self.outbound_ipv6_socket.insert(socket) } }, }; match socket.send_to(data, target_addr).await { Ok(n) => { if n != data.len() { warn!( "{} -> {} sent {} bytes != expected {} bytes", self.peer_addr, target_addr, n, data.len() ); } Ok(()) } Err(err) => Err(err), } } async fn send_received_respond_packet(&mut self, mut addr: Address, data: &[u8]) { trace!("udp relay {} <- {} received {} bytes", self.peer_addr, addr, data.len()); // Keep association alive in map self.keepalive_flag = true; // Convert IPv4-mapped-IPv6 to IPv4 // // It is an undefined behavior in shadowsocks' protocol about how to handle IPv4-mapped-IPv6. // But for some implementations, they may expect the target address to be IPv4, because // the peer address is IPv4 when calling `sendto`. if let Address::SocketAddress(SocketAddr::V6(ref v6)) = addr && let Some(v4) = to_ipv4_mapped(v6.ip()) { addr = Address::SocketAddress(SocketAddr::new(v4.into(), v6.port())); } match self.client_session { None => { // Naive route, send data directly back to client without session match self.inbound.send_to(self.peer_addr, &addr, data).await { Err(err) => { warn!( "udp failed to send back {} bytes to client {}, from target {}, error: {}", data.len(), self.peer_addr, addr, err ); } _ => { trace!("udp relay {} <- {} with {} bytes", self.peer_addr, addr, data.len()); } } } Some(ref client_session) => { // AEAD 2022, client session // Increase Packet ID before send self.server_packet_id = match self.server_packet_id.checked_add(1) { Some(i) => i, None => { // FIXME: server_packet_id overflowed. There is no way to recover from this error. // // Application clients may open a new session when it couldn't receive proper respond. warn!( "udp failed to send back {} bytes to client {}, from target {}, server packet id overflowed", data.len(), self.peer_addr, addr ); return; } }; let mut control = UdpSocketControlData::default(); control.client_session_id = client_session.client_session_id; control.server_session_id = self.server_session_id; control.packet_id = self.server_packet_id; control.user.clone_from(&client_session.client_user); match self .inbound .send_to_with_ctrl(self.peer_addr, &addr, &control, data) .await { Err(err) => { warn!( "udp failed to send back {} bytes to client {}, from target {}, control: {:?}, error: {}", data.len(), self.peer_addr, addr, control, err ); } _ => { trace!( "udp relay {} <- {} with {} bytes, control {:?}", self.peer_addr, addr, data.len(), control ); } } } } } } ================================================ FILE: crates/shadowsocks-service/src/sys/mod.rs ================================================ use cfg_if::cfg_if; cfg_if! { if #[cfg(unix)] { mod unix; #[allow(unused_imports)] pub use self::unix::*; } } ================================================ FILE: crates/shadowsocks-service/src/sys/unix/macos.rs ================================================ //! macOS specific APIs use std::{ffi::CString, io, os::fd::RawFd, ptr}; use log::error; unsafe extern "C" { /// https://developer.apple.com/documentation/xpc/1505523-launch_activate_socket fn launch_activate_socket( name: *const libc::c_char, fds: *mut *mut libc::c_int, cnt: *mut libc::size_t, ) -> libc::c_int; } pub fn get_launch_activate_socket(name: &str) -> io::Result { let mut fds: *mut libc::c_int = ptr::null_mut(); let mut cnt: libc::size_t = 0; let cname = match CString::new(name) { Ok(n) => n, Err(..) => { return Err(io::Error::other(format!( "activate socket name \"{}\" contains NUL bytes", name ))); } }; unsafe { let ret = launch_activate_socket(cname.as_ptr(), &mut fds as *mut _, &mut cnt as *mut _); if ret != 0 { let err = io::Error::last_os_error(); match err.raw_os_error() { Some(libc::ENOENT) => { error!("activate socket name \"{}\" doesn't exist, error: {}", name, err); } Some(libc::ESRCH) => { error!("current process is not managed by launchd, error: {}", err); } Some(libc::EALREADY) => { error!( "activate socket name \"{}\" has already been activated, error: {}", name, err ); } _ => {} } return Err(err); } } let result = if cnt == 0 { Err(io::Error::new( io::ErrorKind::InvalidData, format!("launch socket with name \"{}\" doesn't exist", name), )) } else if cnt > 1 { for idx in 0..cnt { unsafe { let fd = *(fds.add(idx)); let _ = libc::close(fd); } } Err(io::Error::new( io::ErrorKind::InvalidData, format!( "launch socket with name \"{}\" should be unique, but found {}", name, cnt ), )) } else { // Take fds[0] as the result let fd = unsafe { *fds }; Ok(fd as RawFd) }; if !fds.is_null() { unsafe { libc::free(fds as *mut _) }; } result } ================================================ FILE: crates/shadowsocks-service/src/sys/unix/mod.rs ================================================ use std::io; use cfg_if::cfg_if; cfg_if! { if #[cfg(target_os = "macos")] { mod macos; #[allow(unused_imports)] pub use self::macos::*; } } #[allow(dead_code)] #[cfg(not(target_os = "android"))] pub fn set_nofile(nofile: u64) -> io::Result<()> { use std::io::Error; unsafe { // set both soft and hard limit let lim = libc::rlimit { rlim_cur: nofile as libc::rlim_t, rlim_max: nofile as libc::rlim_t, }; if libc::setrlimit(libc::RLIMIT_NOFILE, &lim as *const _) < 0 { return Err(Error::last_os_error()); } } Ok(()) } #[allow(dead_code)] #[cfg(target_os = "android")] pub fn set_nofile(_nofile: u64) -> io::Result<()> { // Android doesn't have this API Ok(()) } ================================================ FILE: crates/shadowsocks-service/src/utils.rs ================================================ //! Service Utilities use std::{ future::Future, io, pin::Pin, task::{Context, Poll}, }; use futures::ready; use tokio::task::JoinHandle; /// Wrapper of `tokio::task::JoinHandle`, which links to a server instance. /// /// `ServerHandle` implements `Future` which will join the `JoinHandle` and get the result. /// When `ServerHandle` drops, it will abort the task. pub struct ServerHandle(pub JoinHandle>); impl Drop for ServerHandle { #[inline] fn drop(&mut self) { self.0.abort(); } } impl Future for ServerHandle { type Output = io::Result<()>; #[inline] fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { match ready!(Pin::new(&mut self.0).poll(cx)) { Ok(res) => res.into(), Err(err) => Err(io::Error::other(err)).into(), } } } ================================================ FILE: debian/.gitignore ================================================ shadowsocks-rust debhelper-* *.debhelper files *.substvars ================================================ FILE: debian/changelog ================================================ shadowsocks-rust (1.24.0) unstable; urgency=medium ## Features - #1993, #2044 Support logging to file and syslog - #2026 HTTP Client support auto retry if cached connection was lost ## Miscellaneous - RUSTSEC-2025-0120, `json5` upgraded to v1.3 - MSRV bumps to v1.88 -- ty Thur, 11 Dec 2025 07:37:00 +0800 shadowsocks-rust (1.23.5) unstable; urgency=medium ## Features - #1963 Updated `once_cell::sync::Lazy` to `std::sync::LazyLock` - #1967 ACL supported `outbound_allow_list` - #1974 Allow customizable `SocketProtect` trait for Android VpnService ## Bug Fixes - #1966 Build `xdg` only on *nix platforms - #1968 Make `hickory-dns` truly optional -- ty Fri, 04 Jul 2025 22:58:00 +0800 shadowsocks-rust (1.23.4) unstable; urgency=medium ## Bug Fixes - shadowsocks/shadowsocks-android#3185 `local-dns`: Fixed skipping remote resolver for remote servers' names -- ty Mon, 12 May 2025 23:29:00 +0800 shadowsocks-rust (1.23.3) unstable; urgency=medium ## Features - #1943 `online-config`: SIP008 online configuration supports adding plugin whitelist (see README for details) ## Bug Fixes - Build feature `--full` won't report errors for targets that are not supported by `local-tun` and `local-redir`. -- ty Sun, 11 May 2025 21:21:00 +0800 shadowsocks-rust (1.23.2) unstable; urgency=medium ## Bug Fixes - #1940 `local-tun`: Fixes `panic` when resizing cached buffers -- ty Fri, 25 Apr 2025 08:20:00 +0800 shadowsocks-rust (1.23.1) unstable; urgency=medium ## Features - #1922 `local-tun`: Enable congestion control algorithm for TCP connections - #1923 `local-tun`: Disable TCP package receive checksum for improving performance - `local-tun`: Buffer for receiving/sending packets from/to `tun` device are cached globally ## Bug Fixes - #1929 `outbound_bind_addr` for UDP sockets failed to `bind()` if it is an IPv4 address - Double check IPSK key length (AEAD-2022) when reading from configuration file -- ty Mon, 21 Apr 2025 22:26:00 +0800 shadowsocks-rust (1.23.0) unstable; urgency=medium ## Features, Breaking Changes - MSRV bumps to v1.85, Rust language edition upgraded to `2024` - `rand` crate upgraded to v0.9, which may be incompatible with other older crates - `local-fake-dns` switched storage engine from `sled` to `rocksdb`, users should delete the old database file and let `sslocal` recreate it ageain - `local-fake-dns` is moved from `full` to `full-extra` feature because its still unstable ## Bug fixes - #1832 Fixes FreeBSD build error - #1833 Fixes `sswinservice.exe` file paths in Powershell build script - `mips-*` targets cross build reenabled ## Miscellaneous - #1834 Shadowsocks entrance APIs has strongly typed errors -- ty Wed, 19 Mar 2025 21:40:00 +0800 shadowsocks-rust (1.22.0) unstable; urgency=medium ## Features, Breaking Changes - `ServerConfig::new` returns a `Result`, fails if `password` doesn't match `method`'s requirements - `ConnectOpts::bind_local_addr` supports binding to a specific port - Uses `async` in trait, bump MSRV to v1.75 - #1790 `outbound_udp_allow_fragmentation` new option for allowing UDP outbound sockets to enable IP fragmentation - `tun2` has been merged back to `meh/rust-tun` - #1810 `UdpSocket::bind` - `shadowsocks-rust` binary crate "default" feature set to `full` ## Bug Fixes - Method `none` (`plain`) skips key derivation process. - #1762 Do not crash in `ServerConfig::from_url()` on unknown method - #1759 Flush `local-tun` tcp writer half before close - #1765 Disallow HTTP/SOCKS4a in `socks` protocol handler when authentication is required - `ConnectOpts`'s per-server options should not be shared globally - #1814 `local-dns` upstream udp packet buffer size 256 ## Miscellaneous - Make cryptographic dependencies optional in default build of `shadowsocks` crate. shadowsocks-rust (1.21.2) unstable; urgency=medium ## Bug Fixes - #1730 `local-http`: HTTP Client removes Authority from Request URI only for HTTP/1.x shadowsocks-rust (1.21.1) unstable; urgency=medium ## Bug Fixes - #1730 `local-http`: The URI field in HTTP Request sent from `sslocal` should only contain path and query. ## Miscellaneous - #1702 Debian package build removes dependency of `pwgen` shadowsocks-rust (1.21.0) unstable; urgency=medium ## Features - #1641 `shadowsocks`: `ProxySocket` supports generic I/O socket type - #1567 `shadowsocks-service`: Support OpenBSD Packet-Filter (pf) shadowsocks-rust (1.20.4) unstable; urgency=medium ## Features - #1616 `local`: Allow configuring SOCKS5 `UDP_ASSOCIATE` address - #1607 Published in MacPorts: https://ports.macports.org/port/shadowsocks-rust/ - #1613 `ProxyServerStream::from_stream` made public ## Bug Fixes - #1612 `server`: Properly exit server instance if any of the sub-tasks exited shadowsocks-rust (1.20.3) unstable; urgency=medium ## Features - `local`: Ping Balancer scores replaced standard deviation with median absolute deviation, which should help focusing less on outlying observations in latency samples. ## Bug Fixes - #1589 `local-tun`: Removes linking to [`SetInterfaceDnsSettings`](https://learn.microsoft.com/en-us/windows/win32/api/netioapi/nf-netioapi-setinterfacednssettings) on Windows shadowsocks-rust (1.20.2) unstable; urgency=medium ## Features - #1560 PingBalancer check Firefox portal allowing `200` HTTP status shadowsocks-rust (1.20.1) unstable; urgency=medium ## Bug Fixes - `local-online-config`: SIP008 auto reload configuration task will add online servers without replacing the existed ones. This bug will eventually cause `sslocal` consumes too many memories and get OOM killed. Users are encourage to update to this version if using 1.19.4 to 1.20.0. ## Features - `shadowsocks-service`: Updated [`rustls`](https://crates.io/crates/rustls) to v0.23 with [`ring`](https://crates.io/crates/ring) backend. - `local-redir`, `server`: Better approach to check current platform IP stack capabilities like Go (IPv4, IPv6, IPv4-mapped-IPv6 supports). - Explicitly enable dual-stack if listen addresses (`server`, `local_address`) are IPv4-mapped-IPv6, by setting `IPV6_V6ONLY=0`. shadowsocks-rust (1.20.0) unstable; urgency=medium ## Breaking Changes - #887 shadowsocks stream cipher (`TABLE`) doesn't need to make a derived key instead of using user's predefined key directly. This change will make shadowsocks-rust not going to be compatible with its older version. Users who are using `TABLE` cipher should upgrade all your local and server instances to the latest version of shadowsocks-rust. On the other hand, `TABLE` cipher is marked deprecated because it is vulnerable, users **must** migrate to other more secured methods immediately. shadowsocks-rust (1.19.4) unstable; urgency=medium ## Features - `local-online-config`: Making HTTP requests with `local-http`'s HttpClient implementation, mainly for supporting `outbound_*` socket configurations. ## Miscellaneous - Fixed build failures on some platforms. shadowsocks-rust (1.19.3) unstable; urgency=medium ## Breaking Changes - Feature `dns-over-h3` moved from feature `full` to `full-extra`. DNS over H3 is still an experimental feature. - `local-fake-dns`: Disabled compression (zstd), which seems to be deprecated by [`sled`](https://crates.io/crates/sled). ## Features - `local-online-config`: Set 30s timeout for update HTTP requests. shadowsocks-rust (1.19.2) unstable; urgency=medium ## Bug Fixes - `local-tun`: `tun2` handles IP packet information automatically. shadowsocks-rust (1.19.1) unstable; urgency=medium ## Features - Rollback `rustls` to v0.22, v0.23 first introduced `aws-lc` as the default crypto implementation, but it cannot be built on some targets if there are still older versions of `rustls` in the dependency tree. - `local-tun`: Switch from `tun` to `tun2`, which is a fork of `tun`. `tun` seems to be abandoned. ## Bug Fixes - #1539 `local-fake-dns`: Query Response Message has to include the original Query and flags. shadowsocks-rust (1.19.0) unstable; urgency=medium ## Features - #302 `sslocal` support SIP008 Online Configuration. Pull `servers` from remote servers automatically. (Experimental) - Add `basic`, `full`, `full-extra` features makes building command line arguments shorter ## Bug Fixes - #1525 Check `"users"` in server configuration if `method` doesn't support AEAD-2022 EIH. - #1528 Fixed FreeBSD build. ## Miscellaneous - Snap: Add alias names like `sslocal`, `ssserver`, ... - `local-tun` feature could be enabled even if target platform is not supported. ## BREAKING - Minimal Supported Rust Version (MSRV) is v1.74 shadowsocks-rust (1.18.4) unstable; urgency=medium ## Features - #1495 Binaries support `--plugin-mode` command line argument - `local-tun` is enabled by default for Windows targets in CI builds ## Bug Fixes - #1516 `local-dns` UDP client support AEAD-2022 protocol properly shadowsocks-rust (1.18.3) unstable; urgency=medium ## Features - #1466 Support `outbound_fwmark` in server side to split outbound tunnel - #1467 Default build for `*-windows-*` targets includes `sswinservice` - `local-fakedns`: Add a basic implementation of Fake-DNS, which will allocate IPs from pool for DNS queries. This experimental feature could be useful when using `local-tun`, `local-redir` or other features that could only receive IP destinations, the domain name that is resolved by the Fake-DNS will be translated from IP back to domain name when connecting to the remote. - #1500 Add `launchd_udp_socket_name`, `launchd_tcp_socket_name` to basic config format ## Bug Fixes - Fixed build on OpenBSD - #1491 Fixed per-server outbound options not taking effect - #1509 `local-tun` TCP socket creation made non-blocking shadowsocks-rust (1.18.2) unstable; urgency=medium ## Features - `local-tun`: Support `tun_interface_destination` configuration key ## Bug Fixes - `local`: macOS launch activate sockets set non-blocking shadowsocks-rust (1.18.1) unstable; urgency=medium ## Features - Default logging framework changed to [`tracing-subscriber`](https://crates.io/crates/tracing-subscriber), which: - Support libraries that log with both [`tracing`](https://crates.io/crates/tracing), and [`log`](https://crates.io/crates/log). - NOTE: `--log-config` parameter will apply only to [`log4rs`](https://crates.io/crates/log4rs), which doesn't support the `tracing` framework. ## Bug Fixes - #1425 Enable `EDNS(0)` by default for hickory-dns resolver. ## NOTE - [`clap`](https://crates.io/crates/clap) upgraded MSRV (Minimal Supported Rust Version) to v1.74 since v4.5.0. This project will have to stay in v4.4 until the next major release. -- ty Sun, 18 Feb 2024 22:05:00 +0800 shadowsocks-rust (1.18.0) unstable; urgency=medium Mostly identical to v1.17.2, except that: - Minimal Supported Rust Version (MSRV) upgraded from v1.64 to v1.71 - #1259 Fixed Snapcraft build. `base` changed to `core22`, auto-build architecture changed to [`arm64`, `amd64`, `armhf`] - #1426 MIPS targets removed from release build, because MIPS targets are now downgraded to TIER 3 -- ty Thu, 08 Feb 2024 00:00:00 +0800 shadowsocks-rust (1.17.2) unstable; urgency=medium ## Features - `local`: `socks` local server will support SOCKS5, SOCKS4a, HTTP proxy protocols when `local-http`, `local-socks4` features are enabled - `local`: Support setting `udp_mtu` in configuration file to actively reject `packet.size > MTU` ## Bug Fixes - #1378 dns-over-tls/https with rustls add dependencies to certs - #1381 Set the incoming socket buffer sizes properly on the listen socket - #1414 TUN synchronize SYN packet and Socket creation shadowsocks-rust (1.17.1) unstable; urgency=medium ## Features - #1330 `local`: Support macOS launch activate socket (https://developer.apple.com/documentation/xpc/1505523-launch_activate_socket) - #1357 `local`: Upgrade hyper (https://crates.io/crates/hyper) to v1.0 ## Bug Fixes - #1328 `run_as_user` aborts if any error occurs ## Miscellaneous - Minor improvements for `local-tun` on Windows - Upgrade `shadowsocks-crypto` that supports `sm4-gcm`, `sm4-ccm` non-standard AEAD ciphers shadowsocks-rust (1.17.0) unstable; urgency=medium ## Features - Trust-DNS is rebranded to Hickory-DNS https://github.com/hickory-dns/hickory-dns/releases/tag/v0.24.0 - Experimental: Support DNS-over-H3 (Try with configuration `"dns": "google_h3"` and compile with feature `"dns-over-h3"`) - #1319 Allow configuring `local-dns` client cache size - Experimental: `local-tun` supports Windows with [Wintun](https://www.wintun.net/) shadowsocks-rust (1.16.2) unstable; urgency=medium ## Features - `ssurl`: #1287 Support SIP008 links - `ssserver`: #1293 Disable UDP dual-stack outbound socket when IPv6 is not supported - `sswinservice`: #1292 Support Windows Service shadowsocks-rust (1.16.1) unstable; urgency=medium ## Bug Fixes - #1285 [Regression fix] local DNS uses mode `tcp_and_udp` by default shadowsocks-rust (1.16.0) unstable; urgency=medium ## Features - `local-redir`: #1159 Linux Redirect (TCP) supports dual-stack listener - #1156 Support Multipath-TCP - DNS resolver (with `trust-dns` enabled) support outbound socket configurations, like `outbound-fwmark`, `outbound-bind-addr`, ... - #1127 Support SIP003u, UDP plugins - #1185 Support creating servers with builder pattern to allow users to retrieve the actual listening address of the server listeners - #1204 Support reading default configuration files `local.json`, `server.json` and `manager.json` - #1229 Support configuring DNS cache size with `--dns-cache-size` in command line options and `dns_cache_size` in configuration file - #1266 Support Network Adapters' `FriendlyName` on Windows in `outbound_bind_interface` ## Bug Fixes - #1239 Fixed misaligned read in shadowsocks' socks5 protocol implementation. It may cause panics compiled by rustc newer than 1.68. - #1234 PingBalancer shouldn't check TCP mode by default - #1221 Compatible with Linux Kernels that doesn't support `IP6T_SO_ORIGINAL_DST` - #1254 Fixed Tree-Rule detector for REGEX rules that ends with `$` ## Miscellaneous - Docker: #1149 Changed binary path to `/usr/bin` from `/usr/local/bin` preventing being overwritten by K8S mount - Snap: Add `network-control` plug for `tun` protocol -- ty Sat, 27 Aug 2023 00:20:00 shadowsocks-rust (1.15.4) unstable; urgency=medium ## Bug Fixed - #1239 Fixed misaligned read in shadowsocks' socks5 protocol implementation. It may cause panics compiled by rustc newer than 1.68. shadowsocks-rust (1.15.3) unstable; urgency=medium ## Features - local-tun: Support `tun_interface_destination` for configuring Tun device's destination address - Support `outbound_fwmark`, `outbound_user_cookie`, `outbound_bind_interface` and `outbound_bind_addr` in configuration file ## Bug Fixed - local-tun: #1138 Fixed TCP state management - local-redir: #988 UDP compatible with Linux < 2.6.37 (without `IPV6_TRANSPARENT`) - manager: #1101 Set missing `ipv6_first` for servers ## Miscellaneous - Snap: #1088 Disable Snap daemon by default shadowsocks-rust (1.15.2) unstable; urgency=medium ## Bug Fixes - #1060 ACL supports checking IPv4-mapped-IPv6 addresses with IPv4 rules ## Miscellaneous - Code style and potential bug fixes with clippy check shadowsocks-rust (1.15.0) unstable; urgency=medium ## Features - #811 AEAD-2022 protocol ([SIP022](https://github.com/shadowsocks/shadowsocks-org/issues/196)) - WARN: This is still a draft protocol, use it at your own risk. - SIP002 Extended Format: Allowing unencoded user-info in URL, https://github.com/shadowsocks/shadowsocks-org/issues/27#issuecomment-1124853747 - #810 Manager standalone mode support bypassing ACL files - #818 Allow `sslocal` run without any `servers`, which will bypass all connections and packets - #838 `"password"` is optional for `none` / `plain` method - redir-local: Enable dual-stack support on Linux (TProxy) and FreeBSD - Disable `md5-asm` and `sha1-asm`: https://github.com/shadowsocks/shadowsocks-crypto/issues/16 - `"acl"` and `"outbound_fwmark"` are available in configuration file ## Miscellaneous - shadowsocks/shadowsocks-org#204 Remove `security-iv-printable-prefix` experimental feature - Upgrade [clap](https://crates.io/crates/clap) to v4.0. - UDP association channel size shrunk to 1024, which could save a lot of memory for each associations ## Enhancements - #855 Properly handle IPv4-mapped-IPv6 addresses in UDP associations - `ssserver` always convert IPv4-mapped-IPv6 addresses to IPv4 in UDP respond target addresses - `sslocal` - `tun`, `socks5` always convert IPv4-mapped-IPv6 addresses to IPv4 - `redir` always use IPv6 sockets for sending back packets shadowsocks-rust (1.14.3) unstable; urgency=medium ## Features - Automatically bump `RLIMIT_NOFILE` on Unix (except Android) - https://github.com/golang/go/issues/46279 - http://0pointer.net/blog/file-descriptor-limits.html shadowsocks-rust (1.14.2) unstable; urgency=medium ## Features - #788 `sslocal` SOCKS5 protocol supports RFC1929 Username/Password Authentication - SECURITY: This is insecured because (a) shadowsocks' SOCKS5 UDP Association doesn't require a dynamic port for each authorized clients (b) Username and passwords are sent in plain text. - RustCrypto/ring-compat#79 HKDF-SHA1 uses [ring](https://crates.io/crates/ring)'s assembly implementation shadowsocks-rust (1.14.1) unstable; urgency=medium ## Miscellaneous - `shadowsocks`, `shadowsocks-service` crates upgraded to Rust Edition 2021. shadowsocks-rust (1.14.0) unstable; urgency=medium ## Features - Optimization: UDP associations management removes unnecessary locks ## Breaking Changes - `shadowsocks_service::local::net::udp::UdpAssociationManager::new` returns clean-up interval and keep-alive receiver. It is not recommended to use this directly in your Project, because the API may change occasionally. shadowsocks-rust (1.13.5) unstable; urgency=medium ## Features - #773 Set environment variable `SS_SYSTEM_DNS_RESOLVER_FORCE_BUILTIN` to use system's builtin DNS resolver shadowsocks-rust (1.13.4) unstable; urgency=medium ## Features - Allow setting `"system"` in DNS configuration key `"dns"` to use system provided DNS API ## BUG Fixes - `ssservice` - fixed command line options when running it as symlink of `ssserver` and `ssmanager` shadowsocks-rust (1.13.3) unstable; urgency=medium ## BUG Fixes - #767 REGRESSION: `ssmanager` missing `--server-host` command line option since v1.13.0 - shadowsocks/shadowsocks-crypto#12 REGRESSION: `rc4-md5` method cipher IV length should be 16 shadowsocks-rust (1.13.2) unstable; urgency=medium ## Features - (EXPERIMENTAL) Support setting `SO_USER_COOKIE` on FreeBSD - Set cookie with `--outbound-user-cookie` command line option, working just like `--outbound-fwmark` on Linux - (EXPERIMENTAL) Local `tun` interface refactored the `VirtDevice::poll` strategy - Improve performance - Still slow comparing to system's network stack ## BUG Fixes - #765 Updated broken Wiki URL for Plugins in command line help message - #764 Regression of client blocking ACL strategy on `ssserver` - Introduced since v1.9.0 shadowsocks-rust (1.13.1) unstable; urgency=medium ## Bug Fixes - `Instant` subtraction may be overflowed in `PingBalancer` - When `sslocal` has set multiple remote servers and the host system just reboots, it will crash. shadowsocks-rust (1.13.0) unstable; urgency=medium ## Features - #706 `balancer.check_best_interval` could let ping balancer to ping only the chosen best server in this interval - Recommended: Set a shorter interval in `balancer.check_best_interval` than `balancer.check_interval` to check much frequently the best server. - `balancer.check_interval` controls the interval of checking all the available servers - When server start, the "check best" strategy starts after it receives enough data for estimating all servers' scores - #744 Refactored `local-tun`, using `smoltcp` as a user-space network stack ## Miscellaneous - Upgrade [`clap`](https://crates.io/crates/clap) (the command-line argument handling library) to v3.0 - #739 Support K8S deployment - [shadowsocks-crypto](https://github.com/shadowsocks/shadowsocks-crypto) switch underlying encryption library to [RustCrypto](https://github.com/RustCrypto) - Able to build with stable Rust - Build for target `aarch64` with nightly, features `"armv8 neon"` should be enabled for hardware acceleration. shadowsocks-rust (1.12.5) unstable; urgency=medium ## Bug Fixes - #725 High CPU consumption on Linux Kernel < 4.11 when TCP Fast Open is enabled. -- ty Fri, 17 Dec 2021 00:13:26 +0800 shadowsocks-rust (1.12.4) unstable; urgency=medium ## Features - Configuration - `ipv6_only` configuration option setting `IPV6_V6ONLY` to all listener sockets that are listening to dual-stack address (`::`) - #700 Default configuration search path also includes `$PWD` - Log and Runtime related options could be configured via configuration file - #698 New binary `ssservice` unified features in (`sslocal`, `ssserver` and `ssmanager`) ## Bug Fixes - #694 UDP binds to dual-stack address (`::`) will detect `0.0.0.0` already in use automatically - Transparent Proxy (redir) local client will always set `IPV6_V6ONLY` for listeners that are listening on `::` ## Miscellaneous - Deprecating `SS_LOG_VERBOSE_LEVEL` and `SS_LOG_WITHOUT_TIME` (introduced in [v1.12.3](https://github.com/shadowsocks/shadowsocks-rust/releases/tag/v1.12.3)) in flavor of configuring in the configuration file -- ty Sun, 28 Nov 2021 15:01:54 +0800 shadowsocks-rust (1.12.3) unstable; urgency=medium ## Features - #688 Support default configuration file path for `sslocal`, `ssserver` and `ssmanager` - Linux: `$XDG_CONFIG_PATH/shadowsocks-rust/config.json` or `$HOME/.config/shadowsocks-rust/config.json` - Windows: `{FOLDERID_RoamingAppData}\shadowsocks\shadowsocks-rust\config\config.json` - macOS: `$HOME/Library/Application Support/org.shadowsocks.shadowsocks-rust/config.json` - #691 Manipulating default logging options (command line options `-vvv` and `--log-without-time`) with environment variable `SS_LOG_VERBOSE_LEVEL` and `SS_LOG_WITHOUT_TIME` - #419 Read servers' password from environment variables - Server created from command line argument without `--password` will try to read it from TTY - Servers' `"password"` field or `--password` option support `${VAR_NAME}` format to read password from environment variable `VAR_NAME` -- ty Fri, 26 Nov 2021 00:12:13 +0800 shadowsocks-rust (1.12.2) unstable; urgency=medium ## BUG Fixes - #683 local-dns command line `--remote-dns-addr` will have default port `53` ## Miscellaneous - Removed direct dependency to [`mio`](https://crates.io/crates/mio), sending file descriptors through UDS now with [`sendfd`](https://crates.io/crates/sendfd). -- ty Tue, 16 Nov 2021 00:11:44 +0800 shadowsocks-rust (1.12.1) unstable; urgency=medium ## Features - #669 ACL regular expression rules will try to convert to `||` (sub-domains) and `|` (exact match) rules. ## Bug Fixes - #674 MIPS targets in pre-built releases binaries will be compressed by `upx` - #670 Servers created by command line options in `ssserver` will have mode `tcp_only` -- ty Tue, 9 Nov 2021 23:27:48 +0800 shadowsocks-rust (1.12.0) unstable; urgency=medium ## Features - TCP connects with Happy Eyeballs (RFC6555, RFC8305) strategy - Local - #586 Basic support of `tun` interface in `sslocal` (Experimental) Tested on macOS and Linux - #620 Local server will choose remote servers based on their `"mode"` - Local Balancer - Configurable `max_server_rtt` and `check_interval` - Reload configuration `"servers"` in runtime when receiving `SIGUSR1` signal - Manager - #421 `ssmanager` support `--plugin` and `--plugin-opts` as default plugin configurations - #648 `ssmanager` support starting `ssserver` in standalone (independent process) mode. - #627 ACL support `|` and `||` hash-set and domain-tree mode - Support `--outbound-bind-interface` on Windows. ## Bug Fixed - #579 UDP server reply target address should be received source address - TFO socket on Windows should bind to `SOCKADDR_IN6` for IPv6 targets - #640 `--daemonize` will set `chdir` to current working directory - [BREAKING] In the previous version `--daemonize` will call `chdir` to `/` by default, so it may change the behavior if users using relative paths in `"plugin"` or `"plugin_opts"` ## Miscellaneous - #596 Support Snapcraft https://snapcraft.io/shadowsocks-rust - TFO on Linux queue length set to 1024 to match backlogs - Completely remove Replay Attack Protection with Ping-Pong bloom filter in default build configuration -- ty Tue, 2 Nov 2021 12:52:17 +0800 shadowsocks-rust (1.11.2) unstable; urgency=medium ## Features - #570 Multi-architecture Docker image for release - Replaced `futures::future::abortable` with `tokio`'s builtin `tokio::task::JoinHandle::abort` - Define binaries' exit code with standard in `sysexits.h` - HTTP local listener supports `TCP_NODELAY`, `SO_KEEPALIVE` and dual-stack ## Bug Fixed - #577 `ssmanager` and `ssserver` command line argument `-u` should overwrite `mode` to be `Mode::UdpOnly` - #566 Exit with error code instead of `panic!` when loading ACL fails - #555 Properly handling `EINPROGRESS` for TFO connect when falling backs - #557 Properly killing UDP associations, which may cause `Future` (memory) leaks ## Security - #556 Remove silent dropping when replay was detected -- ty Sat, 24 July 2021 11:50:00 +0800 shadowsocks-rust (1.11.1) unstable; urgency=medium ## Features - #546 Enable TCP Keep Alive for inbound and outbound sockets - Add a new `keep_alive` key in configuration for configuring keep alive timeout - Default timeout is 15 seconds (like Go's `net` library's default) - #543 Add `disabled` key for local servers in configuration ## Bug Fixed - #490 Try to purge half-open TCP connections when one direction is closed - When one direction is closed, server will set a 5 seconds read timeout on the other half - #542 Allow setting `method` for default encryption method when starting `ssmanager` with configuration - #541 Fixed ACL rules for `ssmanager` -- ty Sun, 6 June 2021 23:16:00 +0800 shadowsocks-rust (1.11.0) unstable; urgency=medium ## Features - Support TFO (TCP Fast Open) on Linux, Windows, macOS (iOS), FreeBSD (https://github.com/shadowsocks/shadowsocks-rust/issues/184) - Support customizing servers' weight for balancer (https://github.com/shadowsocks/shadowsocks-rust/issues/510) -- ty Fri, 14 May 2021 12:31:54 +0800 shadowsocks-rust (1.10.9) unstable; urgency=medium ## Bug Fixes - HTTP Proxy preserves headers' title case. https://github.com/shadowsocks/shadowsocks-rust/discussions/491 , https://github.com/hyperium/hyper/issues/2313 -- ty Fri, 23 Apr 2021 23:58:08 +0800 shadowsocks-rust (1.10.8) unstable; urgency=medium ## Bug Fixes - Removes non-standard AEAD ciphers that have variable nonce length, including - `aes-128-ocb-taglen128`, `aes-192-ocb-taglen128`, `aes-256-ocb-taglen128` - `aes-siv-cmac-256`, `aes-siv-cmac-384`, `aes-siv-cmac-512` -- ty Sun, 18 Apr 2021 21:00:21 +0800 shadowsocks-rust (1.10.7) unstable; urgency=medium ## Features - Support non-standard AEAD ciphers `sm4-gcm` and `sm4-ccm` -- ty Sat, 17 Apr 2021 22:46:39 +0800 shadowsocks-rust (1.10.6) unstable; urgency=medium ## Features - [shadowsocks/shadowsocks-crypto#8](https://github.com/shadowsocks/shadowsocks-crypto/issues/8) Support non-standard AEAD ciphers with `crypto2`, could be enabled by feature `aead-cipher-extra` - `aes-128-ccm`, `aes-256-ccm` - `aes-128-gcm-siv`, `aes-256-gcm-siv` - `aes-128-ocb-taglen128`, `aes-192-ocb-taglen128`, `aes-256-ocb-taglen128` - `aes-siv-cmac-256`, `aes-siv-cmac-384`, `aes-siv-cmac-512` - `xchacha20-ietf-poly1305` ## Bug Fixes - [shadowsocks/shadowsocks-android#2705](https://github.com/shadowsocks/shadowsocks-android/issues/2705) MD5 algorithm bug causes KDF (Key Derived Function) produces wrong key when `LEN(password) % 64 in [50, 64)` -- ty Sat, 17 Apr 2021 21:45:46 +0800 shadowsocks-rust (1.10.5) unstable; urgency=medium ## BUG Fixed - `ProxyClientStream` should keep the concatenated first packet buffer alive before asynchronous `write()` finishes -- ty Sat, 10 Apr 2021 09:07:52 +0800 shadowsocks-rust (1.10.4) unstable; urgency=medium # Fixed BUG - `ProxyClientStream::poll_write` may lose the `Address` in the packet to be sent if socket returns `EAGAIN` # Features - Support `protocol` in basic configuration format -- ty Fri, 9 Apr 2021 17:25:04 +0800 shadowsocks-rust (1.10.3) unstable; urgency=medium ## BUG Fixed - #472 Fixed `SO_INCOMING_CPU` when building on some Linux targets. rust-lang/socket2#213 -- ty Wed, 7 Apr 2021 09:55:40 +0800 shadowsocks-rust (1.10.2) unstable; urgency=medium ## BUG Fixed - `mode` in basic configuration format doesn't work for local instance -- ty Sun, 28 Mar 2021 11:13:01 +0800 shadowsocks-rust (1.10.1) unstable; urgency=medium ## BUG Fixed - #469 Compilation error on Android ## Miscellaneous - `sslocal` checks new local instance's parameters dependency - `--protocol`, `--forward-addr`, ... will require `--local-addr` to be specified -- ty Sat, 27 Mar 2021 00:13:00 +0800 shadowsocks-rust (1.10.0) unstable; urgency=medium ## Features - #452 `sslocal` supports starting multiple instances in the same process - Add `locals` in extended configuration format for specifying multiple local server instances - (Android Only) Support `unix://` schema in `dns` configuration - Support `tcp://` and `udp://` in `dns`configuration for setting DNS protocol. Uses both TCP and UDP if not specified. - Support `quad9_https` predefined DNS servers - Updated `shadowsocks-crypto` to `v0.2`, which `Cipher` implementation uses `enum` static dispatch instead of `Box`ed Trait Object for dynamic dispatch ## BUG Fixes - PingBalancer 2nd check will be sent 10s after 1st initialization check. ## Breaking Changes - `sslocal`'s command line options are now for creating a new local instance: - `--local-addr`, `--forward-addr`, `-U`, `-u`, `--protocol`, ... will only applied to the local instance specified by `--local-addr` - `ssserver`'s command line options are now for creating a new server instance: - `-U` and `-u` will only applied to the local instance specified by `--server-addr` -- ty Thu, 25 Mar 2021 18:10:00 +0800 shadowsocks-rust (1.9.2) unstable; urgency=medium ## Features * #442 Check repeated salt after first successful decryption ## BUG Fixes * Redir: setting SO_REUSEPORT, SO_MARK for UDP send-back sockets -- ty Fri, 6 Mar 2021 01:15:00 +0800 shadowsocks-rust (1.9.1) unstable; urgency=medium ## BUG Fixes * #431 UdpSocket::from_std requires sockets to be non-blocked. ## Features * Removed avx from the default CPU features -- ty Fri, 26 Feb 2021 19:01:06 +0800 shadowsocks-rust (1.9.0) unstable; urgency=medium Complete refactored the whole implementation and splits into 3 different crates: * shadowsocks - Core feature of shadowsocks * shadowsocks-service - Service library for implementing Local Server, Remote Server, Manager Server * shadowsocks-rust - Binary crate for release Replaced libsodium and libcrypto with [crypto2](https://github.com/shadowsocks/crypto2). ## Features * Support setting SO_MARK, SO_BINDTODEVICE on Linux * Support setting SO_SNDBUF and SO_RCVBUF for TCP sockets * Support [SIP008](https://github.com/shadowsocks/shadowsocks-org/issues/89 "Online config") extend server fields server, server_port, remarks * Local DNS Relay * Support sending TCP and UDP queries simultaneously * Support connection reusability * Remove mostly TCP timeout setting for tunnels, connections will only be killed if clients or servers close * Auto-reload DNS resolver configuration from /etc/resolv.conf on *NIX platforms. * [#379](https://github.com/shadowsocks/shadowsocks-rust/issues/379 "希望通过传递参数方式,指定多线程模式下tokio启动的线程数") Allow customizing number of worker-threads for multi-threaded scheduler. * [#401](https://github.com/shadowsocks/shadowsocks-rust/issues/401 "Lazy server disable implementation") Support field disabled in extended server configuration * Ping Balancer * Treat timeouts as failures, so requests that receive no response count as failures. * Increase check timeout from 2s to 5s to avoid penalties on slow servers. * Increase check interval from 6s to 10s. * `--outbound-bind-interface` is now supported in both Linux and macOS * [#352](https://github.com/shadowsocks/shadowsocks-rust/issues/352 "Add command line arguments to control incoming/outgoing send/receive socket OS buffer size") Support customizing inbound and outbound sockets' SO_SNDBUF and SO_RCVBUF by command line options ## Library Update * [tokio v1.0](https://tokio.rs/blog/2020-12-tokio-1-0) * [shadowsocks-crypto](https://github.com/shadowsocks/shadowsocks-crypto), [crypto2](https://github.com/shadowsocks/crypto2) ## Optimization * UDP Relays sending respond packets directly to UdpSocket instead of channel, which will significantly improve respond latency * [#408](https://github.com/shadowsocks/shadowsocks-rust/issues/408 "using crate spin without feature "std" causes performance problem") Enable std features for the spin crate to enable yielding threads when spinning on waiting. ## BUG Fixes * For BSD systems, set IPV6_BINDANY and SO_BINDANY on SOL_SOCKET properly * `trust-dns-resolver` requires explicit enables feature `dns-over-https-rustls` for DoH [#367](https://github.com/shadowsocks/shadowsocks-rust/issues/367 "Compile error on latest `master` branch while enabling `dns-over-tls` & `dns-over-https`") * ACL domain rules should be case insensitive. Domain names are case insensitive. * [shadowsocks/shadowsocks-android#2667](https://github.com/shadowsocks/shadowsocks-android/issues/2667 "Service is down intermittently") set timeout for protect() call to Android's VpnService ## Miscellaneous * Disable HTTPS outbound connection for local HTTP proxy by default. For most use cases, HTTPS should be proxied with CONNECT method. * Unified UDP relay association implementation for less duplicated code. * Deprecated `single-threaded` build feature, replaced by `multi-threaded`. * Disable stream ciphers by default. Could be enabled with feature `stream-cipher`. * Enable IPv6 dual stack mode by default when listening on `::`. -- ty Mon, 22 Feb 2021 09:28:28 +0800 shadowsocks-rust (1.8.23) unstable; urgency=medium ## BUG Fixed * Fixed REDIR client setsockopt options, IPv6 should use IPV6_TRANSPARENT on level SOL_IPV6 or IPPROTO_IPV6 -- ty Tue, 3 Nov 2020 01:17:47 +0800 shadowsocks-rust (1.8.22) unstable; urgency=medium ## Features * Load balancer uses Firefox's network detection address: http://detectportal.firefox.com/success.txt * The original http://dl.google.com/generate_204 is not always available all over the world ## BUG Fixed * ARMv6 release target (arm-unknown-linux-gnueabihf) shouldn't enable output AES instructions * Moves many connection ERROR logs to DEBUG level -- ty Mon, 2 Nov 2020 01:37:24 +0800 shadowsocks-rust (1.8.21) unstable; urgency=medium ## Features * Support [SIP008](https://github.com/shadowsocks/shadowsocks-org/issues/89 "Online config") multi-server configuration keys: `server`, `server_port` and `remarks`: { "servers": [ { "server": "your.shadowsocks.server", "server_port": 8388, "method": "aes-256-gcm", "password": "password", "remarks": "My Shadowsocks Server" } ] } * [#308](https://github.com/shadowsocks/shadowsocks-rust/issues/308 "没有后台运行的吗?") Supports daemonize with command line option (`-d`, `--daemonize`) on *nix platforms * Switched logging facility to [log4rs](https://crates.io/crates/log4rs) for more extensible configurations ## BUG Fixed * [#284](https://github.com/shadowsocks/shadowsocks-rust/issues/284 "ssurl is broken") Fixed conflicts in ssurl command line options * [#309](https://github.com/shadowsocks/shadowsocks-rust/issues/309 "端口占用造成插件退出") Fixed mode in add command of ssmanager * [#303](https://github.com/shadowsocks/shadowsocks-rust/issues/303 "sslocal tries to connect to servers even when network is not yet online") Lower proxy connection error messages to DEBUG level * Call sleep() if server accept() failed -- ty Mon, 19 Oct 2020 09:38:47 +0800 shadowsocks-rust (1.8.20) unstable; urgency=medium ## Features * Updated various dependencies to their latest release * Lazy creating bypassed and proxied UDP associations in ACL mode * Each UDP associations that running in ACL mode would create 2 file descriptors (or HANDLEs) (one for bypassed, the other for proxied) when constructing in older version * UDP associations in ssserver will try to return domain name addresses when receives packets from remotes that were requested with domain name address targets. ## BUG Fixed * UDP associations in sslocal handled bypassed requests incorrectly, which would try to parse response packets in shadowsocks' server protocol -- ty Wed, 14 Oct 2020 00:46:08 +0800 shadowsocks-rust (1.8.19) unstable; urgency=medium ## Features * Plugin configurations in files have a new optional field plugin_args for passing command line arguments when plugin starts { "plugin": "your_plugin", "plugin_args": [ "-p", "arg1" ] } * increase_nonce function for AEAD ciphers is optimized if sodium feature is disabled. * Add arm-unknown-linux-musleabi target in releases * Optimized EncryptWriter by reusing decrypting buffers -- ty Sun, 11 Oct 2020 16:34:58 +0800 shadowsocks-rust (1.8.18) unstable; urgency=medium ## BUG Fixed * [#294](https://github.com/shadowsocks/shadowsocks-rust/pull/294 "") UDP relay server's associations shouldn't bind to local address, which will eventually cause EADDRINUSE -- ty Tue, 15 Sep 2020 10:11:43 +0800 shadowsocks-rust (1.8.17) unstable; urgency=medium ## BUG Fixed * [#292](https://github.com/shadowsocks/shadowsocks-rust/pull/292) Hold the TCP connection if it failed to decrypt the first packet for preventing active probing. * [#293](https://github.com/shadowsocks/shadowsocks-rust/pull/293) Keep server running if it fails to create UDP associations. -- ty Tue, 8 Sep 2020 23:31:20 +0800 shadowsocks-rust (1.8.16) unstable; urgency=medium ## Features * [#290](https://github.com/shadowsocks/shadowsocks-rust/pull/290) UDP's ServerClient support split() into ReadHalf and WriteHalf ## BUG Fixed * [#289](https://github.com/shadowsocks/shadowsocks-rust/pull/289) Fixed UDP's ServerClient data decryption -- ty Thu, 20 Aug 2020 17:11:01 +0800 shadowsocks-rust (1.8.15) unstable; urgency=medium Code base are exactly the same as v1.8.14. ## Bug Fixed * `x86_64-unknown-linux-gnu` release should be built by cross with GLIBC_2.15 * `x86_64-apple-darwin` release built with invalid format sslocal (still don't know why) -- ty Mon, 10 Aug 2020 01:12:54 +0800 shadowsocks-rust (1.8.14) unstable; urgency=medium ## Features * Support customizing memory allocator by features: tcmalloc, mimalloc, jemalloc ## BUG Fixed * [#273](https://github.com/shadowsocks/shadowsocks-rust/issues/273) Use AtomicUsize for maximum compatibility in flow statistics * [#285](https://github.com/shadowsocks/shadowsocks-rust/issues/285) Fixed binaries command line options issue causing by conflicts_with -- ty Sun, 9 Aug 2020 01:06:49 +0800 shadowsocks-rust (1.8.13) unstable; urgency=medium ## Features * Direct send data for none ciphers, prevent unnecessary data copies * Feature jemalloc for enabling jemalloc allocator (use system's default allocator by default) * [#272](https://github.com/shadowsocks/shadowsocks-rust/issues/272) Support customizing manager created server's bind address ## BUG Fixed * Client flow reports tx and rx are swapped * AEAD TCP protocol must check the reserved higher 2 bits -- ty Sun, 19 Jul 2020 12:17:48 +0800 shadowsocks-rust (1.8.12) unstable; urgency=medium ## Features * [#260](https://github.com/shadowsocks/shadowsocks-rust/issues/260) sslocal supports https protocol (HTTP Proxy over TLS) * [#263](https://github.com/shadowsocks/shadowsocks-rust/issues/263) UDP Associations connect() to proxies' IP to avoid re-resolving domain names for every packets * [#233](https://github.com/shadowsocks/shadowsocks-rust/issues/233) sslocal supports socks4 protocol (SOCKS4/4a) * Options for LRU cache in UDP relay: * udp_timeout: UDP Association will be kept up to this duration (in seconds) * udp_max_associations: Maximum number of UDP Associations will be kept simultaneously ## BUG Fixed * Removed unnecessary UDP socket wake ups * Expired Associations will be cleaned by a separated task ## BREAKING Changes * Manager's configurations are now wrapped into ManagerConfig * timeout field in Config is removed inflavored timeout in ServerConfig * DNS resolving timeout is using the default configuration (5 seconds for most cases) * Bypassing TCP streams won't timeout -- ty Mon, 1 Jun 2020 23:48:55 +0800 shadowsocks-rust (1.8.11) unstable; urgency=medium ## Features * [#232](https://github.com/shadowsocks/shadowsocks-rust/issues/232) Send data along with handshake (LOCAL -> REMOTE) * HTTP server supports https target with both native-tls and rustls * For rustls, https connections will try to negotiate h2 with ALPN * shadowsocks/shadowsocks-org#161 Support none as dummy cipher's name * Adding local-tunnel feature for controlling tunnel protocol * [#252](https://github.com/shadowsocks/shadowsocks-rust/issues/252) Support udp_max_associations configuration option * Various updates for local-dns-relay for Android integration ## Fixed BUGs * [#234](https://github.com/shadowsocks/shadowsocks-rust/issues/234) Ensure plugin subprocesses are killed when server is exited * On *NIX platform, SIGTERM is sent to plugins for graceful exit * [#237](https://github.com/shadowsocks/shadowsocks-rust/issues/237) Increase regex memory limit for ACL host rules * [#240](https://github.com/shadowsocks/shadowsocks-rust/issues/240) Wait for 10 seconds for plugins to start * ssserver should start plugins with PluginMode::Server ## BREAKING Changes * Removed Runtime's Handle for all run entry functions -- ty Sat, 16 May 2020 00:20:45 +0800 shadowsocks-rust (1.8.10) unstable; urgency=medium ## Features * Support ACL configuration * Examples could be found in [shadowsocks/shadowsocks-libev](https://github.com/shadowsocks/shadowsocks-libev/tree/master/acl) * sslocal supports transparent proxy protocol (experimental) * TCP * Linux: iptables with REDIRECT or TPROXY rules * macOS: pf * FreeBSD: pf or ipfw, not tested * OpenBSD: pf, not tested * UDP * Linux: iptables with TPROXY rules * FreeBSD/OpenBSD: pf, not tested * Usage: Run sslocal with --protocol redir * Better command line option verifications ## Fixed BUGs * sslocal with HTTP protocol clears [Hop-by-Hop headers](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers) * CryptoStream is now thread safe * [#222](https://github.com/shadowsocks/shadowsocks-rust/issues/222) rc4 cipher is now working ## Miscellaneous * Integrate into the Android's client implementation, [shadowsocks/shadowsocks-android#2452](https://github.com/shadowsocks/shadowsocks-android/issues/2452) * Not finished yet, you shouldn't use them in production environment * Abort on `panic!` for release builds * [#223](https://github.com/shadowsocks/shadowsocks-rust/issues/223) `--log-without-time` command line option is added back * [#205](https://github.com/shadowsocks/shadowsocks-rust/issues/205) `-6` command line option to resolve host names to IPv6 addresses first ## BREAKING Changes * Merged sstunnel and ssredir into sslocal * DNS-over-HTTPS and DNS-over-TLS are disabled by default, could be enabled by features dns-over-https and dns-over-tls * [#217](https://github.com/shadowsocks/shadowsocks-rust/issues/217) Logging output uses local datetime instead of UTC * Logging output is now in customized format -- ty Fri, 10 Apr 2020 19:39:14 +0800 shadowsocks-rust (1.8.9) unstable; urgency=medium ## Features * ssmanager - Supports Manage Multiple Users APIs * Create / Remove servers in the same tokio runtime dynamically * Fallback to tokio's builtin DNS resolver (currently it is libstd's builtin) if trust-dns's resolver initialize failed ## Fixed BUGs * Ping tasks will panic if remote servers fail to connect for the first time -- ty Thu, 13 Feb 2020 01:13:07 +0800 shadowsocks-rust (1.8.8) unstable; urgency=medium ## Features * ssredir - (Experimental) Transparent Proxy. Currently only supports the following platforms: * Linux - TCP: REDIRECT and TPROXY, UDP: TPROXY * FreeBSD - TCP, UDP: ipfw ## BUG Fixed * Enable TCP_NODELAY for better handshaking performance, for * sslocal's socks5 protocol handshaking * Local and Remote server shadowsocks' IV/nonce exchanging * Ensure plugins starts before listening for sslocal * Eliminated those connection failures while sslocal server just started * [#191](https://github.com/shadowsocks/shadowsocks-rust/issues/191) Skip IV/nonce duplication check for plain cipher ## Miscellaneous * Nightly builds on CircleCI: https://circleci.com/gh/shadowsocks/shadowsocks-rust * Obtain release binaries in #Artifacts, for example: * https://circleci.com/gh/shadowsocks/shadowsocks-rust/151#artifacts/containers/0 -- ty Thu, 6 Feb 2020 20:14:57 +0800 shadowsocks-rust (1.8.7) unstable; urgency=medium ## Features * Set RLIMIT_NOFILE on *nix systems by * -r, --nofile command line argument * nofile key in configuration file ## BUG Fixed * ssserver shouldn't use local_port in configuration to bind() before connect() or sendto() * Command line argument --bind-addr or -b should only accept IP or Domain -- ty Mon, 13 Jan 2020 10:45:54 +0800 shadowsocks-rust (1.8.6) unstable; urgency=medium Basically the same as v1.8.5, but prints the actual error while handshaking with clients. Useful if server received a repeated IV and salt (probably replay attacks). -- ty Sun, 12 Jan 2020 09:44:18 +0800 shadowsocks-rust (1.8.5) unstable; urgency=medium ## Features * Add feature trust-dns to allow disable depending on [trust-dns-resolver](https://crates.io/crates/trust-dns-resolver) * Disabling trust-dns would significantly shrink the size of binaries * [#26](https://github.com/shadowsocks/shadowsocks-rust/issues/26) UDP servers will also bind() to local_address and local_port * Check repeated IV / Salt for defending against replay attacks * [Defend against replay attack](https://github.com/shadowsocks/shadowsocks-org/issues/44) -- ty Sun, 12 Jan 2020 00:09:18 +0800 shadowsocks-rust (1.8.4) unstable; urgency=medium ## Features * ssserver supports bind before connect to remote addresses. Can be configured by * local_address and local_port in config.json * -b or --bind-address in command line parameter * Suggestion: Port should be set to 0 otherwise you will get EADDRINUSE ## Breaking Changes * ssserver won't ignore local_address and local_port in config.json -- ty Thu, 9 Jan 2020 23:35:59 +0800 shadowsocks-rust (1.8.3) unstable; urgency=medium ## Enhancements * Refactored PingBalancer for supporting customized Server Configuration structure * For Example: HTTP sslocal can stores HttpClients into the ServerScore structure instead of putting them into a HashMap. * Removed trust-dns feature gate, set as default. -- ty Wed, 8 Jan 2020 13:42:45 +0800 shadowsocks-rust (1.8.2) unstable; urgency=medium ## Enhancements * Refactored PingBalancer for supporting customized Server Configuration structure * For Example: HTTP sslocal can stores HttpClients into the ServerScore structure instead of putting them into a HashMap. * Removed trust-dns feature gate, set as default. -- ty Tue, 7 Jan 2020 09:16:50 +0800 shadowsocks-rust (1.8.1) unstable; urgency=medium ## BUG Fixed * Send crypto IV (Stream Ciphers) / Nonce (AEAD Ciphers) with the first payload in one packet. * Reduced 1 RTT while handshaking with servers * HTTP Proxy client Handles IPv6 URI host properly * RFC 2732 -- ty Sun, 5 Jan 2020 16:40:19 +0800 shadowsocks-rust (1.8.0) unstable; urgency=medium ## Features * A new binary `sstunnel`. Establish TCP and UDP tunnels to remote. Discussion: #177 ``` # Establish an UDP tunnel to 8.8.8.8:53 (just like what ssdns did in the past) sstunnel -c config.json -f '8.8.8.8:53' -u ``` * Uses `async/await` syntax (requires `rustc` version >= `v1.40.0`) * Dependencies * `tokio` - `v0.2` * `trust-dns-resolver` - `v0.18` * `libsodium-sys` (switched from `libsodium-ffi` for better build process) * Ping balancer * Calculate scores not only with servers' latency, but also availability * Supports UDP relay * Retry 3 times if it connects failed to remote proxy server automatically ## Bug Resolved * Refactored UDP relay. Now it works just like NAT. Discussion: #168 * Temporary workaround for UdpSocket `WSAECONNRESET`. Discussion: #179 * Ref: https://stackoverflow.com/questions/30749423/is-winsock-error-10054-wsaeconnreset-normal-with-udp-to-from-localhost ## Breaking Changes * Removed `ssdns`. `sstunnel` can fulfill its job. ## Releases * `shadowsocks-v1.8.0-stable.x86_64-unknown-linux-musl.tar.xz` * SHA256 `5ec41d5a306715e455b1012de0ddaa33273970689b6df48ffbb0da5fb6083531` * `shadowsocks-v1.8.0-stable.x86_64-pc-windows-gnu.zip` * SHA256 `f7e23a145ca42a0ce73349263650256c9cc3e05caf637c2396699d72801d6966` -- ty Sat, 28 Dec 2019 00:00:00 +0800 shadowsocks-rust (1.7.0) unstable; urgency=medium ## Refactors * #141 Build with Rust 2018. * #100 Migrated to Tokio Runtime. * #139 Refactor for using as a library. Move signal monitor outside of shadowsocks library. ## Dependencies * Replaced `ToSocketAddrs` with `trust-dns` * #111 Upgrade rand to v0.5 and use `ThreadRng` * #132 Feature gate RC4 cipher * `--feature miscreant` is now can be built with stable. ## Configurations * Support timeout key in the outer object in configuration ( `{ "timeout": 30 }` ) * UDP relay sets timeout with separated key `udp_timeout` * #123 `set_nodelay` and `set_keepalive`, `no_delay` is configurable in configuration * [Breaking] Replace `enable_udp` with `mode`, possible values are: `tcp_and_udp`, `tcp_only`, `udp_only`. ## Bugfix * [BUG-FIXED] #105 Fixed "Too many open files" in UDP relay. * [BUG-FIXED] Fixed bug while starting UDP relay. While starting server with plugins, it should not change the listening addresses for UDP relay, which are only for TCP relay. * [BUG-FIXED] #106 Server should not panic if accepted socket closed right after `accept()`. * Implemented a new `ssdns` server, which can serve as a DNS server and proxy DNS queries via ShadowSocks' UDP relay. * [FIXED-BUG] #118 #122 Fixed DNS resolving issue. It may failed to resolve remote server's address if you haven't configured any IP addresses in forbidden_ip section. ## New features * Uses `impl Trait` for functions * #113 Supported `xchacha20-ietf-poly1305` encrypt method * Removed all global states in client and servers, which will allow starting multiple ShadowSocks instances in one process. * Uses `json5` to parse config file. * #85 Support `ss-manager` report protocol. (Can co-operate with `ss-manager`) -- ty Wed, 20 Jan 2019 01:14:55 +0800 shadowsocks-rust (1.6.11) unstable; urgency=medium * Updated dependencies -- ty Sat, 20 Jan 2018 20:45:59 +0800 shadowsocks-rust (1.6.10) unstable; urgency=medium * Check AEAD packet length before actually reading it. -- ty Sat, 2 Dec 2017 11:56:00 +0800 shadowsocks-rust (1.6.9) unstable; urgency=medium * Fixed increase_nonce without libsodium -- ty Sun, 26 Nov 2017 10:28:13 UTC shadowsocks-rust (1.6.8) unstable; urgency=medium * Upstream bump version. -- Simon Shi Wed, 08 Nov 2017 14:27:18 +0800 shadowsocks-rust (1.6.6+deb1) unstable; urgency=medium * Add debian files. * Add systemd files and default config. -- Simon Shi Tue, 10 Oct 2017 10:01:14 +0800 shadowsocks-rust (1.6.6) stable; urgency=medium * Removed aes-128-ctr cipher -- ty Wed, 4 Oct 2017 04:11:55 +0800 shadowsocks-rust (1.6.5) unstable; urgency=medium * Initial Release. -- Shigure Moe Sat, 30 Sep 2017 16:21:42 +0800 ================================================ FILE: debian/compat ================================================ 10 ================================================ FILE: debian/config.json ================================================ { "server": "0.0.0.0", "server_port": 8388, "local_address": "127.0.0.1", "local_port": 1080, "password": "barfoo", "timeout": 300, "method": "chacha20-ietf-poly1305" } ================================================ FILE: debian/control ================================================ Source: shadowsocks-rust Section: net Priority: optional Maintainer: Y. T. Chung Build-Depends: debhelper (>=9), rustc, cargo Standards-Version: 3.9.6 Homepage: https://github.com/shadowsocks/shadowsocks-rust Package: shadowsocks-rust Architecture: any Depends: ${shlibs:Depends}, ${misc:Depends}, lsb-base Conflicts: shadowsocks Description: Rust port of shadowsocks, a secure socks5 proxy Shadowsocks is a fast tunnel proxy that helps you bypass firewalls. Shadowsocks-rust was inspired by Shadowsocks (in Python). It's rewritten in rust. ================================================ FILE: debian/copyright ================================================ Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ Upstream-Name: shadowsocks-rust Source: https://github.com/shadowsocks/shadowsocks-rust Files: * Copyright: 2014 Y. T. CHUNG License: MIT Files: debian/* Copyright: 2017 Simon Shi License: MIT License: MIT 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. ================================================ FILE: debian/install ================================================ debian/config.json usr/share/shadowsocks-rust debian/shadowsocks-rust-*.service lib/systemd/system ================================================ FILE: debian/rules ================================================ #!/usr/bin/make -f override_dh_auto_build: dh_auto_build -- TARGET=release override_dh_auto_install: dh_auto_install -- TARGET=release PREFIX=/usr/bin %: dh $@ ================================================ FILE: debian/shadowsocks-rust-local@.service ================================================ # This file is part of shadowsocks-rust. # # This is a template unit file. Users may copy and rename the file into # config directories to make new service instances. See systemd.unit(5) # for details. [Unit] Description=Shadowsocks-rust Custom Client Service for %I Documentation=https://github.com/shadowsocks/shadowsocks-rust After=network.target [Service] Type=simple CapabilityBoundingSet=CAP_NET_BIND_SERVICE AmbientCapabilities=CAP_NET_BIND_SERVICE DynamicUser=yes ExecStart=/usr/bin/ssservice local --log-without-time -c /etc/shadowsocks-rust/%i.json [Install] WantedBy=multi-user.target ================================================ FILE: debian/shadowsocks-rust-server@.service ================================================ # This file is part of shadowsocks-rust. # # This is a template unit file. Users may copy and rename the file into # config directories to make new service instances. See systemd.unit(5) # for details. [Unit] Description=Shadowsocks-rust Custom Server Service for %I Documentation=https://github.com/shadowsocks/shadowsocks-rust After=network.target [Service] Type=simple CapabilityBoundingSet=CAP_NET_BIND_SERVICE AmbientCapabilities=CAP_NET_BIND_SERVICE DynamicUser=yes ExecStart=/usr/bin/ssservice server --log-without-time -c /etc/shadowsocks-rust/%i.json [Install] WantedBy=multi-user.target ================================================ FILE: debian/shadowsocks-rust.default ================================================ # Defaults for shadowsocks initscript # sourced by /etc/init.d/shadowsocks-rust # installed at /etc/default/shadowsocks-rust by the maintainer scripts # # This is a POSIX shell fragment # # Note: `START', `GROUP' and `MAXFD' options are not recognized by systemd. # Please change those settings in the corresponding systemd unit file. # Enable during startup? START=yes # Configuration file CONFFILE="/etc/shadowsocks-rust/config.json" # Extra command line arguments DAEMON_ARGS="--log-without-time" # User and group to run the server as USER=nobody GROUP=nogroup # Number of maximum file descriptors MAXFD=32768 ================================================ FILE: debian/shadowsocks-rust.init ================================================ #!/bin/sh ### BEGIN INIT INFO # Provides: shadowsocks-rust # Required-Start: $network $local_fs $remote_fs # Required-Stop: $remote_fs # Default-Start: 2 3 4 5 # Default-Stop: 0 1 6 # Short-Description: lightweight secured socks5 proxy # Description: Rust port of shadowsocks. # shadowsocks is a fast tunnel proxy that helps you bypass firewalls. ### END INIT INFO # Author: Simon Shi # PATH should only include /usr/ if it runs after the mountnfs.sh script PATH=/sbin:/usr/sbin:/bin:/usr/bin DESC=shadowsocks-rust # Introduce a short description here NAME=shadowsocks-rust # Introduce the short server's name here DAEMON=/usr/bin/ssservice # Introduce the server's location here DAEMON_ARGS="--log-without-time" # Arguments to run the daemon with PIDFILE=/var/run/$NAME/$NAME.pid SCRIPTNAME=/etc/init.d/$NAME # Exit if the package is not installed [ -x $DAEMON ] || exit 0 # Read configuration variable file if it is present [ -r /etc/default/$NAME ] && . /etc/default/$NAME [ "$START" = "yes" ] || exit 0 : ${USER:="nobody"} : ${GROUP:="nogroup"} # Load the VERBOSE setting and other rcS variables . /lib/init/vars.sh # Define LSB log_* functions. # Depend on lsb-base (>= 3.0-6) to ensure that this file is present. . /lib/lsb/init-functions # # Function that starts the daemon/service # do_start() { # Modify the file descriptor limit ulimit -n ${MAXFD} # Take care of pidfile permissions mkdir /var/run/$NAME 2>/dev/null || true chown "$USER:$GROUP" /var/run/$NAME # Return # 0 if daemon has been started # 1 if daemon was already running # 2 if daemon could not be started start-stop-daemon --start --quiet --pidfile $PIDFILE --chuid $USER:$GROUP --exec $DAEMON server \ -c "$CONFFILE" -f $PIDFILE $DAEMON_ARGS \ || return 2 } # # Function that stops the daemon/service # do_stop() { # Return # 0 if daemon has been stopped # 1 if daemon was already stopped # 2 if daemon could not be stopped # other if a failure occurred start-stop-daemon --stop --quiet --retry=TERM/5 --pidfile $PIDFILE --exec $DAEMON RETVAL="$?" [ "$RETVAL" = 2 ] && return 2 # Wait for children to finish too if this is a daemon that forks # and if the daemon is only ever run from this initscript. # If the above conditions are not satisfied then add some other code # that waits for the process to drop all resources that could be # needed by services started subsequently. A last resort is to # sleep for some time. start-stop-daemon --stop --quiet --oknodo --retry=KILL/5 --exec $DAEMON [ "$?" = 2 ] && return 2 # Many daemons don't delete their pidfiles when they exit. rm -f $PIDFILE return "$RETVAL" } case "$1" in start) [ "$VERBOSE" != no ] && log_daemon_msg "Starting $DESC " "$NAME" do_start case "$?" in 0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;; 2) [ "$VERBOSE" != no ] && log_end_msg 1 ;; esac ;; stop) [ "$VERBOSE" != no ] && log_daemon_msg "Stopping $DESC" "$NAME" do_stop case "$?" in 0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;; 2) [ "$VERBOSE" != no ] && log_end_msg 1 ;; esac ;; status) status_of_proc "$DAEMON" "$NAME" && exit 0 || exit $? ;; restart|force-reload) log_daemon_msg "Restarting $DESC" "$NAME" do_stop case "$?" in 0|1) do_start case "$?" in 0) log_end_msg 0 ;; 1) log_end_msg 1 ;; # Old process is still running *) log_end_msg 1 ;; # Failed to start esac ;; *) # Failed to stop log_end_msg 1 ;; esac ;; *) echo "Usage: $SCRIPTNAME {start|stop|status|restart|force-reload}" >&2 exit 3 ;; esac : ================================================ FILE: debian/shadowsocks-rust.postinst ================================================ #!/bin/sh set -e # POSIX-compliant maint function recommend by devref # to check for the existence of a command # https://www.debian.org/doc/manuals/developers-reference/ch06.html#bpp-debian-maint-scripts pathfind() { OLDIFS="$IFS" IFS=: for p in $PATH; do if [ -x "$p/$*" ]; then IFS="$OLDIFS" return 0 fi done IFS="$OLDIFS" return 1 } case "$1" in configure|reconfigure) pathfind setcap && setcap \ cap_net_bind_service+ep /usr/bin/ssservice \ cap_net_bind_service+ep /usr/bin/sslocal \ cap_net_bind_service+ep /usr/bin/ssserver if [ ! -f /etc/shadowsocks-rust/config.json ]; then set +e passwd=$(/usr/bin/ssservice genkey -m "chacha20-ietf-poly1305") passwd=$(echo $passwd | sed "s/+/\\\\+/g" | sed "s/\\//\\\\\\//g") set -e mkdir -p /etc/shadowsocks-rust sed "s/barfoo/$passwd/" /usr/share/shadowsocks-rust/config.json \ > /etc/shadowsocks-rust/config.json fi ;; abort-upgrade|abort-remove|abort-deconfigure) exit 0 ;; *) echo "postinst called with unknown argument \`$1'" >&2 exit 0 ;; esac #DEBHELPER# exit 0 ================================================ FILE: debian/shadowsocks-rust.service ================================================ # This file is part of shadowsocks-rust. # # This file is default for Debian packaging. See also # /etc/default/shadowsocks-rust for environment variables. [Unit] Description=Shadowsocks-rust Default Server Service Documentation=https://github.com/shadowsocks/shadowsocks-rust After=network.target [Service] Type=simple EnvironmentFile=/etc/default/shadowsocks-rust DynamicUser=yes LimitNOFILE=32768 ExecStart=/usr/bin/ssservice server -c ${CONFFILE} ${DAEMON_ARGS} [Install] WantedBy=multi-user.target ================================================ FILE: debian/source/format ================================================ 3.0 (native) ================================================ FILE: deny.toml ================================================ # This template contains all of the possible sections and their default values # Note that all fields that take a lint level have these possible values: # * deny - An error will be produced and the check will fail # * warn - A warning will be produced, but the check will not fail # * allow - No warning or error will be produced, though in some cases a note # will be # The values provided in this template are the default values that will be used # when any section or field is not specified in your own configuration # Root options # The graph table configures how the dependency graph is constructed and thus # which crates the checks are performed against [graph] # If 1 or more target triples (and optionally, target_features) are specified, # only the specified targets will be checked when running `cargo deny check`. # This means, if a particular package is only ever used as a target specific # dependency, such as, for example, the `nix` crate only being used via the # `target_family = "unix"` configuration, that only having windows targets in # this list would mean the nix crate, as well as any of its exclusive # dependencies not shared by any other crates, would be ignored, as the target # list here is effectively saying which targets you are building for. targets = [ # The triple can be any string, but only the target triples built in to # rustc (as of 1.40) can be checked against actual config expressions #"x86_64-unknown-linux-musl", # You can also specify which target_features you promise are enabled for a # particular target. target_features are currently not validated against # the actual valid features supported by the target architecture. #{ triple = "wasm32-unknown-unknown", features = ["atomics"] }, ] # When creating the dependency graph used as the source of truth when checks are # executed, this field can be used to prune crates from the graph, removing them # from the view of cargo-deny. This is an extremely heavy hammer, as if a crate # is pruned from the graph, all of its dependencies will also be pruned unless # they are connected to another crate in the graph that hasn't been pruned, # so it should be used with care. The identifiers are [Package ID Specifications] # (https://doc.rust-lang.org/cargo/reference/pkgid-spec.html) #exclude = [] # If true, metadata will be collected with `--all-features`. Note that this can't # be toggled off if true, if you want to conditionally enable `--all-features` it # is recommended to pass `--all-features` on the cmd line instead all-features = false # If true, metadata will be collected with `--no-default-features`. The same # caveat with `all-features` applies no-default-features = false # If set, these feature will be enabled when collecting metadata. If `--features` # is specified on the cmd line they will take precedence over this option. features = ["full-extra"] # The output table provides options for how/if diagnostics are outputted [output] # When outputting inclusion graphs in diagnostics that include features, this # option can be used to specify the depth at which feature edges will be added. # This option is included since the graphs can be quite large and the addition # of features from the crate(s) to all of the graph roots can be far too verbose. # This option can be overridden via `--feature-depth` on the cmd line feature-depth = 1 # This section is considered when running `cargo deny check advisories` # More documentation for the advisories section can be found here: # https://embarkstudios.github.io/cargo-deny/checks/advisories/cfg.html [advisories] # The path where the advisory databases are cloned/fetched into #db-path = "$CARGO_HOME/advisory-dbs" # The url(s) of the advisory databases to use #db-urls = ["https://github.com/rustsec/advisory-db"] # A list of advisory IDs to ignore. Note that ignored advisories will still # output a note when they are encountered. ignore = [ #"RUSTSEC-0000-0000", #{ id = "RUSTSEC-0000-0000", reason = "you can specify a reason the advisory is ignored" }, #"a-crate-that-is-yanked@0.1.1", # you can also ignore yanked crate versions if you wish #{ crate = "a-crate-that-is-yanked@0.1.1", reason = "you can specify why you are ignoring the yanked crate" }, ] # If this is true, then cargo deny will use the git executable to fetch advisory database. # If this is false, then it uses a built-in git library. # Setting this to true can be helpful if you have special authentication requirements that cargo-deny does not support. # See Git Authentication for more information about setting up git authentication. #git-fetch-with-cli = true # This section is considered when running `cargo deny check licenses` # More documentation for the licenses section can be found here: # https://embarkstudios.github.io/cargo-deny/checks/licenses/cfg.html [licenses] # List of explicitly allowed licenses # See https://spdx.org/licenses/ for list of possible licenses # [possible values: any SPDX 3.11 short identifier (+ optional exception)]. allow = [ "MIT", "Apache-2.0", "Apache-2.0 WITH LLVM-exception", "ISC", "BSD-2-Clause", "BSD-3-Clause", "Unicode-3.0", "MPL-2.0", "CDLA-Permissive-2.0", "CC0-1.0", "0BSD", "OpenSSL", ] # The confidence threshold for detecting a license from license text. # The higher the value, the more closely the license text must be to the # canonical license text of a valid SPDX license file. # [possible values: any between 0.0 and 1.0]. confidence-threshold = 0.8 # Allow 1 or more licenses on a per-crate basis, so that particular licenses # aren't accepted for every possible crate as with the normal allow list exceptions = [ # Each entry is the crate and version constraint, and its specific allow # list #{ allow = ["Zlib"], crate = "adler32" }, { allow = ["WTFPL"], crate = "tun" }, ] # Some crates don't have (easily) machine readable licensing information, # adding a clarification entry for it allows you to manually specify the # licensing information #[[licenses.clarify]] # The package spec the clarification applies to #crate = "ring" # The SPDX expression for the license requirements of the crate #expression = "MIT AND ISC AND OpenSSL" # One or more files in the crate's source used as the "source of truth" for # the license expression. If the contents match, the clarification will be used # when running the license check, otherwise the clarification will be ignored # and the crate will be checked normally, which may produce warnings or errors # depending on the rest of your configuration #license-files = [ # Each entry is a crate relative path, and the (opaque) hash of its contents #{ path = "LICENSE", hash = 0xbd0eed23 } #] [[licenses.clarify]] name = "ring" expression = "LicenseRef-ring" license-files = [{ path = "LICENSE", hash = 0xbd0eed23 }] [licenses.private] # If true, ignores workspace crates that aren't published, or are only # published to private registries. # To see how to mark a crate as unpublished (to the official registry), # visit https://doc.rust-lang.org/cargo/reference/manifest.html#the-publish-field. ignore = false # One or more private registries that you might publish crates to, if a crate # is only published to private registries, and ignore is true, the crate will # not have its license(s) checked registries = [ #"https://sekretz.com/registry ] # This section is considered when running `cargo deny check bans`. # More documentation about the 'bans' section can be found here: # https://embarkstudios.github.io/cargo-deny/checks/bans/cfg.html [bans] # Lint level for when multiple versions of the same crate are detected multiple-versions = "warn" # Lint level for when a crate version requirement is `*` wildcards = "deny" # The graph highlighting used when creating dotgraphs for crates # with multiple versions # * lowest-version - The path to the lowest versioned duplicate is highlighted # * simplest-path - The path to the version with the fewest edges is highlighted # * all - Both lowest-version and simplest-path are used highlight = "all" # The default lint level for `default` features for crates that are members of # the workspace that is being checked. This can be overridden by allowing/denying # `default` on a crate-by-crate basis if desired. workspace-default-features = "allow" # The default lint level for `default` features for external crates that are not # members of the workspace. This can be overridden by allowing/denying `default` # on a crate-by-crate basis if desired. external-default-features = "allow" # List of crates that are allowed. Use with care! allow = [ #"ansi_term@0.11.0", #{ crate = "ansi_term@0.11.0", reason = "you can specify a reason it is allowed" }, ] # List of crates to deny deny = [ #"ansi_term@0.11.0", #{ crate = "ansi_term@0.11.0", reason = "you can specify a reason it is banned" }, # Wrapper crates can optionally be specified to allow the crate when it # is a direct dependency of the otherwise banned crate #{ crate = "ansi_term@0.11.0", wrappers = ["this-crate-directly-depends-on-ansi_term"] }, ] # List of features to allow/deny # Each entry the name of a crate and a version range. If version is # not specified, all versions will be matched. #[[bans.features]] #crate = "reqwest" # Features to not allow #deny = ["json"] # Features to allow #allow = [ # "rustls", # "__rustls", # "__tls", # "hyper-rustls", # "rustls", # "rustls-pemfile", # "rustls-tls-webpki-roots", # "tokio-rustls", # "webpki-roots", #] # If true, the allowed features must exactly match the enabled feature set. If # this is set there is no point setting `deny` #exact = true # Certain crates/versions that will be skipped when doing duplicate detection. skip = [ #"ansi_term@0.11.0", #{ crate = "ansi_term@0.11.0", reason = "you can specify a reason why it can't be updated/removed" }, ] # Similarly to `skip` allows you to skip certain crates during duplicate # detection. Unlike skip, it also includes the entire tree of transitive # dependencies starting at the specified crate, up to a certain depth, which is # by default infinite. skip-tree = [ #"ansi_term@0.11.0", # will be skipped along with _all_ of its direct and transitive dependencies #{ crate = "ansi_term@0.11.0", depth = 20 }, ] # This section is considered when running `cargo deny check sources`. # More documentation about the 'sources' section can be found here: # https://embarkstudios.github.io/cargo-deny/checks/sources/cfg.html [sources] # Lint level for what to happen when a crate from a crate registry that is not # in the allow list is encountered unknown-registry = "deny" # Lint level for what to happen when a crate from a git repository that is not # in the allow list is encountered unknown-git = "deny" # List of URLs for allowed crate registries. Defaults to the crates.io index # if not specified. If it is specified but empty, no registries are allowed. allow-registry = ["https://github.com/rust-lang/crates.io-index"] # List of URLs for allowed Git repositories allow-git = [] [sources.allow-org] # github.com organizations to allow git sources for github = [] # gitlab.com organizations to allow git sources for gitlab = [] # bitbucket.org organizations to allow git sources for bitbucket = [] ================================================ FILE: docker/Dockerfile.v2ray ================================================ FROM ghcr.io/shadowsocks/ssserver-rust:latest USER root RUN cd /tmp && \ TAG=$(wget -qO- https://api.github.com/repos/shadowsocks/v2ray-plugin/releases/latest | grep tag_name | cut -d '"' -f4) && \ wget https://github.com/shadowsocks/v2ray-plugin/releases/download/$TAG/v2ray-plugin-linux-amd64-$TAG.tar.gz && \ tar -xf *.gz && \ rm *.gz && \ mv v2ray* /usr/bin/v2ray-plugin && \ chmod +x /usr/bin/v2ray-plugin USER nobody ENTRYPOINT [ "/docker-entrypoint.sh" ] CMD [ "ssserver", "--log-without-time", "-c", "/etc/shadowsocks-rust/config.json" ] ================================================ FILE: docker/docker-entrypoint.sh ================================================ #!/bin/sh # vim:sw=4:ts=4:et set -e if [ -z "${SS_ENTRYPOINT_QUIET_LOGS:-}" ]; then exec 3>&1 else exec 3>/dev/null fi if [ "$1" = "sslocal" -o "$1" = "ssserver" -o "$1" = "ssmanager" -o "$1" = "ssservice" ]; then if [ -f "/etc/shadowsocks-rust/config.json" ]; then echo >&3 "$0: Configuration complete; ready for start up" else echo >&3 "$0: No configuration files found in /etc/shadowsocks-rust, skipping configuration" fi fi exec "$@" ================================================ FILE: docker/linux-cross/Dockerfile ================================================ ARG CROSS_BASE_IMAGE FROM $CROSS_BASE_IMAGE ARG DEBIAN_FRONTEND=noninteractive RUN apt-get update && \ apt-get install --assume-yes --no-install-recommends build-essential cmake nasm llvm-8-dev libclang-8-dev clang-8 && \ git config --global --add safe.directory '*' && \ rm -rf /tmp/* ENV GOCACHE=/tmp ================================================ FILE: examples/config.json ================================================ { "server": "127.0.0.1", "server_port": 8388, "local_port": 1080, "local_address": "127.0.0.1", "password": "password", "timeout": 300, "method": "aes-256-gcm" } ================================================ FILE: examples/config_ext.json ================================================ { "locals": [ { "local_address": "127.0.0.1", "local_port": 1080 }, { "local_address": "127.0.0.1", "local_port": 3128, "protocol": "http" }, { "local_address": "127.0.0.1", "local_port": 53, "protocol": "tunnel", "forward_address": "8.8.8.8", "forward_port": 53 } ], "servers": [ { "server": "127.0.0.1", "server_port": 8384, "password": "password-svr2", "method": "chacha20-ietf-poly1305" }, { "server": "127.0.0.1", "server_port": 8385, "password": "password-svr3", "method": "aes-128-gcm" } ] } ================================================ FILE: homebrew/shadowsocks-rust.rb ================================================ class ShadowsocksRust < Formula desc "Rust port of Shadowsocks" homepage "https://github.com/shadowsocks/shadowsocks-rust" url "https://github.com/shadowsocks/shadowsocks-rust/archive/v1.17.2.tar.gz" sha256 "79d3d5204fad725bd2712f29066e71d14a329c3ea956b708cb6ea64bb0316a0b" license "MIT" head "https://github.com/shadowsocks/shadowsocks-rust.git", branch: "master" depends_on "rust" => :build def install system "cargo", "install", *std_cargo_args (buildpath/"shadowsocks-rust.json").write <<~EOS { "server":"localhost", "server_port":8388, "password":"barfoo!", "timeout":600, "acl": "/usr/local/etc/chn.acl", "locals": [ { "protocol": "socks", "local_address": "127.0.0.1", "local_port": 1080 }, { "protocol": "http", "local_address": "127.0.0.1", "local_port": 3128 } ] } EOS etc.install "shadowsocks-rust.json" end service do run [opt_bin/"sslocal", "--config", etc/"shadowsocks-rust.json"] keep_alive true end test do server_port = free_port local_port = free_port (testpath/"server.json").write <<~EOS { "server":"127.0.0.1", "server_port":#{server_port}, "password":"mypassword", "method":"aes-256-gcm" } EOS (testpath/"local.json").write <<~EOS { "server":"127.0.0.1", "server_port":#{server_port}, "password":"mypassword", "method":"aes-256-gcm", "local_address":"127.0.0.1", "local_port":#{local_port} } EOS fork { exec bin/"ssserver", "-c", testpath/"server.json" } fork { exec bin/"sslocal", "-c", testpath/"local.json" } sleep 3 output = shell_output "curl --socks5 127.0.0.1:#{local_port} https://example.com" assert_match "Example Domain", output end end ================================================ FILE: k8s/chart/.helmignore ================================================ # Patterns to ignore when building packages. # This supports shell glob matching, relative path matching, and # negation (prefixed with !). Only one pattern per line. .DS_Store # Common VCS dirs .git/ .gitignore .bzr/ .bzrignore .hg/ .hgignore .svn/ # Common backup files *.swp *.bak *.tmp *.orig *~ # Various IDEs .project .idea/ *.tmproj .vscode/ ================================================ FILE: k8s/chart/Chart.yaml ================================================ apiVersion: v2 name: shadowsocks-rust description: A Helm chart for shadowsocks-rust # A chart can be either an 'application' or a 'library' chart. # # Application charts are a collection of templates that can be packaged into versioned archives # to be deployed. # # Library charts provide useful utilities or functions for the chart developer. They're included as # a dependency of application charts to inject those utilities and functions into the rendering # pipeline. Library charts do not define any templates and therefore cannot be deployed. type: application # This is the chart version. This version number should be incremented each time you make changes # to the chart and its templates, including the app version. # Versions are expected to follow Semantic Versioning (https://semver.org/) version: 0.1.0 # This is the version number of the application being deployed. This version number should be # incremented each time you make changes to the application. Versions are not expected to # follow Semantic Versioning. They should reflect the version the application is using. # It is recommended to use it with quotes. appVersion: "1.x.x" ================================================ FILE: k8s/chart/templates/NOTES.txt ================================================ {{- $port := "" -}} {{- if not .Values.configMapName -}} {{- $port = (.Values.servers | first).server_port -}} {{- end -}} 1. Get the shadowsocks URL by running these commands: {{- if contains "NodePort" .Values.service.type }} export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "shadowsocks-rust.fullname" . }}) export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}") echo http://$NODE_IP:$NODE_PORT {{- else if contains "LoadBalancer" .Values.service.type }} NOTE: It may take a few minutes for the LoadBalancer IP to be available. You can watch the status of by running 'kubectl get --namespace {{ .Release.Namespace }} svc -w {{ include "shadowsocks-rust.fullname" . }}' export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "shadowsocks-rust.fullname" . }} --template "{{"{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}"}}") echo http://$SERVICE_IP:{{ $port }} {{- else if contains "ClusterIP" .Values.service.type }} export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ include "shadowsocks-rust.name" . }},app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}") export CONTAINER_PORT=$(kubectl get pod --namespace {{ .Release.Namespace }} $POD_NAME -o jsonpath="{.spec.containers[0].ports[0].containerPort}") echo "Visit http://127.0.0.1:8080 to use your application" kubectl --namespace {{ .Release.Namespace }} port-forward $POD_NAME 8080:$CONTAINER_PORT {{- end }} ================================================ FILE: k8s/chart/templates/_helpers.tpl ================================================ {{/* Expand the name of the chart. */}} {{- define "shadowsocks-rust.name" -}} {{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} {{- end }} {{/* Create a default fully qualified app name. We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). If release name contains chart name it will be used as a full name. */}} {{- define "shadowsocks-rust.fullname" -}} {{- if .Values.fullnameOverride }} {{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} {{- else }} {{- $name := default .Chart.Name .Values.nameOverride }} {{- if contains $name .Release.Name }} {{- .Release.Name | trunc 63 | trimSuffix "-" }} {{- else }} {{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} {{- end }} {{- end }} {{- end }} {{/* Create chart name and version as used by the chart label. */}} {{- define "shadowsocks-rust.chart" -}} {{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} {{- end }} {{/* Common labels */}} {{- define "shadowsocks-rust.labels" -}} helm.sh/chart: {{ include "shadowsocks-rust.chart" . }} {{ include "shadowsocks-rust.selectorLabels" . }} {{- if .Chart.AppVersion }} app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} {{- end }} app.kubernetes.io/managed-by: {{ .Release.Service }} {{- end }} {{/* Selector labels */}} {{- define "shadowsocks-rust.selectorLabels" -}} app.kubernetes.io/name: {{ include "shadowsocks-rust.name" . }} app.kubernetes.io/instance: {{ .Release.Name }} {{- end }} {{/* Create the name of the service account to use */}} {{- define "shadowsocks-rust.serviceAccountName" -}} {{- if .Values.serviceAccount.create }} {{- default (include "shadowsocks-rust.fullname" .) .Values.serviceAccount.name }} {{- else }} {{- default "default" .Values.serviceAccount.name }} {{- end }} {{- end }} {{- define "shadowsocks-rust.portName" -}} {{- if .name -}} {{- .name -}} {{- else -}} {{- printf "ss-%d" (.server_port | int) -}} {{- end -}} {{- end -}} ================================================ FILE: k8s/chart/templates/config.yaml ================================================ {{- if not .Values.configMapName -}} kind: ConfigMap apiVersion: v1 metadata: name: {{ include "shadowsocks-rust.fullname" . }} labels: {{- include "shadowsocks-rust.labels" . | nindent 4 }} data: config.json: | { "servers": {{- .Values.servers | toPrettyJson | nindent 8 }} } {{- end -}} ================================================ FILE: k8s/chart/templates/deployment.yaml ================================================ apiVersion: apps/v1 kind: Deployment metadata: name: {{ include "shadowsocks-rust.fullname" . }} labels: {{- include "shadowsocks-rust.labels" . | nindent 4 }} spec: {{- if not .Values.autoscaling.enabled }} replicas: {{ .Values.replicaCount }} {{- end }} selector: matchLabels: {{- include "shadowsocks-rust.selectorLabels" . | nindent 6 }} template: metadata: {{- with .Values.podAnnotations }} annotations: {{- toYaml . | nindent 8 }} {{- end }} labels: {{- include "shadowsocks-rust.selectorLabels" . | nindent 8 }} spec: {{- with .Values.imagePullSecrets }} imagePullSecrets: {{- toYaml . | nindent 8 }} {{- end }} serviceAccountName: {{ include "shadowsocks-rust.serviceAccountName" . }} securityContext: {{- toYaml .Values.podSecurityContext | nindent 8 }} volumes: - name: config configMap: name: {{ default (include "shadowsocks-rust.fullname" .) .Values.configMapName }} - name: plugins emptyDir: {} {{- if .Values.downloadPlugins }} initContainers: - name: plugin-downloader image: busybox command: - sh - -c - | TAG=$(wget -qO- https://api.github.com/repos/shadowsocks/v2ray-plugin/releases/latest | grep tag_name | cut -d '"' -f4) wget https://github.com/shadowsocks/v2ray-plugin/releases/download/$TAG/v2ray-plugin-linux-amd64-$TAG.tar.gz tar -xf *.gz rm *.gz mv v2ray* /usr/local/bin/v2ray-plugin chmod +x /usr/local/bin/v2ray-plugin TAG=$(wget -qO- https://api.github.com/repos/teddysun/xray-plugin/releases/latest | grep tag_name | cut -d '"' -f4) wget https://github.com/teddysun/xray-plugin/releases/download/$TAG/xray-plugin-linux-amd64-$TAG.tar.gz tar -xf *.gz rm *.gz mv xray* /usr/local/bin/xray-plugin chmod +x /usr/local/bin/xray-plugin volumeMounts: - name: plugins mountPath: /usr/local/bin {{- end }} containers: - name: {{ .Chart.Name }} securityContext: {{- toYaml .Values.securityContext | nindent 10 }} image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" imagePullPolicy: {{ .Values.image.pullPolicy }} volumeMounts: - name: config mountPath: /etc/shadowsocks-rust readOnly: true - name: plugins mountPath: /usr/local/bin ports: {{- $hostPort := .Values.hostPort -}} {{- range $i, $svr := .Values.servers }} - name: {{ include "shadowsocks-rust.portName" $svr }} containerPort: {{ $svr.server_port }} {{- if $hostPort }} hostPort: {{ $svr.server_port }} {{- end }} protocol: TCP {{ end -}} {{- /* use the first port for health check */ -}} {{- $defaultPort := (.Values.servers | first).server_port -}} livenessProbe: tcpSocket: port: {{ $defaultPort }} failureThreshold: 3 initialDelaySeconds: 1 timeoutSeconds: 1 readinessProbe: tcpSocket: port: {{ $defaultPort }} initialDelaySeconds: 2 resources: {{- toYaml .Values.resources | nindent 10 }} {{- with .Values.nodeSelector }} nodeSelector: {{- toYaml . | nindent 8 }} {{- end }} {{- with .Values.affinity }} affinity: {{- toYaml . | nindent 8 }} {{- end }} {{- with .Values.tolerations }} tolerations: {{- toYaml . | nindent 8 }} {{- end }} ================================================ FILE: k8s/chart/templates/hpa.yaml ================================================ {{- if .Values.autoscaling.enabled }} apiVersion: autoscaling/v2beta1 kind: HorizontalPodAutoscaler metadata: name: {{ include "shadowsocks-rust.fullname" . }} labels: {{- include "shadowsocks-rust.labels" . | nindent 4 }} spec: scaleTargetRef: apiVersion: apps/v1 kind: Deployment name: {{ include "shadowsocks-rust.fullname" . }} minReplicas: {{ .Values.autoscaling.minReplicas }} maxReplicas: {{ .Values.autoscaling.maxReplicas }} metrics: {{- if .Values.autoscaling.targetCPUUtilizationPercentage }} - type: Resource resource: name: cpu targetAverageUtilization: {{ .Values.autoscaling.targetCPUUtilizationPercentage }} {{- end }} {{- if .Values.autoscaling.targetMemoryUtilizationPercentage }} - type: Resource resource: name: memory targetAverageUtilization: {{ .Values.autoscaling.targetMemoryUtilizationPercentage }} {{- end }} {{- end }} ================================================ FILE: k8s/chart/templates/service.yaml ================================================ apiVersion: v1 kind: Service metadata: name: {{ include "shadowsocks-rust.fullname" . }} labels: {{- include "shadowsocks-rust.labels" . | nindent 4 }} annotations: {{- range $key, $value := .Values.service.annotations }} {{ $key }}: {{ $value | quote }} {{- end }} spec: type: {{ .Values.service.type }} ports: {{- range $i, $svr := .Values.servers }} - name: {{ include "shadowsocks-rust.portName" $svr }} targetPort: {{ $svr.server_port }} protocol: TCP port: {{ default $svr.server_port $svr.service_port }} {{ end -}} selector: {{- include "shadowsocks-rust.selectorLabels" . | nindent 4 }} ================================================ FILE: k8s/chart/templates/serviceaccount.yaml ================================================ {{- if .Values.serviceAccount.create -}} apiVersion: v1 kind: ServiceAccount metadata: name: {{ include "shadowsocks-rust.serviceAccountName" . }} labels: {{- include "shadowsocks-rust.labels" . | nindent 4 }} {{- with .Values.serviceAccount.annotations }} annotations: {{- toYaml . | nindent 4 }} {{- end }} {{- end }} ================================================ FILE: k8s/chart/templates/tests/test-connection.yaml ================================================ apiVersion: v1 kind: Pod metadata: name: "{{ include "shadowsocks-rust.fullname" . }}-test-connection" labels: {{- include "shadowsocks-rust.labels" . | nindent 4 }} annotations: "helm.sh/hook": test spec: containers: - name: wget image: busybox command: ['wget'] args: ['{{ include "shadowsocks-rust.fullname" . }}:{{ .Values.service.port }}'] restartPolicy: Never ================================================ FILE: k8s/chart/values.yaml ================================================ # Default values for shadowsocks-rust. # This is a YAML-formatted file. # Declare variables to be passed into your templates. # This is the shadowsocks config which will be mount to /etc/shadowocks-rust. # You can put arbitrary yaml here, and it will be translated to json before mounting. servers: - server: "::" server_port: 8388 service_port: 80 # the k8s service port, default to server_port password: mypassword method: aes-256-gcm fast_open: true mode: tcp_and_udp # plugin: v2ray-plugin # plugin_opts: server;tls;host=github.com # Whether to download v2ray and xray plugin. downloadPlugins: false # Name of the ConfigMap with config.json configuration for shadowsocks-rust. configMapName: "" service: # Change to LoadBalancer if you are behind a cloud provider like aws, gce, or tke. type: ClusterIP # external-dns.alpha.kubernetes.io/hostname: socks.example.com annotations: {} # Bind shadowsocks port port to host, i.e., we can use host:port to access shawdowsocks server. hostPort: false replicaCount: 1 image: repository: ghcr.io/shadowsocks/ssserver-rust pullPolicy: IfNotPresent # Overrides the image tag whose default is the chart appVersion. tag: "latest" imagePullSecrets: [] nameOverride: "" fullnameOverride: "" serviceAccount: # Specifies whether a service account should be created create: true # Annotations to add to the service account annotations: {} # The name of the service account to use. # If not set and create is true, a name is generated using the fullname template name: "" podAnnotations: {} podSecurityContext: {} # fsGroup: 2000 securityContext: {} # capabilities: # drop: # - ALL # readOnlyRootFilesystem: true # runAsNonRoot: true # runAsUser: 1000 resources: # We usually recommend not to specify default resources and to leave this as a conscious # choice for the user. This also increases chances charts run on environments with little # resources, such as Minikube. If you do want to specify resources, uncomment the following # lines, adjust them as necessary, and remove the curly braces after 'resources:'. limits: cpu: 100m memory: 128Mi requests: cpu: 20m memory: 32Mi autoscaling: enabled: false minReplicas: 1 maxReplicas: 100 targetCPUUtilizationPercentage: 80 # targetMemoryUtilizationPercentage: 80 nodeSelector: {} tolerations: [] affinity: {} ================================================ FILE: k8s/shadowsocks-rust.yaml ================================================ --- # Source: shadowsocks-rust/templates/serviceaccount.yaml apiVersion: v1 kind: ServiceAccount metadata: name: shadowsocks-rust labels: helm.sh/chart: shadowsocks-rust-0.1.0 app.kubernetes.io/name: shadowsocks-rust app.kubernetes.io/instance: shadowsocks-rust app.kubernetes.io/version: "1.x.x" app.kubernetes.io/managed-by: Helm --- # Source: shadowsocks-rust/templates/config.yaml kind: ConfigMap apiVersion: v1 metadata: name: shadowsocks-rust labels: helm.sh/chart: shadowsocks-rust-0.1.0 app.kubernetes.io/name: shadowsocks-rust app.kubernetes.io/instance: shadowsocks-rust app.kubernetes.io/version: "1.x.x" app.kubernetes.io/managed-by: Helm data: config.json: | { "servers": [ { "fast_open": true, "method": "aes-256-gcm", "mode": "tcp_and_udp", "password": "mypassword", "server": "::", "server_port": 8388, "service_port": 80 } ] } --- # Source: shadowsocks-rust/templates/service.yaml apiVersion: v1 kind: Service metadata: name: shadowsocks-rust labels: helm.sh/chart: shadowsocks-rust-0.1.0 app.kubernetes.io/name: shadowsocks-rust app.kubernetes.io/instance: shadowsocks-rust app.kubernetes.io/version: "1.x.x" app.kubernetes.io/managed-by: Helm spec: type: ClusterIP ports: - name: ss-8388 targetPort: 8388 protocol: TCP port: 80 selector: app.kubernetes.io/name: shadowsocks-rust app.kubernetes.io/instance: shadowsocks-rust --- # Source: shadowsocks-rust/templates/deployment.yaml apiVersion: apps/v1 kind: Deployment metadata: name: shadowsocks-rust labels: helm.sh/chart: shadowsocks-rust-0.1.0 app.kubernetes.io/name: shadowsocks-rust app.kubernetes.io/instance: shadowsocks-rust app.kubernetes.io/version: "1.x.x" app.kubernetes.io/managed-by: Helm spec: replicas: 1 selector: matchLabels: app.kubernetes.io/name: shadowsocks-rust app.kubernetes.io/instance: shadowsocks-rust template: metadata: labels: app.kubernetes.io/name: shadowsocks-rust app.kubernetes.io/instance: shadowsocks-rust spec: serviceAccountName: shadowsocks-rust securityContext: {} volumes: - name: config configMap: name: shadowsocks-rust - name: plugins emptyDir: {} containers: - name: shadowsocks-rust securityContext: {} image: "ghcr.io/shadowsocks/ssserver-rust:latest" imagePullPolicy: IfNotPresent volumeMounts: - name: config mountPath: /etc/shadowsocks-rust readOnly: true - name: plugins mountPath: /usr/local/bin ports: - name: ss-8388 containerPort: 8388 protocol: TCP livenessProbe: tcpSocket: port: 8388 failureThreshold: 3 initialDelaySeconds: 1 timeoutSeconds: 1 readinessProbe: tcpSocket: port: 8388 initialDelaySeconds: 2 resources: limits: cpu: 100m memory: 128Mi requests: cpu: 20m memory: 32Mi --- # Source: shadowsocks-rust/templates/tests/test-connection.yaml apiVersion: v1 kind: Pod metadata: name: "shadowsocks-rust-test-connection" labels: helm.sh/chart: shadowsocks-rust-0.1.0 app.kubernetes.io/name: shadowsocks-rust app.kubernetes.io/instance: shadowsocks-rust app.kubernetes.io/version: "1.x.x" app.kubernetes.io/managed-by: Helm annotations: "helm.sh/hook": test spec: containers: - name: wget image: busybox command: ['wget'] args: ['shadowsocks-rust:'] restartPolicy: Never ================================================ FILE: rustfmt.toml ================================================ edition = "2021" max_width = 120 #indent_style = "Visual" #fn_call_width = 120 reorder_imports = true reorder_modules = true #reorder_imports_in_group = true #reorder_imported_names = true condense_wildcard_suffixes = true #fn_args_layout = "Visual" #fn_call_style = "Visual" #chain_indent = "Visual" normalize_comments = true use_try_shorthand = true reorder_impl_items = true #use_small_heuristics = "Max" imports_layout = "HorizontalVertical" #imports_granularity = "Crate" ================================================ FILE: selinux/README.md ================================================ # Shadowsocks SELinux Policy ## Prerequisites Install required SELinux development tools: ```bash dnf upgrade && dnf install setools-console policycoreutils-python-utils selinux-policy-devel make ``` ## Creating SELinux Policy ### 1. Compile the policy ```bash make -f /usr/share/selinux/devel/Makefile shadowsocks.pp ``` ### 2. Install the policy module ```bash semodule -i shadowsocks.pp ``` ## Apply File Contexts ### 1. Add file context mappings ```bash semanage fcontext -a -t shadowsocks_exec_t "/usr/bin/ssservice" semanage fcontext -a -t shadowsocks_conf_t "/etc/shadowsocks(/.*)?" semanage fcontext -a -t shadowsocks_unit_file_t "/usr/lib/systemd/system/ss-server@.*\.service" ``` ### 2. Apply contexts to files ```bash restorecon -v /etc/systemd/system/ss-server@.service restorecon -R /usr/bin/ssservice /etc/shadowsocks ``` ### 3. Start the service ```bash systemctl start ss-server@main ``` ### 4. Verify the policy is working ```bash # Check that shadowsocks is running in the correct domain ps -eZ | grep ssservice # Should show: system_u:system_r:shadowsocks_t:s0 (not unconfined_service_t) ``` ## Troubleshooting ### Check for SELinux denials ```bash # View recent AVC denials ausearch -m avc -ts recent | grep denied # Generate additional policy rules if needed ausearch -m avc -ts recent | grep shadowsocks | audit2allow ``` ### Update policy if needed If you need to add more permissions: ```bash # Edit shadowsocks.te file # Recompile and update make -f /usr/share/selinux/devel/Makefile shadowsocks.pp semodule -u shadowsocks.pp ``` ### Remove policy (if needed) ```bash # Remove file contexts first semanage fcontext -d "/usr/bin/ssservice" semanage fcontext -d "/etc/shadowsocks(/.*)?" semanage fcontext -d "/usr/lib/systemd/system/ss-server@.*\.service" # Reset file labels restorecon -F /usr/bin/ssservice restorecon -RF /etc/shadowsocks # Remove the policy module semodule -r shadowsocks ``` ## Security Benefits This policy provides several security improvements over running shadowsocks as `unconfined_service_t`: - **Principle of least privilege**: Only grants necessary permissions - **Network isolation**: Controls which ports and connections are allowed - **File system protection**: Restricts file access to configuration and required system files - **Process isolation**: Runs in a dedicated SELinux domain - **Audit trail**: All access attempts are logged for security monitoring ## Notes - The policy includes optional monitoring features (cgroup access, DNS watching) - File contexts use equivalency rules between `/etc/systemd/system` and `/usr/lib/systemd/system` ================================================ FILE: selinux/shadowsocks.fc ================================================ /usr/bin/ssservice -- gen_context(system_u:object_r:shadowsocks_exec_t,s0) /etc/shadowsocks(/.*)? -- gen_context(system_u:object_r:shadowsocks_conf_t,s0) /usr/lib/systemd/system/ss-server@.*\.service -- gen_context(system_u:object_r:shadowsocks_unit_file_t,s0) ================================================ FILE: selinux/shadowsocks.te ================================================ policy_module(shadowsocks, 1.0.0) ######################################## # # Declarations # type shadowsocks_t; type shadowsocks_exec_t; init_daemon_domain(shadowsocks_t, shadowsocks_exec_t) type shadowsocks_conf_t; files_config_file(shadowsocks_conf_t) type shadowsocks_unit_file_t; systemd_unit_file(shadowsocks_unit_file_t) ######################################## # # shadowsocks local policy # # Domain transition rules domain_auto_trans(init_t, shadowsocks_exec_t, shadowsocks_t) allow init_t shadowsocks_t:process2 nnp_transition; # Allow shadowsocks to use its own executable as entrypoint allow shadowsocks_t shadowsocks_exec_t:file { entrypoint ioctl lock }; # Network sockets allow shadowsocks_t self:tcp_socket create_stream_socket_perms; allow shadowsocks_t self:udp_socket create_socket_perms; allow shadowsocks_t self:process signal_perms; # Configuration files allow shadowsocks_t shadowsocks_conf_t:file read_file_perms; allow shadowsocks_t shadowsocks_conf_t:dir list_dir_perms; # Network access corenet_tcp_bind_generic_node(shadowsocks_t) corenet_udp_bind_generic_node(shadowsocks_t) corenet_tcp_connect_all_ports(shadowsocks_t) corenet_tcp_bind_all_ports(shadowsocks_t) corenet_udp_bind_all_ports(shadowsocks_t) # System access kernel_read_system_state(shadowsocks_t) dev_read_urand(shadowsocks_t) files_read_etc_files(shadowsocks_t) miscfiles_read_localization(shadowsocks_t) logging_send_syslog_msg(shadowsocks_t) # Network configuration and DNS resolution sysnet_read_config(shadowsocks_t) sysnet_dns_name_resolve(shadowsocks_t) allow shadowsocks_t net_conf_t:file { read_file_perms watch }; # Cgroup access for resource monitoring fs_search_cgroup_dirs(shadowsocks_t) fs_getattr_cgroup(shadowsocks_t) allow shadowsocks_t cgroup_t:file { getattr open read }; allow shadowsocks_t cgroup_t:dir { search getattr }; ================================================ FILE: snap/snapcraft.yaml ================================================ name: shadowsocks-rust adopt-info: shadowsocks-rust summary: Rust port of Shadowsocks description: | Shadowsocks Client & Server, written in Rust. base: core22 grade: stable confinement: strict architectures: - build-on: amd64 - build-on: arm64 - build-on: armhf - build-on: ppc64el - build-on: s390x - build-on: riscv64 license: MIT source-code: https://github.com/shadowsocks/shadowsocks-rust apps: sslocal: command: bin/sslocal plugs: [network, network-bind, network-control, home] aliases: [sslocal] sslocal-daemon: command: bin/sslocal daemon: simple install-mode: disable plugs: [network, network-bind, network-control, home] ssserver: command: bin/ssserver plugs: [network, network-bind, home] aliases: [ssserver] ssserver-daemon: command: bin/ssserver daemon: simple install-mode: disable plugs: [network, network-bind, home] ssservice: command: bin/ssservice plugs: [network, network-bind, network-control, home] aliases: [ssservice] ssurl: command: bin/ssurl aliases: [ssurl] ssmanager: command: bin/ssmanager plugs: [network, network-bind, home] aliases: [ssmanager] passthrough: layout: /etc/shadowsocks-rust: bind: $SNAP_COMMON/etc/shadowsocks-rust parts: shadowsocks-rust: plugin: rust source: https://github.com/shadowsocks/shadowsocks-rust.git rust-channel: stable rust-features: [full] override-pull: | craftctl default craftctl set version=`git describe --tags --long | sed 's/\([^-]*-g\)/r\1/;s/-/./g'` build-packages: - rustc - cargo - cmake - bindgen - llvm-dev - libclang-dev - clang ================================================ FILE: src/allocator/mod.rs ================================================ //! Memory allocator #[cfg(feature = "jemalloc")] #[global_allocator] static ALLOC: jemallocator::Jemalloc = jemallocator::Jemalloc; #[cfg(feature = "tcmalloc")] #[global_allocator] static ALLOC: tcmalloc::TCMalloc = tcmalloc::TCMalloc; #[cfg(feature = "mimalloc")] #[global_allocator] static ALLOC: mimalloc::MiMalloc = mimalloc::MiMalloc; #[cfg(feature = "snmalloc")] #[global_allocator] static ALLOC: snmalloc_rs::SnMalloc = snmalloc_rs::SnMalloc; #[cfg(feature = "rpmalloc")] #[global_allocator] static ALLOC: rpmalloc::RpMalloc = rpmalloc::RpMalloc; ================================================ FILE: src/config.rs ================================================ //! Common configuration utilities use std::{ env, fs::OpenOptions, io::{self, Read}, path::{Path, PathBuf}, }; use clap::ArgMatches; use directories::ProjectDirs; use serde::Deserialize; /// Default configuration file path pub fn get_default_config_path(config_file: &str) -> Option { // config.json in the current working directory ($PWD) let config_files = vec![config_file, "config.json"]; if let Ok(mut path) = env::current_dir() { for filename in &config_files { path.push(filename); if path.exists() { return Some(path); } path.pop(); } } else { // config.json in the current working directory (relative path) for filename in &config_files { let relative_path = PathBuf::from(filename); if relative_path.exists() { return Some(relative_path); } } } // System standard directories if let Some(project_dirs) = ProjectDirs::from("org", "shadowsocks", "shadowsocks-rust") { // Linux: $XDG_CONFIG_HOME/shadowsocks-rust/config.json // $HOME/.config/shadowsocks-rust/config.json // macOS: $HOME/Library/Application Support/org.shadowsocks.shadowsocks-rust/config.json // Windows: {FOLDERID_RoamingAppData}/shadowsocks/shadowsocks-rust/config/config.json let mut config_path = project_dirs.config_dir().to_path_buf(); for filename in &config_files { config_path.push(filename); if config_path.exists() { return Some(config_path); } config_path.pop(); } } // UNIX systems, XDG Base Directory // https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html #[cfg(unix)] { let base_directories = xdg::BaseDirectories::with_prefix("shadowsocks-rust"); // $XDG_CONFIG_HOME/shadowsocks-rust/config.json // for dir in $XDG_CONFIG_DIRS; $dir/shadowsocks-rust/config.json for filename in &config_files { if let Some(config_path) = base_directories.find_config_file(filename) { return Some(config_path); } } } // UNIX global configuration file #[cfg(unix)] { let mut global_config_path = PathBuf::from("/etc/shadowsocks-rust"); for filename in &config_files { global_config_path.push(filename); if global_config_path.exists() { return Some(global_config_path.to_path_buf()); } global_config_path.pop(); } } None } /// Error while reading `Config` #[derive(thiserror::Error, Debug)] pub enum ConfigError { /// Input/Output error #[error("{0}")] IoError(#[from] io::Error), /// JSON parsing error #[error("{0}")] JsonError(#[from] json5::Error), /// Invalid value #[error("Invalid value: {0}")] InvalidValue(String), } /// Configuration Options for shadowsocks service runnables #[derive(Deserialize, Debug, Clone, Default)] #[serde(default)] pub struct Config { /// Logger configuration #[cfg(feature = "logging")] pub log: LogConfig, /// Runtime configuration pub runtime: RuntimeConfig, } impl Config { /// Load `Config` from file pub fn load_from_file>(filename: &P) -> Result { let filename = filename.as_ref(); let mut reader = OpenOptions::new().read(true).open(filename)?; let mut content = String::new(); reader.read_to_string(&mut content)?; Self::load_from_str(&content) } /// Load `Config` from string pub fn load_from_str(s: &str) -> Result { json5::from_str(s).map_err(ConfigError::from) } /// Set by command line options pub fn set_options(&mut self, matches: &ArgMatches) { #[cfg(feature = "logging")] { let debug_level = matches.get_count("VERBOSE"); if debug_level > 0 { self.log.level = debug_level as u32; } if matches.get_flag("LOG_WITHOUT_TIME") { self.log.format.without_time = true; } if let Some(log_config) = matches.get_one::("LOG_CONFIG").cloned() { self.log.config_path = Some(log_config); } } #[cfg(feature = "multi-threaded")] if matches.get_flag("SINGLE_THREADED") { self.runtime.mode = RuntimeMode::SingleThread; } #[cfg(feature = "multi-threaded")] if let Some(worker_count) = matches.get_one::("WORKER_THREADS") { self.runtime.worker_count = Some(*worker_count); } // suppress unused warning let _ = matches; } } /// Logger configuration #[cfg(feature = "logging")] #[derive(Deserialize, Debug, Clone)] #[serde(default)] pub struct LogConfig { /// Default log level for all writers, [0, 3] pub level: u32, /// Default format configuration for all writers pub format: LogFormatConfig, /// Log writers configuration pub writers: Vec, /// Deprecated: Path to the `log4rs` config file pub config_path: Option, } #[cfg(feature = "logging")] impl Default for LogConfig { fn default() -> Self { LogConfig { level: 0, format: LogFormatConfig::default(), writers: vec![LogWriterConfig::Console(LogConsoleWriterConfig::default())], config_path: None, } } } /// Logger format configuration #[cfg(feature = "logging")] #[derive(Deserialize, Debug, Clone, Default, Eq, PartialEq)] #[serde(default)] pub struct LogFormatConfig { pub without_time: bool, } /// Holds writer-specific configuration for logging #[cfg(feature = "logging")] #[derive(Deserialize, Debug, Clone)] #[serde(rename_all = "snake_case")] pub enum LogWriterConfig { Console(LogConsoleWriterConfig), File(LogFileWriterConfig), #[cfg(unix)] Syslog(LogSyslogWriterConfig), } /// Console appender configuration for logging #[cfg(feature = "logging")] #[derive(Deserialize, Debug, Clone, Default)] pub struct LogConsoleWriterConfig { /// Level override #[serde(default)] pub level: Option, /// Format override #[serde(default)] pub format: LogFormatConfigOverride, } /// Logger format override #[cfg(feature = "logging")] #[derive(Deserialize, Debug, Clone, Default)] #[serde(default)] pub struct LogFormatConfigOverride { pub without_time: Option, } /// File appender configuration for logging #[cfg(feature = "logging")] #[derive(Deserialize, Debug, Clone)] pub struct LogFileWriterConfig { /// Level override #[serde(default)] pub level: Option, /// Format override #[serde(default)] pub format: LogFormatConfigOverride, /// Directory to store log files pub directory: PathBuf, /// Rotation strategy for log files. Default is `Rotation::NEVER`. #[serde(default)] pub rotation: LogRotation, /// Prefix for log file names. Default is the binary name. #[serde(default)] pub prefix: Option, /// Suffix for log file names. Default is "log". #[serde(default)] pub suffix: Option, /// Maximum number of log files to keep. Default is `None`, meaning no limit. #[serde(default)] pub max_files: Option, } /// Log rotation frequency #[cfg(feature = "logging")] #[derive(Deserialize, Debug, Copy, Clone, Default, Eq, PartialEq)] #[serde(rename_all = "snake_case")] pub enum LogRotation { #[default] Never, Hourly, Daily, } #[cfg(feature = "logging")] impl From for tracing_appender::rolling::Rotation { fn from(rotation: LogRotation) -> Self { match rotation { LogRotation::Never => Self::NEVER, LogRotation::Hourly => Self::HOURLY, LogRotation::Daily => Self::DAILY, } } } /// File appender configuration for logging #[cfg(all(feature = "logging", unix))] #[derive(Deserialize, Debug, Clone)] pub struct LogSyslogWriterConfig { /// Level override #[serde(default)] pub level: Option, /// Format override #[serde(default)] pub format: LogFormatConfigOverride, /// syslog identity, process name by default #[serde(default)] pub identity: Option, /// Facility, 1 (USER) by default #[serde(default)] pub facility: Option, } /// Runtime mode (Tokio) #[derive(Deserialize, Debug, Clone, Copy, Default, Eq, PartialEq)] #[serde(rename_all = "snake_case")] pub enum RuntimeMode { /// Single-Thread Runtime #[cfg_attr(not(feature = "multi-threaded"), default)] SingleThread, /// Multi-Thread Runtime #[cfg(feature = "multi-threaded")] #[cfg_attr(feature = "multi-threaded", default)] MultiThread, } /// Runtime configuration #[derive(Deserialize, Debug, Clone, Default)] #[serde(default)] pub struct RuntimeConfig { /// Multithread runtime worker count, CPU count if not configured #[cfg(feature = "multi-threaded")] pub worker_count: Option, /// Runtime Mode, single-thread, multi-thread pub mode: RuntimeMode, } #[cfg(test)] mod tests { use super::*; #[test] fn test_deser_empty() { // empty config should load successfully let config: Config = Config::load_from_str("{}").unwrap(); assert_eq!(config.runtime.mode, RuntimeMode::default()); #[cfg(feature = "multi-threaded")] { assert!(config.runtime.worker_count.is_none()); } #[cfg(feature = "logging")] { assert_eq!(config.log.level, 0); assert!(!config.log.format.without_time); // default writer configuration should contain a stdout writer assert_eq!(config.log.writers.len(), 1); if let LogWriterConfig::Console(stdout_config) = &config.log.writers[0] { assert_eq!(stdout_config.level, None); assert_eq!(stdout_config.format.without_time, None); } else { panic!("Expected a stdout writer configuration"); } } } #[test] fn test_deser_disable_logging() { // allow user explicitly disable logging by providing an empty writers array let config_str = r#" { "log": { "writers": [] } } "#; let config: Config = Config::load_from_str(config_str).unwrap(); #[cfg(feature = "logging")] { assert_eq!(config.log.level, 0); assert!(!config.log.format.without_time); assert!(config.log.writers.is_empty()); } } #[test] fn test_deser_file_writer_full() { let config_str = r#" { "log": { "writers": [ { "file": { "level": 2, "format": { "without_time": true }, "directory": "/var/log/shadowsocks", "rotation": "daily", "prefix": "ss-rust", "suffix": "log", "max_files": 5 } } ] } } "#; let config: Config = Config::load_from_str(config_str).unwrap(); #[cfg(feature = "logging")] { assert_eq!(config.log.writers.len(), 1); if let LogWriterConfig::File(file_config) = &config.log.writers[0] { assert_eq!(file_config.level, Some(2)); assert_eq!(file_config.format.without_time, Some(true)); assert_eq!(file_config.directory, PathBuf::from("/var/log/shadowsocks")); assert_eq!(file_config.rotation, LogRotation::Daily); assert_eq!(file_config.prefix.as_deref(), Some("ss-rust")); assert_eq!(file_config.suffix.as_deref(), Some("log")); assert_eq!(file_config.max_files, Some(5)); } else { panic!("Expected a file writer configuration"); } } } #[test] fn test_deser_file_writer_minimal() { // Minimal valid file writer configuration let config_str = r#" { "log": { "writers": [ { "file": { "directory": "/var/log/shadowsocks" } } ] } } "#; let config: Config = Config::load_from_str(config_str).unwrap(); #[cfg(feature = "logging")] { assert_eq!(config.log.writers.len(), 1); if let LogWriterConfig::File(file_config) = &config.log.writers[0] { assert_eq!(file_config.level, None); assert_eq!(file_config.format.without_time, None); assert_eq!(file_config.directory, PathBuf::from("/var/log/shadowsocks")); assert_eq!(file_config.rotation, LogRotation::Never); assert!(file_config.prefix.is_none()); assert!(file_config.suffix.is_none()); assert!(file_config.max_files.is_none()); } else { panic!("Expected a file writer configuration"); } } } #[test] fn test_deser_console_writer_full() { let config_str = r#" { "log": { "writers": [ { "console": { "level": 1, "format": { "without_time": false } } } ] } } "#; let config: Config = Config::load_from_str(config_str).unwrap(); #[cfg(feature = "logging")] { assert_eq!(config.log.writers.len(), 1); if let LogWriterConfig::Console(stdout_config) = &config.log.writers[0] { assert_eq!(stdout_config.level, Some(1)); assert_eq!(stdout_config.format.without_time, Some(false)); } else { panic!("Expected a console writer configuration"); } } } #[test] fn test_deser_console_writer_minimal() { // Minimal valid console writer configuration let config_str = r#" { "log": { "writers": [ { "console": {} } ] } } "#; let config: Config = Config::load_from_str(config_str).unwrap(); #[cfg(feature = "logging")] { assert_eq!(config.log.writers.len(), 1); if let LogWriterConfig::Console(stdout_config) = &config.log.writers[0] { assert_eq!(stdout_config.level, None); assert_eq!(stdout_config.format.without_time, None); } else { panic!("Expected a console writer configuration"); } } } } ================================================ FILE: src/daemonize/daemonize/error.rs ================================================ pub type Errno = libc::c_int; /// This error type for `Daemonize` `start` method. #[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone)] pub struct Error { kind: ErrorKind, } /// This error type for `Daemonize` `start` method. #[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone)] pub enum ErrorKind { Fork(Errno), Wait(Errno), DetachSession(Errno), GroupNotFound, GroupContainsNul, SetGroup(Errno), UserNotFound, UserContainsNul, SetUser(Errno), ChangeDirectory(Errno), PathContainsNul, OpenPidfile(Errno), GetPidfileFlags(Errno), SetPidfileFlags(Errno), LockPidfile(Errno), ChownPidfile(Errno), OpenDevnull(Errno), RedirectStreams(Errno), CloseDevnull(Errno), TruncatePidfile(Errno), WritePid(Errno), WritePidUnspecifiedError, Chroot(Errno), } impl ErrorKind { fn description(&self) -> &str { match self { ErrorKind::Fork(_) => "unable to fork", ErrorKind::Wait(_) => "wait failed", ErrorKind::DetachSession(_) => "unable to create new session", ErrorKind::GroupNotFound => "unable to resolve group name to group id", ErrorKind::GroupContainsNul => "group option contains NUL", ErrorKind::SetGroup(_) => "unable to set group", ErrorKind::UserNotFound => "unable to resolve user name to user id", ErrorKind::UserContainsNul => "user option contains NUL", ErrorKind::SetUser(_) => "unable to set user", ErrorKind::ChangeDirectory(_) => "unable to change directory", ErrorKind::PathContainsNul => "pid_file option contains NUL", ErrorKind::OpenPidfile(_) => "unable to open pid file", ErrorKind::GetPidfileFlags(_) => "unable get pid file flags", ErrorKind::SetPidfileFlags(_) => "unable set pid file flags", ErrorKind::LockPidfile(_) => "unable to lock pid file", ErrorKind::ChownPidfile(_) => "unable to chown pid file", ErrorKind::OpenDevnull(_) => "unable to open /dev/null", ErrorKind::RedirectStreams(_) => "unable to redirect standard streams to /dev/null", ErrorKind::CloseDevnull(_) => "unable to close /dev/null", ErrorKind::TruncatePidfile(_) => "unable to truncate pid file", ErrorKind::WritePid(_) => "unable to write self pid to pid file", ErrorKind::WritePidUnspecifiedError => "unable to write self pid to pid file due to unknown reason", ErrorKind::Chroot(_) => "unable to chroot into directory", } } fn errno(&self) -> Option { match self { ErrorKind::Fork(errno) => Some(*errno), ErrorKind::Wait(errno) => Some(*errno), ErrorKind::DetachSession(errno) => Some(*errno), ErrorKind::GroupNotFound => None, ErrorKind::GroupContainsNul => None, ErrorKind::SetGroup(errno) => Some(*errno), ErrorKind::UserNotFound => None, ErrorKind::UserContainsNul => None, ErrorKind::SetUser(errno) => Some(*errno), ErrorKind::ChangeDirectory(errno) => Some(*errno), ErrorKind::PathContainsNul => None, ErrorKind::OpenPidfile(errno) => Some(*errno), ErrorKind::GetPidfileFlags(errno) => Some(*errno), ErrorKind::SetPidfileFlags(errno) => Some(*errno), ErrorKind::LockPidfile(errno) => Some(*errno), ErrorKind::ChownPidfile(errno) => Some(*errno), ErrorKind::OpenDevnull(errno) => Some(*errno), ErrorKind::RedirectStreams(errno) => Some(*errno), ErrorKind::CloseDevnull(errno) => Some(*errno), ErrorKind::TruncatePidfile(errno) => Some(*errno), ErrorKind::WritePid(errno) => Some(*errno), ErrorKind::WritePidUnspecifiedError => None, ErrorKind::Chroot(errno) => Some(*errno), } } } impl std::fmt::Display for ErrorKind { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { f.write_str(self.description())?; if let Some(errno) = self.errno() { write!(f, ", errno {}", errno)? } Ok(()) } } impl std::error::Error for ErrorKind {} impl std::fmt::Display for Error { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "{}", self.kind) } } impl std::error::Error for Error {} impl From for Error { fn from(kind: ErrorKind) -> Self { Self { kind } } } pub trait Num { fn is_err(&self) -> bool; } impl Num for i8 { fn is_err(&self) -> bool { *self == -1 } } impl Num for i16 { fn is_err(&self) -> bool { *self == -1 } } impl Num for i32 { fn is_err(&self) -> bool { *self == -1 } } impl Num for i64 { fn is_err(&self) -> bool { *self == -1 } } impl Num for isize { fn is_err(&self) -> bool { *self == -1 } } pub fn check_err ErrorKind>(ret: N, f: F) -> Result { if ret.is_err() { Err(f(errno())) } else { Ok(ret) } } pub fn errno() -> Errno { std::io::Error::last_os_error().raw_os_error().expect("errno") } ================================================ FILE: src/daemonize/daemonize/mod.rs ================================================ // Copyright (c) 2016 Fedor Gogolev // // Licensed under the Apache License, Version 2.0 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. //! daemonize is a library for writing system daemons. Inspired by the Python library [thesharp/daemonize](https://github.com/thesharp/daemonize). //! //! The respository is located at . //! //! Usage example: //! //! ```rust,ignore //! use std::fs::File; //! //! use Daemonize; //! //! fn main() { //! let stdout = File::create("/tmp/daemon.out").unwrap(); //! let stderr = File::create("/tmp/daemon.err").unwrap(); //! //! let daemonize = Daemonize::new() //! .pid_file("/tmp/test.pid") // Every method except `new` and `start` //! .chown_pid_file(true) // is optional, see `Daemonize` documentation //! .working_directory("/tmp") // for default behaviour. //! .user("nobody") //! .group("daemon") // Group name //! .group(2) // or group id. //! .umask(0o777) // Set umask, `0o027` by default. //! .stdout(stdout) // Redirect stdout to `/tmp/daemon.out`. //! .stderr(stderr) // Redirect stderr to `/tmp/daemon.err`. //! .privileged_action(|| "Executed before drop privileges"); //! //! match daemonize.start() { //! Ok(_) => println!("Success, daemonized"), //! Err(e) => eprintln!("Error, {}", e), //! } //! } //! ``` mod error; use std::env::set_current_dir; use std::ffi::CString; use std::fmt; use std::fs::File; use std::os::unix::ffi::OsStringExt; use std::os::unix::io::AsRawFd; use std::path::{Path, PathBuf}; use std::process::exit; use self::error::{ErrorKind, check_err, errno}; pub use self::error::Error; #[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone)] enum UserImpl { Name(String), Id(libc::uid_t), } /// Expects system user id or name. If name is provided it will be resolved to id later. #[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone)] pub struct User { inner: UserImpl, } impl From<&str> for User { fn from(t: &str) -> User { User { inner: UserImpl::Name(t.to_owned()), } } } impl From for User { fn from(t: u32) -> User { User { inner: UserImpl::Id(t as libc::uid_t), } } } #[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone)] enum GroupImpl { Name(String), Id(libc::gid_t), } /// Expects system group id or name. If name is provided it will be resolved to id later. #[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone)] pub struct Group { inner: GroupImpl, } impl From<&str> for Group { fn from(t: &str) -> Group { Group { inner: GroupImpl::Name(t.to_owned()), } } } impl From for Group { fn from(t: u32) -> Group { Group { inner: GroupImpl::Id(t as libc::gid_t), } } } /// File mode creation mask. #[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone)] pub struct Mask { inner: libc::mode_t, } impl From for Mask { fn from(inner: u32) -> Mask { Mask { inner: inner as libc::mode_t, } } } #[derive(Debug)] enum StdioImpl { Devnull, RedirectToFile(File), Keep, } /// Describes what to do with a standard I/O stream for a child process. #[derive(Debug)] pub struct Stdio { inner: StdioImpl, } impl Stdio { pub fn devnull() -> Self { Self { inner: StdioImpl::Devnull, } } pub fn keep() -> Self { Self { inner: StdioImpl::Keep } } } impl From for Stdio { fn from(file: File) -> Self { Self { inner: StdioImpl::RedirectToFile(file), } } } /// Parent process execution outcome. #[derive(Debug, PartialEq, Eq, PartialOrd, Ord)] #[non_exhaustive] pub struct Parent { pub first_child_exit_code: i32, } /// Child process execution outcome. #[derive(Debug, PartialEq, Eq, PartialOrd, Ord)] #[non_exhaustive] pub struct Child { pub privileged_action_result: T, } /// Daemonization process outcome. Can be matched to check is it a parent process or a child /// process. #[derive(Debug, PartialEq, Eq, PartialOrd, Ord)] pub enum Outcome { Parent(Result), Child(Result, Error>), } impl Outcome { pub fn is_parent(&self) -> bool { match self { Outcome::Parent(_) => true, Outcome::Child(_) => false, } } pub fn is_child(&self) -> bool { match self { Outcome::Parent(_) => false, Outcome::Child(_) => true, } } } /// Daemonization options. /// /// Fork the process in the background, disassociate from its process group and the control terminal. /// Change umask value to `0o027`, redirect all standard streams to `/dev/null`. Change working /// directory to `/` or provided value. /// /// Optionally: /// /// * maintain and lock the pid-file; /// * drop user privileges; /// * drop group privileges; /// * change root directory; /// * change the pid-file ownership to provided user (and/or) group; /// * execute any provided action just before dropping privileges. pub struct Daemonize { directory: PathBuf, pid_file: Option, chown_pid_file: bool, user: Option, group: Option, umask: Mask, root: Option, privileged_action: Box T>, stdin: Stdio, stdout: Stdio, stderr: Stdio, } impl fmt::Debug for Daemonize { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { fmt.debug_struct("Daemonize") .field("directory", &self.directory) .field("pid_file", &self.pid_file) .field("chown_pid_file", &self.chown_pid_file) .field("user", &self.user) .field("group", &self.group) .field("umask", &self.umask) .field("root", &self.root) .field("stdin", &self.stdin) .field("stdout", &self.stdout) .field("stderr", &self.stderr) .finish() } } impl Default for Daemonize<()> { fn default() -> Self { Self::new() } } impl Daemonize<()> { pub fn new() -> Self { Daemonize { directory: Path::new("/").to_owned(), pid_file: None, chown_pid_file: false, user: None, group: None, umask: 0o027.into(), privileged_action: Box::new(|| ()), root: None, stdin: Stdio::devnull(), stdout: Stdio::devnull(), stderr: Stdio::devnull(), } } } impl Daemonize { /// Create pid-file at `path`, lock it exclusive and write daemon pid. pub fn pid_file>(mut self, path: F) -> Self { self.pid_file = Some(path.as_ref().to_owned()); self } /// If `chown` is true, daemonize will change the pid-file ownership, if user or group are provided pub fn chown_pid_file(mut self, chown: bool) -> Self { self.chown_pid_file = chown; self } /// Change working directory to `path` or `/` by default. pub fn working_directory>(mut self, path: F) -> Self { self.directory = path.as_ref().to_owned(); self } /// Drop privileges to `user`. pub fn user>(mut self, user: U) -> Self { self.user = Some(user.into()); self } /// Drop privileges to `group`. pub fn group>(mut self, group: G) -> Self { self.group = Some(group.into()); self } /// Change umask to `mask` or `0o027` by default. pub fn umask>(mut self, mask: M) -> Self { self.umask = mask.into(); self } /// Change root to `path` pub fn chroot>(mut self, path: F) -> Self { self.root = Some(path.as_ref().to_owned()); self } /// Execute `action` just before dropping privileges. Most common use case is to open /// listening socket. Result of `action` execution will be returned by `start` method. pub fn privileged_action N + 'static>(self, action: F) -> Daemonize { Daemonize { directory: self.directory, pid_file: self.pid_file, chown_pid_file: self.chown_pid_file, user: self.user, group: self.group, umask: self.umask, root: self.root, privileged_action: Box::new(action), stdin: self.stdin, stdout: self.stdout, stderr: self.stderr, } } /// Configuration for the child process's standard output stream. pub fn stdout>(mut self, stdio: S) -> Self { self.stdout = stdio.into(); self } /// Configuration for the child process's standard error stream. pub fn stderr>(mut self, stdio: S) -> Self { self.stderr = stdio.into(); self } /// Start daemonization process, terminate parent after first fork, returns privileged action /// result to the child. pub fn start(self) -> Result { match self.execute() { Outcome::Parent(Ok(Parent { first_child_exit_code })) => exit(first_child_exit_code), Outcome::Parent(Err(err)) => Err(err), Outcome::Child(Ok(child)) => Ok(child.privileged_action_result), Outcome::Child(Err(err)) => Err(err), } } /// Execute daemonization process, don't terminate parent after first fork. pub fn execute(self) -> Outcome { unsafe { match perform_fork() { Ok(Some(first_child_pid)) => Outcome::Parent(match waitpid(first_child_pid) { Err(err) => Err(err.into()), // return value of `waitpid` may not be i32 on all platforms. #[allow(clippy::unnecessary_cast)] Ok(first_child_exit_code) => Ok(Parent { first_child_exit_code: first_child_exit_code as i32, }), }), Err(err) => Outcome::Parent(Err(err.into())), Ok(None) => match self.execute_child() { Ok(privileged_action_result) => Outcome::Child(Ok(Child { privileged_action_result, })), Err(err) => Outcome::Child(Err(err.into())), }, } } } fn execute_child(self) -> Result { unsafe { set_current_dir(&self.directory).map_err(|_| ErrorKind::ChangeDirectory(errno()))?; set_sid()?; libc::umask(self.umask.inner); let pid_file_fd = self .pid_file .clone() .map(|pid_file| create_pid_file(pid_file)) .transpose()?; if perform_fork()?.is_some() { exit(0) }; redirect_standard_streams(self.stdin, self.stdout, self.stderr)?; let uid = self.user.map(|user| get_user(user)).transpose()?; let gid = self.group.map(|group| get_group(group)).transpose()?; if self.chown_pid_file { let args: Option<(PathBuf, libc::uid_t, libc::gid_t)> = match (self.pid_file, uid, gid) { (Some(pid), Some(uid), Some(gid)) => Some((pid, uid, gid)), (Some(pid), None, Some(gid)) => Some((pid, libc::getuid(), gid)), (Some(pid), Some(uid), None) => Some((pid, uid, libc::getgid())), // Or pid file is not provided, or both user and group _ => None, }; if let Some((pid, uid, gid)) = args { chown_pid_file(pid, uid, gid)?; } } if let Some(pid_file_fd) = pid_file_fd { set_cloexec_pid_file(pid_file_fd)?; } let privileged_action_result = (self.privileged_action)(); if let Some(root) = self.root { change_root(root)?; } if let Some(gid) = gid { set_group(gid)?; } if let Some(uid) = uid { set_user(uid)?; } if let Some(pid_file_fd) = pid_file_fd { write_pid_file(pid_file_fd)?; } Ok(privileged_action_result) } } } unsafe fn perform_fork() -> Result, ErrorKind> { let pid = check_err(libc::fork(), ErrorKind::Fork)?; if pid == 0 { Ok(None) } else { Ok(Some(pid)) } } unsafe fn waitpid(pid: libc::pid_t) -> Result { let mut child_stat = 0; check_err(libc::waitpid(pid, &mut child_stat, 0), ErrorKind::Wait)?; Ok(libc::WEXITSTATUS(child_stat)) } unsafe fn set_sid() -> Result<(), ErrorKind> { check_err(libc::setsid(), ErrorKind::DetachSession)?; Ok(()) } unsafe fn redirect_standard_streams(stdin: Stdio, stdout: Stdio, stderr: Stdio) -> Result<(), ErrorKind> { let devnull_fd = check_err( libc::open(b"/dev/null\0" as *const [u8; 10] as _, libc::O_RDWR), ErrorKind::OpenDevnull, )?; let process_stdio = |fd, stdio: Stdio| { match stdio.inner { StdioImpl::Devnull => { check_err(libc::dup2(devnull_fd, fd), ErrorKind::RedirectStreams)?; } StdioImpl::RedirectToFile(file) => { let raw_fd = file.as_raw_fd(); check_err(libc::dup2(raw_fd, fd), ErrorKind::RedirectStreams)?; } StdioImpl::Keep => (), }; Ok(()) }; process_stdio(libc::STDIN_FILENO, stdin)?; process_stdio(libc::STDOUT_FILENO, stdout)?; process_stdio(libc::STDERR_FILENO, stderr)?; check_err(libc::close(devnull_fd), ErrorKind::CloseDevnull)?; Ok(()) } unsafe fn get_group(group: Group) -> Result { match group.inner { GroupImpl::Id(id) => Ok(id), GroupImpl::Name(name) => { let s = CString::new(name).map_err(|_| ErrorKind::GroupContainsNul)?; match get_gid_by_name(&s) { Some(id) => get_group(id.into()), None => Err(ErrorKind::GroupNotFound), } } } } unsafe fn set_group(group: libc::gid_t) -> Result<(), ErrorKind> { check_err(libc::setregid(group, group), ErrorKind::SetGroup)?; Ok(()) } unsafe fn get_user(user: User) -> Result { match user.inner { UserImpl::Id(id) => Ok(id), UserImpl::Name(name) => { let s = CString::new(name).map_err(|_| ErrorKind::UserContainsNul)?; match get_uid_by_name(&s) { Some(id) => get_user(id.into()), None => Err(ErrorKind::UserNotFound), } } } } unsafe fn set_user(user: libc::uid_t) -> Result<(), ErrorKind> { check_err(libc::setreuid(user, user), ErrorKind::SetUser)?; Ok(()) } unsafe fn create_pid_file(path: PathBuf) -> Result { let path_c = pathbuf_into_cstring(path)?; let fd = check_err( libc::open(path_c.as_ptr(), libc::O_WRONLY | libc::O_CREAT, 0o666), ErrorKind::OpenPidfile, )?; check_err(libc::flock(fd, libc::LOCK_EX | libc::LOCK_NB), ErrorKind::LockPidfile)?; Ok(fd) } unsafe fn chown_pid_file(path: PathBuf, uid: libc::uid_t, gid: libc::gid_t) -> Result<(), ErrorKind> { let path_c = pathbuf_into_cstring(path)?; check_err(libc::chown(path_c.as_ptr(), uid, gid), ErrorKind::ChownPidfile)?; Ok(()) } unsafe fn write_pid_file(fd: libc::c_int) -> Result<(), ErrorKind> { let pid = libc::getpid(); let pid_buf = format!("{}\n", pid).into_bytes(); let pid_length = pid_buf.len(); let pid_c = CString::new(pid_buf).unwrap(); check_err(libc::ftruncate(fd, 0), ErrorKind::TruncatePidfile)?; let written = check_err( libc::write(fd, pid_c.as_ptr() as *const libc::c_void, pid_length), ErrorKind::WritePid, )?; if written < pid_length as isize { return Err(ErrorKind::WritePidUnspecifiedError); } Ok(()) } unsafe fn set_cloexec_pid_file(fd: libc::c_int) -> Result<(), ErrorKind> { if cfg!(not(target_os = "redox")) { let flags = check_err(libc::fcntl(fd, libc::F_GETFD), ErrorKind::GetPidfileFlags)?; check_err( libc::fcntl(fd, libc::F_SETFD, flags | libc::FD_CLOEXEC), ErrorKind::SetPidfileFlags, )?; } else { check_err(libc::ioctl(fd, libc::FIOCLEX), ErrorKind::SetPidfileFlags)?; } Ok(()) } unsafe fn change_root(path: PathBuf) -> Result<(), ErrorKind> { let path_c = pathbuf_into_cstring(path)?; check_err(libc::chroot(path_c.as_ptr()), ErrorKind::Chroot)?; Ok(()) } unsafe fn get_gid_by_name(name: &CString) -> Option { let ptr = libc::getgrnam(name.as_ptr() as *const libc::c_char); if ptr.is_null() { None } else { let s = &*ptr; Some(s.gr_gid) } } unsafe fn get_uid_by_name(name: &CString) -> Option { let ptr = libc::getpwnam(name.as_ptr() as *const libc::c_char); if ptr.is_null() { None } else { let s = &*ptr; Some(s.pw_uid) } } fn pathbuf_into_cstring(path: PathBuf) -> Result { CString::new(path.into_os_string().into_vec()).map_err(|_| ErrorKind::PathContainsNul) } ================================================ FILE: src/daemonize/mod.rs ================================================ //! Daemonize server process use cfg_if::cfg_if; cfg_if! { if #[cfg(unix)] { mod unix; #[allow(unsafe_op_in_unsafe_fn, unused)] #[allow(clippy::module_inception)] mod daemonize; pub use self::unix::daemonize; } else { compile_error!("Process daemonization is not supported by the current platform"); } } ================================================ FILE: src/daemonize/unix.rs ================================================ use std::{env::current_dir, path::Path}; use super::daemonize::Daemonize; use log::error; /// Daemonize a server process in a *nix standard way /// /// This function will redirect `stdout`, `stderr` to `/dev/null`, /// and follow the exact behavior in shadowsocks-libev pub fn daemonize>(pid_path: Option) { let pwd = current_dir() .unwrap_or_else(|err| panic!("cannot get current working directory, {err:?}")) .canonicalize() .unwrap_or_else(|err| panic!("cannot get absolute path to working directory, {err:?}")); let mut d = Daemonize::new().umask(0).working_directory(pwd); if let Some(p) = pid_path { d = d.pid_file(p); } if let Err(err) = d.start() { error!("failed to daemonize, {:?} ({})", err, err); } } ================================================ FILE: src/error.rs ================================================ //! Shadowsocks-specific error encoding. /// A result with a shadowsocks-specific error. pub type ShadowsocksResult = Result; /// A generic error class which encodes all possible ways the application can /// fail, along with debug information. #[derive(Clone, Debug)] pub enum ShadowsocksError { ServerExitUnexpectedly(String), ServerAborted(String), LoadConfigFailure(String), LoadAclFailure(String), InsufficientParams(String), } impl ShadowsocksError { /// The corresponding `sysexits::ExitCode` for this error. pub fn exit_code(&self) -> sysexits::ExitCode { match self { Self::ServerExitUnexpectedly(_) | Self::ServerAborted(_) => sysexits::ExitCode::Software, Self::LoadConfigFailure(_) | Self::LoadAclFailure(_) => sysexits::ExitCode::Config, Self::InsufficientParams(_) => sysexits::ExitCode::Usage, } } } impl std::fmt::Display for ShadowsocksError { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { Self::ServerExitUnexpectedly(msg) | Self::ServerAborted(msg) | Self::LoadConfigFailure(msg) | Self::LoadAclFailure(msg) | Self::InsufficientParams(msg) => write!(f, "{msg}"), } } } impl std::error::Error for ShadowsocksError {} ================================================ FILE: src/lib.rs ================================================ //! Shadowsocks service command line utilities pub mod allocator; pub mod config; #[cfg(unix)] pub mod daemonize; pub mod error; #[cfg(feature = "logging")] pub mod logging; pub mod monitor; pub mod password; pub mod service; pub mod sys; pub mod vparser; /// Build timestamp in UTC pub const BUILD_TIME: &str = build_time::build_time_utc!(); /// shadowsocks version pub const VERSION: &str = env!("CARGO_PKG_VERSION"); ================================================ FILE: src/logging/log4rs.rs ================================================ //! Logging facilities with log4rs use std::path::Path; use log::LevelFilter; use log4rs::{ append::console::{ConsoleAppender, Target}, config::{Appender, Config, Logger, Root}, encode::pattern::PatternEncoder, }; use crate::config::LogConfig; /// Initialize logger ([log4rs](https://crates.io/crates/log4rs)) from yaml configuration file pub fn init_with_file

(path: P) where P: AsRef, { log4rs::init_file(path, Default::default()).expect("init logging with file"); } /// Initialize logger with provided configuration #[allow(dead_code)] pub fn init_with_config(bin_name: &str, config: &LogConfig) { let debug_level = config.level; let without_time = config.format.without_time; let mut pattern = String::new(); if !without_time { pattern += "{d} "; } pattern += "{h({l}):<5} "; if debug_level >= 1 { pattern += "[{P}:{I}] [{M}] "; } pattern += "{m}{n}"; let logging_builder = Config::builder().appender( Appender::builder().build( "console", Box::new( ConsoleAppender::builder() .encoder(Box::new(PatternEncoder::new(&pattern))) .target(Target::Stderr) .build(), ), ), ); let (l1, l2) = match debug_level { 0 => (LevelFilter::Info, LevelFilter::Off), 1 => (LevelFilter::Debug, LevelFilter::Off), 2 => (LevelFilter::Trace, LevelFilter::Off), 3 => (LevelFilter::Trace, LevelFilter::Debug), _ => (LevelFilter::Off, LevelFilter::Trace), }; let config = match debug_level { 0..=3 => logging_builder .logger(Logger::builder().build(bin_name, l1)) .logger(Logger::builder().build("shadowsocks_rust", l1)) .logger(Logger::builder().build("shadowsocks", l1)) .logger(Logger::builder().build("shadowsocks_service", l1)), _ => logging_builder, } .build(Root::builder().appender("console").build(l2)) .expect("logging"); log4rs::init_config(config).expect("logging"); } ================================================ FILE: src/logging/mod.rs ================================================ //! Logging facilities use std::path::Path; use log::warn; use crate::config::LogConfig; mod log4rs; mod tracing; /// Initialize [log4rs](https://crates.io/crates/log4rs) from yaml configuration file pub fn init_with_file

(path: P) where P: AsRef, { log4rs::init_with_file(path); warn!( "log4rs doesn't support the tracing (https://crates.io/crates/tracing) framework, so it would be removed in the future. Consider configure logging with RUST_LOG environment variable. Check more configuration detail in https://docs.rs/tracing-subscriber/latest/tracing_subscriber/fmt/index.html#filtering-events-with-environment-variables ." ); } /// Initialize logger with provided configuration pub fn init_with_config(bin_name: &str, config: &LogConfig) { tracing::init_with_config(bin_name, config); } /// Init a default logger pub fn init_with_default(bin_name: &str) { init_with_config(bin_name, &LogConfig::default()); } ================================================ FILE: src/logging/tracing.rs ================================================ //! Logging facilities with tracing use std::io::{self, IsTerminal}; #[cfg(unix)] use syslog_tracing::Syslog; use time::{UtcOffset, format_description::well_known::Rfc3339}; use tracing::level_filters::LevelFilter; use tracing_appender::rolling::{InitError, RollingFileAppender}; use tracing_subscriber::{ fmt::{MakeWriter, time::OffsetTime}, layer::SubscriberExt, util::SubscriberInitExt, {EnvFilter, Layer, Registry, fmt}, }; #[cfg(unix)] use crate::config::LogSyslogWriterConfig; use crate::config::{ LogConfig, LogConsoleWriterConfig, LogFileWriterConfig, LogFormatConfig, LogFormatConfigOverride, LogWriterConfig, }; /// Initialize logger with provided configuration pub fn init_with_config(bin_name: &str, config: &LogConfig) { let layers: Vec = config .writers .iter() .map(|writer| writer.make_layer(bin_name, config)) .collect(); tracing_subscriber::registry().with(layers).init(); } type BoxedLayer = Box + Send + Sync + 'static>; trait MakeLayer { fn make_layer(&self, bin_name: &str, global: &LogConfig) -> BoxedLayer; } impl MakeLayer for LogWriterConfig { fn make_layer(&self, bin_name: &str, global: &LogConfig) -> BoxedLayer { match self { LogWriterConfig::Console(console_config) => console_config.make_layer(bin_name, global), LogWriterConfig::File(file_config) => file_config.make_layer(bin_name, global), #[cfg(unix)] LogWriterConfig::Syslog(syslog_config) => syslog_config.make_layer(bin_name, global), } } } impl MakeLayer for LogConsoleWriterConfig { fn make_layer(&self, bin_name: &str, global: &LogConfig) -> BoxedLayer { let level = self.level.unwrap_or(global.level); let format = apply_override(&global.format, &self.format); let ansi = io::stdout().is_terminal(); make_fmt_layer(bin_name, level, &format, ansi, io::stdout) } } impl MakeLayer for LogFileWriterConfig { fn make_layer(&self, bin_name: &str, global: &LogConfig) -> BoxedLayer { let level = self.level.unwrap_or(global.level); let format = apply_override(&global.format, &self.format); let file_writer = make_file_writer(bin_name, self) // don't have the room for a more graceful error handling here .expect("Failed to create file writer for logging"); make_fmt_layer(bin_name, level, &format, false, file_writer) } } #[cfg(unix)] impl MakeLayer for LogSyslogWriterConfig { fn make_layer(&self, bin_name: &str, global: &LogConfig) -> BoxedLayer { let level = self.level.unwrap_or(global.level); let format = apply_override(&global.format, &self.format); let syslog_writer = make_syslog_writer(bin_name, self); make_fmt_layer(bin_name, level, &format, false, syslog_writer) } } /// Boilerplate for configuring a `fmt::Layer` with `level` and `format` for different writers. fn make_fmt_layer(bin_name: &str, level: u32, format: &LogFormatConfig, ansi: bool, writer: W) -> BoxedLayer where W: for<'a> MakeWriter<'a> + Send + Sync + 'static, { let mut layer = fmt::layer().with_level(true); // NOTE: ansi is enabled by default. // Could be disabled by `NO_COLOR` environment variable. // https://no-color.org/ if !ansi { layer = layer.with_ansi(false); } if level >= 1 { layer = layer.with_target(true).with_thread_ids(true).with_thread_names(true); if level >= 3 { layer = layer.with_file(true).with_line_number(true); } } else { layer = layer.with_target(false).with_thread_ids(false).with_thread_names(false); } let layer = layer.with_writer(writer); let boxed_layer = if format.without_time { layer.without_time().boxed() } else { layer .with_timer(OffsetTime::local_rfc_3339() // Fallback to UTC. Eagerly evaluate because it is cheap to create. .unwrap_or(OffsetTime::new(UtcOffset::UTC, Rfc3339))) .boxed() }; let filter = make_env_filter(bin_name, level); boxed_layer.with_filter(filter).boxed() } fn make_env_filter(bin_name: &str, level: u32) -> EnvFilter { match EnvFilter::try_from_default_env() { Ok(f) => f, Err(_) => match level { 0 => EnvFilter::builder() .with_regex(true) .with_default_directive(LevelFilter::ERROR.into()) .parse_lossy(format!( "warn,{}=info,shadowsocks_rust=info,shadowsocks_service=info,shadowsocks=info", bin_name )), 1 => EnvFilter::builder() .with_regex(true) .with_default_directive(LevelFilter::ERROR.into()) .parse_lossy(format!( "warn,{}=debug,shadowsocks_rust=debug,shadowsocks_service=debug,shadowsocks=debug", bin_name )), 2 => EnvFilter::builder() .with_regex(true) .with_default_directive(LevelFilter::ERROR.into()) .parse_lossy(format!( "warn,{}=trace,shadowsocks_rust=trace,shadowsocks_service=trace,shadowsocks=trace", bin_name )), _ => EnvFilter::builder() .with_default_directive(LevelFilter::TRACE.into()) .parse_lossy(""), }, } } fn make_file_writer(bin_name: &str, config: &LogFileWriterConfig) -> Result { // We provide default values here because we don't have access to the // `bin_name` elsewhere. let prefix = config.prefix.as_deref().unwrap_or(bin_name); let suffix = config.suffix.as_deref().unwrap_or("log"); let mut builder = RollingFileAppender::builder() .rotation(config.rotation.into()) .filename_prefix(prefix) .filename_suffix(suffix); if let Some(max_files) = config.max_files { // setting `max_files` to `0` will cause panicking due to // integer underflow in the `tracing_appender` crate. if max_files > 0 { builder = builder.max_log_files(max_files); } } builder.build(&config.directory) } fn apply_override(global: &LogFormatConfig, override_config: &LogFormatConfigOverride) -> LogFormatConfig { LogFormatConfig { without_time: override_config.without_time.unwrap_or(global.without_time), } } #[cfg(unix)] fn make_syslog_writer(bin_name: &str, config: &LogSyslogWriterConfig) -> Syslog { use std::ffi::CString; use syslog_tracing::{Facility, Options}; let identity = config.identity.as_deref().unwrap_or(bin_name); let facility = match config.facility { None => Facility::default(), Some(f) => match f { 1 => Facility::User, 2 => Facility::Mail, 3 => Facility::Daemon, 4 => Facility::Auth, 6 => Facility::Lpr, 7 => Facility::News, 8 => Facility::Uucp, 9 => Facility::Cron, 10 => Facility::AuthPriv, 16 => Facility::Local0, 17 => Facility::Local1, 18 => Facility::Local2, 19 => Facility::Local3, 20 => Facility::Local4, 21 => Facility::Local5, 22 => Facility::Local6, 23 => Facility::Local7, _ => panic!("unsupported syslog facility: {}", f), }, }; let options = Options::default(); let identity = CString::new(identity).expect("syslog identity contains null-byte ('\\0')"); match Syslog::new(identity, options, facility) { Some(l) => l, None => panic!("syslog is already initialized"), } } ================================================ FILE: src/monitor/mod.rs ================================================ //! Signal monitor #[cfg(unix)] #[path = "unix.rs"] mod imp; #[cfg(windows)] #[path = "windows.rs"] mod imp; #[cfg(not(any(windows, unix)))] #[path = "other.rs"] mod imp; pub use self::imp::create_signal_monitor; ================================================ FILE: src/monitor/other.rs ================================================ use futures; use std::io; /// Create a monitor future for signals /// /// This is a dummy future in the current platform. pub async fn create_signal_monitor() -> io::Result<()> { // FIXME: What can I do ... // Blocks forever futures::empty::<(), io::Error>().await } ================================================ FILE: src/monitor/unix.rs ================================================ use futures::future::{self, Either, FutureExt}; use log::info; use std::io; use tokio::signal::unix::{SignalKind, signal}; /// Create a monitor future for signals /// /// It will exit when received `SIGTERM` or `SIGINT`. pub async fn create_signal_monitor() -> io::Result<()> { // Future resolving to two signal streams. Can fail if setting up signal monitoring fails let mut sigterm = signal(SignalKind::terminate())?; let mut sigint = signal(SignalKind::interrupt())?; let signal_name = match future::select(sigterm.recv().boxed(), sigint.recv().boxed()).await { Either::Left(..) => "SIGTERM", Either::Right(..) => "SIGINT", }; info!("received {}, exiting", signal_name); Ok(()) } ================================================ FILE: src/monitor/windows.rs ================================================ use log::info; use std::io; use tokio::signal::ctrl_c; /// Create a monitor future for signals /// /// It will exit when received Ctrl-C. pub async fn create_signal_monitor() -> io::Result<()> { let _ = ctrl_c().await; info!("received CTRL-C, exiting"); Ok(()) } ================================================ FILE: src/password.rs ================================================ //! Common password utilities use std::{env, io}; use log::debug; /// Read server's password from environment variable or TTY pub fn read_server_password(server_name: &str) -> io::Result { // common SS_SERVER_PASSWORD if let Ok(pwd) = env::var("SS_SERVER_PASSWORD") { debug!( "got server {} password from environment variable SS_SERVER_PASSWORD", server_name ); return Ok(pwd); } // read from TTY let tty_prompt = format!("({server_name}) Password: "); if let Ok(pwd) = rpassword::prompt_password(tty_prompt) { debug!("got server {} password from tty prompt", server_name); return Ok(pwd); } Err(io::Error::other("no server password found")) } ================================================ FILE: src/service/genkey.rs ================================================ //! Generate sufficient key for method use std::process::ExitCode; use base64::Engine as _; use clap::{Arg, ArgAction, ArgMatches, Command, builder::PossibleValuesParser}; use shadowsocks_service::shadowsocks::crypto::{CipherKind, available_ciphers}; /// Defines command line options pub fn define_command_line_options(mut app: Command) -> Command { app = app.arg( Arg::new("ENCRYPT_METHOD") .short('m') .long("encrypt-method") .num_args(1) .action(ArgAction::Set) .required(true) .value_parser(PossibleValuesParser::new(available_ciphers())) .help("Server's encryption method"), ); app } /// Program entrance `main` pub fn main(matches: &ArgMatches) -> ExitCode { let method = matches .get_one::("ENCRYPT_METHOD") .map(|x| x.parse::().expect("method")) .expect("`method` is required"); let key_len = method.key_len(); if key_len > 0 { let mut key = vec![0u8; key_len]; rand::fill(key.as_mut_slice()); let encoded_key = base64::engine::general_purpose::STANDARD.encode(&key); println!("{encoded_key}"); } ExitCode::SUCCESS } ================================================ FILE: src/service/local.rs ================================================ //! Local server launchers #[cfg(unix)] use std::sync::Arc; use std::{ future::Future, net::IpAddr, path::PathBuf, process::ExitCode, time::{Duration, Instant}, }; use clap::{Arg, ArgAction, ArgGroup, ArgMatches, Command, ValueHint, builder::PossibleValuesParser}; use futures::future::{self, FutureExt}; use log::{error, info, trace}; use tokio::{ self, runtime::{Builder, Runtime}, }; #[cfg(feature = "local-redir")] use shadowsocks_service::config::RedirType; #[cfg(feature = "local-tunnel")] use shadowsocks_service::shadowsocks::relay::socks5::Address; use shadowsocks_service::{ acl::AccessControl, config::{ Config, ConfigType, LocalConfig, LocalInstanceConfig, ProtocolType, ServerInstanceConfig, read_variable_field_value, }, local::{Server, loadbalancing::PingBalancer}, shadowsocks::{ config::{Mode, ServerAddr, ServerConfig, ServerSource}, crypto::{CipherKind, available_ciphers}, plugin::PluginConfig, }, }; #[cfg(feature = "logging")] use crate::logging; use crate::{ config::{Config as ServiceConfig, RuntimeMode}, error::{ShadowsocksError, ShadowsocksResult}, monitor, vparser, }; #[cfg(feature = "local-dns")] mod local_value_parser { use std::{ net::{IpAddr, SocketAddr}, str::FromStr, }; use shadowsocks_service::shadowsocks::relay::socks5::{Address, AddressError}; #[derive(Debug, Clone)] pub struct RemoteDnsAddress(pub Address); impl FromStr for RemoteDnsAddress { type Err = AddressError; fn from_str(a: &str) -> Result { if let Ok(ip) = a.parse::() { return Ok(Self(Address::SocketAddress(SocketAddr::new(ip, 53)))); } if let Ok(saddr) = a.parse::() { return Ok(Self(Address::SocketAddress(saddr))); } if a.find(':').is_some() { a.parse::

().map(RemoteDnsAddress) } else { Ok(Self(Address::DomainNameAddress(a.to_owned(), 53))) } } } #[inline] pub fn parse_remote_dns_address(s: &str) -> Result { s.parse::() } } /// Defines command line options pub fn define_command_line_options(mut app: Command) -> Command { app = app.arg( Arg::new("CONFIG") .short('c') .long("config") .num_args(1) .action(ArgAction::Set) .value_parser(clap::value_parser!(PathBuf)) .value_hint(ValueHint::FilePath) .help("Shadowsocks configuration file (https://shadowsocks.org/doc/configs.html)"), ) .arg( Arg::new("LOCAL_ADDR") .short('b') .long("local-addr") .num_args(1) .action(ArgAction::Set) .value_parser(vparser::parse_server_addr) .help("Local address, listen only to this address if specified"), ) .arg( Arg::new("UDP_ONLY") .short('u') .action(ArgAction::SetTrue) .conflicts_with("TCP_AND_UDP") .requires("LOCAL_ADDR") .help("Server mode UDP_ONLY"), ) .arg( Arg::new("TCP_AND_UDP") .short('U') .action(ArgAction::SetTrue) .help("Server mode TCP_AND_UDP"), ) .arg( Arg::new("PROTOCOL") .long("protocol") .num_args(1) .action(ArgAction::Set) .value_parser(PossibleValuesParser::new(ProtocolType::available_protocols())) .help("Protocol for communicating with clients (SOCKS5 by default)"), ) .arg( Arg::new("UDP_BIND_ADDR") .long("udp-bind-addr") .num_args(1) .action(ArgAction::Set) .value_parser(vparser::parse_server_addr) .help("UDP relay's bind address, default is the same as local-addr"), ) .arg( Arg::new("UDP_ASSOCIATE_ADDR") .long("udp-associate-addr") .num_args(1) .action(ArgAction::Set) .value_parser(vparser::parse_server_addr) .help("UDP relay's externally visible address return in UDP Associate responses"), ) .arg( Arg::new("SERVER_ADDR") .short('s') .long("server-addr") .num_args(1) .action(ArgAction::Set) .requires("ENCRYPT_METHOD") .help("Server address"), ) .arg( Arg::new("PASSWORD") .short('k') .long("password") .num_args(1) .action(ArgAction::Set) .requires("SERVER_ADDR") .help("Server's password"), ) .arg( Arg::new("ENCRYPT_METHOD") .short('m') .long("encrypt-method") .num_args(1) .action(ArgAction::Set) .requires("SERVER_ADDR") .value_parser(PossibleValuesParser::new(available_ciphers())) .help("Server's encryption method"), ) .arg( Arg::new("TIMEOUT") .long("timeout") .num_args(1) .action(ArgAction::Set) .value_parser(clap::value_parser!(u64)) .requires("SERVER_ADDR") .help("Server's timeout seconds for TCP relay"), ) .arg( Arg::new("PLUGIN") .long("plugin") .num_args(1) .action(ArgAction::Set) .value_hint(ValueHint::CommandName) .requires("SERVER_ADDR") .help("SIP003 (https://shadowsocks.org/doc/sip003.html) plugin"), ) .arg( Arg::new("PLUGIN_MODE") .long("plugin-mode") .num_args(1) .action(ArgAction::Set) .requires("PLUGIN") .help("SIP003/SIP003u plugin mode, must be one of `tcp_only` (default), `udp_only` and `tcp_and_udp`"), ) .arg( Arg::new("PLUGIN_OPT") .long("plugin-opts") .num_args(1) .action(ArgAction::Set) .requires("PLUGIN") .help("Set SIP003 plugin options"), ) .arg( Arg::new("SERVER_URL") .long("server-url") .num_args(1) .action(ArgAction::Set) .value_hint(ValueHint::Url) .value_parser(vparser::parse_server_url) .help("Server address in SIP002 (https://shadowsocks.org/doc/sip002.html) URL"), ) .group(ArgGroup::new("SERVER_CONFIG") .arg("SERVER_ADDR").arg("SERVER_URL").multiple(true)) .arg( Arg::new("ACL") .long("acl") .num_args(1) .action(ArgAction::Set) .value_hint(ValueHint::FilePath) .help("Path to ACL (Access Control List)"), ) .arg(Arg::new("DNS").long("dns").num_args(1).action(ArgAction::Set).help("DNS nameservers, formatted like [(tcp|udp)://]host[:port][,host[:port]]..., or unix:///path/to/dns, or predefined keys like \"google\", \"cloudflare\"")) .arg(Arg::new("DNS_CACHE_SIZE").long("dns-cache-size").num_args(1).action(ArgAction::Set).value_parser(clap::value_parser!(usize)).help("DNS cache size in number of records. Works when trust-dns DNS backend is enabled.")) .arg(Arg::new("TCP_NO_DELAY").long("tcp-no-delay").alias("no-delay").action(ArgAction::SetTrue).help("Set TCP_NODELAY option for sockets")) .arg(Arg::new("TCP_FAST_OPEN").long("tcp-fast-open").alias("fast-open").action(ArgAction::SetTrue).help("Enable TCP Fast Open (TFO)")) .arg(Arg::new("TCP_KEEP_ALIVE").long("tcp-keep-alive").num_args(1).action(ArgAction::Set).value_parser(clap::value_parser!(u64)).help("Set TCP keep alive timeout seconds")) .arg(Arg::new("TCP_MULTIPATH").long("tcp-multipath").alias("mptcp").action(ArgAction::SetTrue).help("Enable Multipath-TCP (MPTCP)")) .arg(Arg::new("UDP_TIMEOUT").long("udp-timeout").num_args(1).action(ArgAction::Set).value_parser(clap::value_parser!(u64)).help("Timeout seconds for UDP relay")) .arg(Arg::new("UDP_MAX_ASSOCIATIONS").long("udp-max-associations").num_args(1).action(ArgAction::Set).value_parser(clap::value_parser!(usize)).help("Maximum associations to be kept simultaneously for UDP relay")) .arg(Arg::new("INBOUND_SEND_BUFFER_SIZE").long("inbound-send-buffer-size").num_args(1).action(ArgAction::Set).value_parser(clap::value_parser!(u32)).help("Set inbound sockets' SO_SNDBUF option")) .arg(Arg::new("INBOUND_RECV_BUFFER_SIZE").long("inbound-recv-buffer-size").num_args(1).action(ArgAction::Set).value_parser(clap::value_parser!(u32)).help("Set inbound sockets' SO_RCVBUF option")) .arg(Arg::new("OUTBOUND_SEND_BUFFER_SIZE").long("outbound-send-buffer-size").num_args(1).action(ArgAction::Set).value_parser(clap::value_parser!(u32)).help("Set outbound sockets' SO_SNDBUF option")) .arg(Arg::new("OUTBOUND_RECV_BUFFER_SIZE").long("outbound-recv-buffer-size").num_args(1).action(ArgAction::Set).value_parser(clap::value_parser!(u32)).help("Set outbound sockets' SO_RCVBUF option")) .arg(Arg::new("OUTBOUND_BIND_ADDR").long("outbound-bind-addr").num_args(1).alias("bind-addr").action(ArgAction::Set).value_parser(vparser::parse_ip_addr).help("Bind address, outbound socket will bind this address")) .arg(Arg::new("OUTBOUND_BIND_INTERFACE").long("outbound-bind-interface").num_args(1).action(ArgAction::Set).help("Set SO_BINDTODEVICE / IP_BOUND_IF / IP_UNICAST_IF option for outbound socket")) .arg( Arg::new("IPV6_FIRST") .short('6') .action(ArgAction::SetTrue) .help("Resolve hostname to IPv6 address first"), ); #[cfg(feature = "logging")] { app = app .arg( Arg::new("VERBOSE") .short('v') .action(ArgAction::Count) .help("Set log level"), ) .arg( Arg::new("LOG_WITHOUT_TIME") .long("log-without-time") .action(ArgAction::SetTrue) .help("Log without datetime prefix"), ) .arg( Arg::new("LOG_CONFIG") .long("log-config") // deprecated for removal .hide(true) .num_args(1) .action(ArgAction::Set) .value_parser(clap::value_parser!(PathBuf)) .value_hint(ValueHint::FilePath) .help("log4rs configuration file"), ); } #[cfg(feature = "local-tunnel")] { app = app.arg( Arg::new("FORWARD_ADDR") .short('f') .long("forward-addr") .num_args(1) .action(ArgAction::Set) .requires("LOCAL_ADDR") .value_parser(vparser::parse_address) .required_if_eq("PROTOCOL", "tunnel") .help("Forwarding data directly to this address (for tunnel)"), ); } #[cfg(all(unix, not(target_os = "android")))] { app = app.arg( Arg::new("NOFILE") .short('n') .long("nofile") .num_args(1) .action(ArgAction::Set) .value_parser(clap::value_parser!(u64)) .help("Set RLIMIT_NOFILE with both soft and hard limit"), ); } #[cfg(any(target_os = "linux", target_os = "android"))] { app = app.arg( Arg::new("OUTBOUND_FWMARK") .long("outbound-fwmark") .num_args(1) .action(ArgAction::Set) .value_parser(clap::value_parser!(u32)) .help("Set SO_MARK option for outbound sockets"), ); } #[cfg(target_os = "freebsd")] { app = app.arg( Arg::new("OUTBOUND_USER_COOKIE") .long("outbound-user-cookie") .num_args(1) .action(ArgAction::Set) .value_parser(clap::value_parser!(u32)) .help("Set SO_USER_COOKIE option for outbound sockets"), ); } #[cfg(feature = "local-redir")] { if RedirType::tcp_default() != RedirType::NotSupported { app = app.arg( Arg::new("TCP_REDIR") .long("tcp-redir") .num_args(1) .action(ArgAction::Set) .requires("LOCAL_ADDR") .value_parser(PossibleValuesParser::new(RedirType::tcp_available_types())) .help("TCP redir (transparent proxy) type"), ); } if RedirType::udp_default() != RedirType::NotSupported { app = app.arg( Arg::new("UDP_REDIR") .long("udp-redir") .num_args(1) .action(ArgAction::Set) .requires("LOCAL_ADDR") .value_parser(PossibleValuesParser::new(RedirType::udp_available_types())) .help("UDP redir (transparent proxy) type"), ); } } #[cfg(target_os = "android")] { app = app.arg( Arg::new("VPN_MODE") .long("vpn") .action(ArgAction::SetTrue) .help("Enable VPN mode (only for Android)"), ); } #[cfg(feature = "local-flow-stat")] { #[cfg(unix)] { app = app.arg( Arg::new("STAT_PATH") .long("stat-path") .num_args(1) .action(ArgAction::Set) .value_hint(ValueHint::FilePath) .conflicts_with("STAT_ADDR") .help("Specify socket path (unix domain socket) for sending traffic statistic"), ); } app = app.arg( Arg::new("STAT_ADDR") .long("stat-addr") .num_args(1) .action(ArgAction::Set) .value_parser(vparser::parse_socket_addr) .help("Specify socket address IP:PORT (TCP) for sending traffic statistic"), ); } #[cfg(feature = "local-dns")] { app = app .arg( Arg::new("LOCAL_DNS_ADDR") .long("local-dns-addr") .num_args(1) .action(ArgAction::Set) .required_if_eq("PROTOCOL", "dns") .requires("LOCAL_ADDR") .value_parser(vparser::parse_name_server_addr) .help("Specify the address of local DNS server, send queries directly"), ) .arg( Arg::new("REMOTE_DNS_ADDR") .long("remote-dns-addr") .num_args(1) .action(ArgAction::Set) .required_if_eq("PROTOCOL", "dns") .requires("LOCAL_ADDR") .value_parser(self::local_value_parser::parse_remote_dns_address) .help("Specify the address of remote DNS server, send queries through shadowsocks' tunnel"), ); #[cfg(target_os = "android")] { app = app.arg( Arg::new("DNS_LOCAL_ADDR") .long("dns-addr") .num_args(1) .action(ArgAction::Set) .requires_all(&["LOCAL_ADDR", "REMOTE_DNS_ADDR"]) .value_parser(vparser::parse_server_addr) .help("DNS address, listen to this address if specified"), ); } } #[cfg(feature = "local-tun")] { app = app .arg( Arg::new("TUN_INTERFACE_NAME") .long("tun-interface-name") .num_args(1) .action(ArgAction::Set) .help("Tun interface name, allocate one if not specify"), ) .arg( Arg::new("TUN_INTERFACE_ADDRESS") .long("tun-interface-address") .num_args(1) .action(ArgAction::Set) .value_parser(vparser::parse_ipnet) .help("Tun interface address (network)"), ) .arg( Arg::new("TUN_INTERFACE_DESTINATION") .long("tun-interface-destination") .num_args(1) .action(ArgAction::Set) .value_parser(vparser::parse_ipnet) .help("Tun interface destination address (network)"), ); #[cfg(unix)] { app = app.arg( Arg::new("TUN_DEVICE_FD_FROM_PATH") .long("tun-device-fd-from-path") .num_args(1) .action(ArgAction::Set) .value_parser(clap::value_parser!(PathBuf)) .value_hint(ValueHint::AnyPath) .help("Tun device file descriptor will be transferred from this unix domain socket path"), ); } } #[cfg(feature = "local-fake-dns")] { app = app .arg( Arg::new("FAKE_DNS_RECORD_EXPIRE_DURATION") .long("fake-dns-record-expire-duration") .num_args(1) .action(ArgAction::Set) .value_parser(clap::value_parser!(u64)) .help("Fake DNS record expire duration in seconds"), ) .arg( Arg::new("FAKE_DNS_IPV4_NETWORK") .long("fake-dns-ipv4-network") .num_args(1) .action(ArgAction::Set) .value_parser(vparser::parse_ipnet) .help("Fake DNS IPv4 address network"), ) .arg( Arg::new("FAKE_DNS_IPV6_NETWORK") .long("fake-dns-ipv6-network") .num_args(1) .action(ArgAction::Set) .value_parser(vparser::parse_ipnet) .help("Fake DNS IPv6 address network"), ) .arg( Arg::new("FAKE_DNS_DATABASE_PATH") .long("fake-dns-database-path") .num_args(1) .action(ArgAction::Set) .value_hint(ValueHint::AnyPath) .help("Fake DNS database storage path"), ); } #[cfg(unix)] { app = app .arg( Arg::new("DAEMONIZE") .short('d') .long("daemonize") .action(ArgAction::SetTrue) .help("Daemonize"), ) .arg( Arg::new("DAEMONIZE_PID_PATH") .long("daemonize-pid") .num_args(1) .action(ArgAction::Set) .value_parser(clap::value_parser!(PathBuf)) .value_hint(ValueHint::FilePath) .help("File path to store daemonized process's PID"), ); } #[cfg(feature = "multi-threaded")] { app = app .arg( Arg::new("SINGLE_THREADED") .long("single-threaded") .action(ArgAction::SetTrue) .help("Run the program all in one thread"), ) .arg( Arg::new("WORKER_THREADS") .long("worker-threads") .num_args(1) .action(ArgAction::Set) .value_parser(clap::value_parser!(usize)) .help("Sets the number of worker threads the `Runtime` will use"), ); } #[cfg(unix)] { app = app.arg( Arg::new("USER") .long("user") .short('a') .num_args(1) .action(ArgAction::Set) .value_hint(ValueHint::Username) .help("Run as another user"), ); } #[cfg(feature = "local-online-config")] { app = app .arg( Arg::new("ONLINE_CONFIG_URL") .long("online-config-url") .num_args(1) .action(ArgAction::Set) .value_hint(ValueHint::Url) .help("SIP008 Online Configuration Delivery URL (https://shadowsocks.org/doc/sip008.html)"), ) .arg( Arg::new("ONLINE_CONFIG_UPDATE_INTERVAL") .long("online-config-update-interval") .num_args(1) .action(ArgAction::Set) .value_parser(clap::value_parser!(u64)) .help("SIP008 Online Configuration Delivery update interval in seconds, 3600 by default"), ) .arg( Arg::new("ONLINE_CONFIG_ALLOWED_PLUGIN") .long("online-config-allowed-plugin") .action(ArgAction::Append) .help("SIP008 Online Configuration Delivery allowed plugin list"), ); } app } /// Create `Runtime` and `main` entry pub fn create(matches: &ArgMatches) -> ShadowsocksResult<(Runtime, impl Future + use<>)> { #[cfg_attr(not(feature = "local-online-config"), allow(unused_mut))] let (config, _, runtime) = { let config_path_opt = matches.get_one::("CONFIG").cloned().or_else(|| { if !matches.contains_id("SERVER_CONFIG") { match crate::config::get_default_config_path("local.json") { None => None, Some(p) => { println!("loading default config {p:?}"); Some(p) } } } else { None } }); let mut service_config = match config_path_opt { Some(ref config_path) => ServiceConfig::load_from_file(config_path) .map_err(|err| ShadowsocksError::LoadConfigFailure(format!("loading config {config_path:?}, {err}")))?, None => ServiceConfig::default(), }; service_config.set_options(matches); #[cfg(feature = "logging")] match service_config.log.config_path { Some(ref path) => { logging::init_with_file(path); } None => { logging::init_with_config("sslocal", &service_config.log); } } trace!("{:?}", service_config); let mut config = match config_path_opt { Some(cpath) => Config::load_from_file(&cpath, ConfigType::Local) .map_err(|err| ShadowsocksError::LoadConfigFailure(format!("loading config {cpath:?}, {err}")))?, None => Config::new(ConfigType::Local), }; if let Some(svr_addr) = matches.get_one::("SERVER_ADDR") { let method = matches .get_one::("ENCRYPT_METHOD") .map(|x| x.parse::().expect("method")) .expect("`method` is required"); let password = match matches.get_one::("PASSWORD") { Some(pwd) => read_variable_field_value(pwd).into(), None => { // NOTE: svr_addr should have been checked by crate::vparser if method.is_none() { // If method doesn't need a key (none, plain), then we can leave it empty String::new() } else { match crate::password::read_server_password(svr_addr) { Ok(pwd) => pwd, Err(..) => panic!("`password` is required for server {svr_addr}"), } } } }; let svr_addr = svr_addr.parse::().expect("server-addr"); let timeout = matches.get_one::("TIMEOUT").map(|x| Duration::from_secs(*x)); let mut sc = match ServerConfig::new(svr_addr, password, method) { Ok(sc) => sc, Err(err) => { panic!("failed to create ServerConfig, error: {}", err); } }; sc.set_source(ServerSource::CommandLine); if let Some(timeout) = timeout { sc.set_timeout(timeout); } if let Some(p) = matches.get_one::("PLUGIN").cloned() { let plugin = PluginConfig { plugin: p, plugin_opts: matches.get_one::("PLUGIN_OPT").cloned(), plugin_args: Vec::new(), plugin_mode: matches .get_one::("PLUGIN_MODE") .map(|x| { x.parse::() .expect("plugin-mode must be one of `tcp_only` (default), `udp_only` and `tcp_and_udp`") }) .unwrap_or(Mode::TcpOnly), }; sc.set_plugin(plugin); } config.server.push(ServerInstanceConfig::with_server_config(sc)); } if let Some(mut svr_addr) = matches.get_one::("SERVER_URL").cloned() { svr_addr.set_source(ServerSource::CommandLine); config.server.push(ServerInstanceConfig::with_server_config(svr_addr)); } #[cfg(feature = "local-flow-stat")] { use shadowsocks_service::config::LocalFlowStatAddress; use std::net::SocketAddr; #[cfg(unix)] if let Some(stat_path) = matches.get_one::("STAT_PATH") { config.local_stat_addr = Some(LocalFlowStatAddress::UnixStreamPath(From::from(stat_path))); } if let Some(stat_addr) = matches.get_one::("STAT_ADDR").cloned() { config.local_stat_addr = Some(LocalFlowStatAddress::TcpStreamAddr(stat_addr)); } } #[cfg(target_os = "android")] if matches.get_flag("VPN_MODE") { // A socket `protect_path` in CWD // Same as shadowsocks-libev's android.c config.outbound_vpn_protect_path = Some(From::from("protect_path")); } if matches.get_raw("LOCAL_ADDR").is_some() || matches.get_raw("PROTOCOL").is_some() { let protocol = match matches.get_one::("PROTOCOL").map(|s| s.as_str()) { Some("socks") => ProtocolType::Socks, #[cfg(feature = "local-http")] Some("http") => ProtocolType::Http, #[cfg(feature = "local-tunnel")] Some("tunnel") => ProtocolType::Tunnel, #[cfg(feature = "local-redir")] Some("redir") => ProtocolType::Redir, #[cfg(feature = "local-dns")] Some("dns") => ProtocolType::Dns, #[cfg(feature = "local-tun")] Some("tun") => ProtocolType::Tun, Some(p) => panic!("not supported `protocol` \"{p}\""), None => ProtocolType::Socks, }; let mut local_config = LocalConfig::new(protocol); match matches.get_one::("LOCAL_ADDR").cloned() { Some(local_addr) => local_config.addr = Some(local_addr), None => { #[cfg(feature = "local-tun")] if protocol == ProtocolType::Tun { // `tun` protocol doesn't need --local-addr } else { panic!("`local-addr` is required for protocol {}", protocol.as_str()); } } } if let Some(udp_bind_addr) = matches.get_one::("UDP_BIND_ADDR").cloned() { local_config.udp_addr = Some(udp_bind_addr); } if let Some(udp_associate_addr) = matches.get_one::("UDP_ASSOCIATE_ADDR").cloned() { local_config.udp_associate_addr = Some(udp_associate_addr); } #[cfg(feature = "local-tunnel")] if let Some(addr) = matches.get_one::
("FORWARD_ADDR").cloned() { local_config.forward_addr = Some(addr); } #[cfg(feature = "local-redir")] { if RedirType::tcp_default() != RedirType::NotSupported && let Some(tcp_redir) = matches.get_one::("TCP_REDIR") { local_config.tcp_redir = tcp_redir.parse::().expect("tcp-redir"); } if RedirType::udp_default() != RedirType::NotSupported && let Some(udp_redir) = matches.get_one::("UDP_REDIR") { local_config.udp_redir = udp_redir.parse::().expect("udp-redir"); } } #[cfg(feature = "local-dns")] { use shadowsocks_service::local::dns::NameServerAddr; use self::local_value_parser::RemoteDnsAddress; if let Some(addr) = matches.get_one::("LOCAL_DNS_ADDR").cloned() { local_config.local_dns_addr = Some(addr); } if let Some(addr) = matches.get_one::("REMOTE_DNS_ADDR").cloned() { local_config.remote_dns_addr = Some(addr.0); } } #[cfg(all(feature = "local-dns", target_os = "android"))] if protocol != ProtocolType::Dns { // Start a DNS local server binding to DNS_LOCAL_ADDR // // This is a special route only for shadowsocks-android if let Some(addr) = matches.get_one::("DNS_LOCAL_ADDR").cloned() { let mut local_dns_config = LocalConfig::new_with_addr(addr, ProtocolType::Dns); // The `local_dns_addr` and `remote_dns_addr` are for this DNS server (for compatibility) local_dns_config.local_dns_addr = local_config.local_dns_addr.take(); local_dns_config.remote_dns_addr = local_config.remote_dns_addr.take(); config .local .push(LocalInstanceConfig::with_local_config(local_dns_config)); } } #[cfg(feature = "local-tun")] { use ipnet::IpNet; if let Some(tun_address) = matches.get_one::("TUN_INTERFACE_ADDRESS").cloned() { local_config.tun_interface_address = Some(tun_address); } if let Some(tun_address) = matches.get_one::("TUN_INTERFACE_DESTINATION").cloned() { local_config.tun_interface_destination = Some(tun_address); } if let Some(tun_name) = matches.get_one::("TUN_INTERFACE_NAME").cloned() { local_config.tun_interface_name = Some(tun_name); } #[cfg(unix)] if let Some(fd_path) = matches.get_one::("TUN_DEVICE_FD_FROM_PATH").cloned() { local_config.tun_device_fd_from_path = Some(fd_path); } } #[cfg(feature = "local-fake-dns")] { use ipnet::{Ipv4Net, Ipv6Net}; if let Some(d) = matches.get_one::("FAKE_DNS_RECORD_EXPIRE_DURATION") { local_config.fake_dns_record_expire_duration = Some(Duration::from_secs(*d)); } if let Some(n) = matches.get_one::("FAKE_DNS_IPV4_NETWORK") { local_config.fake_dns_ipv4_network = Some(*n); } if let Some(n) = matches.get_one::("FAKE_DNS_IPV6_NETWORK") { local_config.fake_dns_ipv6_network = Some(*n); } if let Some(p) = matches.get_one::("FAKE_DNS_DATABASE_PATH").cloned() { local_config.fake_dns_database_path = Some(p); } } if matches.get_flag("UDP_ONLY") { local_config.mode = Mode::UdpOnly; } if matches.get_flag("TCP_AND_UDP") { local_config.mode = Mode::TcpAndUdp; } config.local.push(LocalInstanceConfig::with_local_config(local_config)); } if matches.get_flag("TCP_NO_DELAY") { config.no_delay = true; } if matches.get_flag("TCP_FAST_OPEN") { config.fast_open = true; } if let Some(keep_alive) = matches.get_one::("TCP_KEEP_ALIVE") { config.keep_alive = Some(Duration::from_secs(*keep_alive)); } if matches.get_flag("TCP_MULTIPATH") { config.mptcp = true; } #[cfg(any(target_os = "linux", target_os = "android"))] if let Some(mark) = matches.get_one::("OUTBOUND_FWMARK") { config.outbound_fwmark = Some(*mark); } #[cfg(target_os = "freebsd")] if let Some(user_cookie) = matches.get_one::("OUTBOUND_USER_COOKIE") { config.outbound_user_cookie = Some(*user_cookie); } if let Some(iface) = matches.get_one::("OUTBOUND_BIND_INTERFACE").cloned() { config.outbound_bind_interface = Some(iface); } #[cfg(all(unix, not(target_os = "android")))] match matches.get_one::("NOFILE") { Some(nofile) => config.nofile = Some(*nofile), None => { if config.nofile.is_none() { crate::sys::adjust_nofile(); } } } if let Some(acl_file) = matches.get_one::("ACL") { let acl = AccessControl::load_from_file(acl_file) .map_err(|err| ShadowsocksError::LoadAclFailure(format!("loading ACL \"{acl_file}\", {err}")))?; config.acl = Some(acl); } if let Some(dns) = matches.get_one::("DNS") { config.set_dns_formatted(dns).expect("dns"); } if let Some(dns_cache_size) = matches.get_one::("DNS_CACHE_SIZE") { config.dns_cache_size = Some(*dns_cache_size); } if matches.get_flag("IPV6_FIRST") { config.ipv6_first = true; } if let Some(udp_timeout) = matches.get_one::("UDP_TIMEOUT") { config.udp_timeout = Some(Duration::from_secs(*udp_timeout)); } if let Some(udp_max_assoc) = matches.get_one::("UDP_MAX_ASSOCIATIONS") { config.udp_max_associations = Some(*udp_max_assoc); } if let Some(bs) = matches.get_one::("INBOUND_SEND_BUFFER_SIZE") { config.inbound_send_buffer_size = Some(*bs); } if let Some(bs) = matches.get_one::("INBOUND_RECV_BUFFER_SIZE") { config.inbound_recv_buffer_size = Some(*bs); } if let Some(bs) = matches.get_one::("OUTBOUND_SEND_BUFFER_SIZE") { config.outbound_send_buffer_size = Some(*bs); } if let Some(bs) = matches.get_one::("OUTBOUND_RECV_BUFFER_SIZE") { config.outbound_recv_buffer_size = Some(*bs); } if let Some(bind_addr) = matches.get_one::("OUTBOUND_BIND_ADDR") { config.outbound_bind_addr = Some(*bind_addr); } #[cfg(feature = "local-online-config")] if let Some(online_config_url) = matches.get_one::("ONLINE_CONFIG_URL") { use shadowsocks_service::config::OnlineConfig; let online_config_update_interval = matches.get_one::("ONLINE_CONFIG_UPDATE_INTERVAL").cloned(); let mut allowed_plugins = None; if let Some(plugins) = matches.get_many::("ONLINE_CONFIG_ALLOWED_PLUGIN") { allowed_plugins = Some(plugins.cloned().collect()); } config.online_config = Some(OnlineConfig { config_url: online_config_url.clone(), update_interval: online_config_update_interval.map(Duration::from_secs), allowed_plugins, }); } // DONE READING options if config.local.is_empty() { return Err(ShadowsocksError::InsufficientParams( "missing `local_address`, consider specifying it by --local-addr command line option, \ or \"local_address\" and \"local_port\" in configuration file" .to_string(), )); } config .check_integrity() .map_err(|err| ShadowsocksError::LoadConfigFailure(format!("config integrity check failed, {err}")))?; #[cfg(unix)] if matches.get_flag("DAEMONIZE") || matches.get_raw("DAEMONIZE_PID_PATH").is_some() { use crate::daemonize; daemonize::daemonize(matches.get_one::("DAEMONIZE_PID_PATH")); } #[cfg(unix)] if let Some(uname) = matches.get_one::("USER") { crate::sys::run_as_user(uname).map_err(|err| { ShadowsocksError::InsufficientParams(format!("failed to change as user, error: {err}")) })?; } info!("shadowsocks local {} build {}", crate::VERSION, crate::BUILD_TIME); let mut builder = match service_config.runtime.mode { RuntimeMode::SingleThread => Builder::new_current_thread(), #[cfg(feature = "multi-threaded")] RuntimeMode::MultiThread => { let mut builder = Builder::new_multi_thread(); if let Some(worker_threads) = service_config.runtime.worker_count { builder.worker_threads(worker_threads); } builder } }; let runtime = builder.enable_all().build().expect("create tokio Runtime"); (config, service_config, runtime) }; let main_fut = async move { let config_path = config.config_path.clone(); let instance = Server::new(config).await.expect("create local"); let reload_task = match config_path { Some(config_path) => ServerReloader { config_path: config_path.clone(), balancer: instance.server_balancer().clone(), } .launch_reload_server_task() .boxed(), None => future::pending().boxed(), }; let abort_signal = monitor::create_signal_monitor(); let server = instance.run(); let reload_task = reload_task.fuse(); let abort_signal = abort_signal.fuse(); let server = server.fuse(); tokio::pin!(reload_task); tokio::pin!(abort_signal); tokio::pin!(server); loop { futures::select! { server_res = server => { match server_res { // Server future resolved without an error. This should never happen. Ok(..) => { return Err(ShadowsocksError::ServerExitUnexpectedly("server exited unexpectedly".to_owned())); } // Server future resolved with error, which are listener errors in most cases Err(err) => { return Err(ShadowsocksError::ServerAborted(format!("server aborted with {err}"))); } } } // The abort signal future resolved. Means we should just exit. _ = abort_signal => { return Ok(()); } _ = reload_task => { // continue. trace!("server-loader task task exited"); } } } }; Ok((runtime, main_fut)) } /// Program entrance `main` #[inline] pub fn main(matches: &ArgMatches) -> ExitCode { match create(matches).and_then(|(runtime, main_fut)| runtime.block_on(main_fut)) { Ok(()) => ExitCode::SUCCESS, Err(err) => { eprintln!("{err}"); err.exit_code().into() } } } struct ServerReloader { config_path: PathBuf, balancer: PingBalancer, } impl ServerReloader { #[cfg_attr(not(unix), allow(dead_code))] async fn run_once(&self) -> Result<(), Box> { let start_time = Instant::now(); // Load servers from source let source_config = match Config::load_from_file(&self.config_path, ConfigType::Local) { Ok(c) => c, Err(err) => { error!( "server-loader task failed to load from file: {}, error: {}", self.config_path.display(), err ); return Err(Box::new(err)); } }; let server_len = source_config.server.len(); let fetch_end_time = Instant::now(); if let Err(err) = self .balancer .reset_servers(source_config.server, &[ServerSource::Configuration]) .await { error!("server-loader task {} servers but found error: {}", server_len, err); return Err(Box::new(err)); } let total_end_time = Instant::now(); info!( "server-loader task load from {} with {} servers, fetch costs: {:?}, total costs: {:?}", self.config_path.display(), server_len, fetch_end_time - start_time, total_end_time - start_time, ); Ok(()) } #[cfg(unix)] async fn launch_signal_reload_server_task(self: Arc) { use log::debug; use tokio::signal::unix::{SignalKind, signal}; let mut sigusr1 = signal(SignalKind::user_defined1()).expect("signal"); debug!("server-loader task is now listening USR1"); while sigusr1.recv().await.is_some() { let _ = self.run_once().await; } } #[cfg(unix)] async fn launch_reload_server_task(self) { let arc_self = Arc::new(self); arc_self.launch_signal_reload_server_task().await } #[cfg(windows)] async fn launch_reload_server_task(self) { let _ = self.config_path; let _ = self.balancer; } } #[cfg(test)] mod test { use clap::Command; #[test] fn verify_local_command() { let mut app = Command::new("shadowsocks") .version(crate::VERSION) .about("A fast tunnel proxy that helps you bypass firewalls. (https://shadowsocks.org)"); app = super::define_command_line_options(app); app.debug_assert(); } } ================================================ FILE: src/service/manager.rs ================================================ //! Server Manager launchers use std::{future::Future, net::IpAddr, path::PathBuf, process::ExitCode, time::Duration}; use clap::{Arg, ArgAction, ArgGroup, ArgMatches, Command, ValueHint, builder::PossibleValuesParser}; use futures::future::{self, Either}; use log::{info, trace}; use tokio::{ self, runtime::{Builder, Runtime}, }; #[cfg(unix)] use shadowsocks_service::config::ManagerServerMode; use shadowsocks_service::{ acl::AccessControl, config::{Config, ConfigType, ManagerConfig, ManagerServerHost}, run_manager, shadowsocks::{ config::{ManagerAddr, Mode}, crypto::{CipherKind, available_ciphers}, plugin::PluginConfig, }, }; #[cfg(feature = "logging")] use crate::logging; use crate::{ config::{Config as ServiceConfig, RuntimeMode}, error::{ShadowsocksError, ShadowsocksResult}, monitor, vparser, }; /// Defines command line options pub fn define_command_line_options(mut app: Command) -> Command { app = app .arg( Arg::new("CONFIG") .short('c') .long("config") .num_args(1) .action(ArgAction::Set) .value_parser(clap::value_parser!(PathBuf)) .value_hint(ValueHint::FilePath) .help("Shadowsocks configuration file (https://shadowsocks.org/doc/configs.html), the only required fields are \"manager_address\" and \"manager_port\". Servers defined will be created when process is started."), ) .arg( Arg::new("UDP_ONLY") .short('u') .action(ArgAction::SetTrue) .conflicts_with("TCP_AND_UDP") .help("Server mode UDP_ONLY"), ) .arg( Arg::new("TCP_AND_UDP") .short('U') .action(ArgAction::SetTrue) .help("Server mode TCP_AND_UDP"), ) .arg( Arg::new("OUTBOUND_BIND_ADDR") .short('b') .long("outbound-bind-addr") .num_args(1) .action(ArgAction::Set) .alias("bind-addr") .value_parser(vparser::parse_ip_addr) .help("Bind address, outbound socket will bind this address"), ) .arg( Arg::new("OUTBOUND_BIND_INTERFACE") .long("outbound-bind-interface") .num_args(1) .action(ArgAction::Set) .help("Set SO_BINDTODEVICE / IP_BOUND_IF / IP_UNICAST_IF option for outbound socket"), ) .arg(Arg::new("SERVER_HOST").short('s').long("server-host").num_args(1).action(ArgAction::Set).value_parser(vparser::parse_manager_server_host).help("Host name or IP address of your remote server")) .arg( Arg::new("MANAGER_ADDR") .long("manager-addr") .num_args(1) .action(ArgAction::Set) .alias("manager-address") .value_parser(vparser::parse_manager_addr) .help("ShadowSocks Manager (ssmgr) address, could be ip:port, domain:port or /path/to/unix.sock"), ) .group(ArgGroup::new("SERVER_CONFIG").arg("MANAGER_ADDR")) .arg(Arg::new("ENCRYPT_METHOD").short('m').long("encrypt-method").num_args(1).action(ArgAction::Set).value_parser(PossibleValuesParser::new(available_ciphers())).help("Default encryption method")) .arg(Arg::new("TIMEOUT").long("timeout").num_args(1).action(ArgAction::Set).value_parser(clap::value_parser!(u64)).help("Default timeout seconds for TCP relay")) .arg( Arg::new("PLUGIN") .long("plugin") .num_args(1) .action(ArgAction::Set) .value_hint(ValueHint::CommandName) .help("Default SIP003 (https://shadowsocks.org/doc/sip003.html) plugin"), ) .arg( Arg::new("PLUGIN_MODE") .long("plugin-mode") .num_args(1) .action(ArgAction::Set) .requires("PLUGIN") .help("SIP003/SIP003u plugin mode, must be one of `tcp_only` (default), `udp_only` and `tcp_and_udp`"), ) .arg( Arg::new("PLUGIN_OPT") .long("plugin-opts") .num_args(1) .action(ArgAction::Set) .requires("PLUGIN") .help("Default SIP003 plugin options"), ).arg(Arg::new("ACL").long("acl").num_args(1).action(ArgAction::Set).value_hint(ValueHint::FilePath).help("Path to ACL (Access Control List)")) .arg(Arg::new("DNS").long("dns").num_args(1).action(ArgAction::Set).help("DNS nameservers, formatted like [(tcp|udp)://]host[:port][,host[:port]]..., or unix:///path/to/dns, or predefined keys like \"google\", \"cloudflare\"")) .arg(Arg::new("DNS_CACHE_SIZE").long("dns-cache-size").num_args(1).action(ArgAction::Set).value_parser(clap::value_parser!(usize)).help("DNS cache size in number of records. Works when trust-dns DNS backend is used.")) .arg(Arg::new("TCP_NO_DELAY").long("tcp-no-delay").alias("no-delay").action(ArgAction::SetTrue).help("Set TCP_NODELAY option for sockets")) .arg(Arg::new("TCP_FAST_OPEN").long("tcp-fast-open").alias("fast-open").action(ArgAction::SetTrue).help("Enable TCP Fast Open (TFO)")) .arg(Arg::new("TCP_KEEP_ALIVE").long("tcp-keep-alive").num_args(1).action(ArgAction::Set).value_parser(clap::value_parser!(u64)).help("Set TCP keep alive timeout seconds")) .arg(Arg::new("TCP_MULTIPATH").long("tcp-multipath").alias("mptcp").action(ArgAction::SetTrue).help("Enable Multipath-TCP (MPTCP)")) .arg(Arg::new("UDP_TIMEOUT").long("udp-timeout").num_args(1).action(ArgAction::Set).value_parser(clap::value_parser!(u64)).help("Timeout seconds for UDP relay")) .arg(Arg::new("UDP_MAX_ASSOCIATIONS").long("udp-max-associations").num_args(1).action(ArgAction::Set).value_parser(clap::value_parser!(usize)).help("Maximum associations to be kept simultaneously for UDP relay")) .arg(Arg::new("INBOUND_SEND_BUFFER_SIZE").long("inbound-send-buffer-size").num_args(1).action(ArgAction::Set).value_parser(clap::value_parser!(u32)).help("Set inbound sockets' SO_SNDBUF option")) .arg(Arg::new("INBOUND_RECV_BUFFER_SIZE").long("inbound-recv-buffer-size").num_args(1).action(ArgAction::Set).value_parser(clap::value_parser!(u32)).help("Set inbound sockets' SO_RCVBUF option")) .arg(Arg::new("OUTBOUND_SEND_BUFFER_SIZE").long("outbound-send-buffer-size").num_args(1).action(ArgAction::Set).value_parser(clap::value_parser!(u32)).help("Set outbound sockets' SO_SNDBUF option")) .arg(Arg::new("OUTBOUND_RECV_BUFFER_SIZE").long("outbound-recv-buffer-size").num_args(1).action(ArgAction::Set).value_parser(clap::value_parser!(u32)).help("Set outbound sockets' SO_RCVBUF option")) .arg( Arg::new("IPV6_FIRST") .short('6') .action(ArgAction::SetTrue) .help("Resolve hostname to IPv6 address first"), ); #[cfg(feature = "logging")] { app = app .arg( Arg::new("VERBOSE") .short('v') .action(ArgAction::Count) .help("Set log level"), ) .arg( Arg::new("LOG_WITHOUT_TIME") .long("log-without-time") .action(ArgAction::SetTrue) .help("Log without datetime prefix"), ) .arg( Arg::new("LOG_CONFIG") .long("log-config") // deprecated for removal .hide(true) .num_args(1) .action(ArgAction::Set) .value_parser(clap::value_parser!(PathBuf)) .value_hint(ValueHint::FilePath) .help("log4rs configuration file"), ); } #[cfg(unix)] { app = app .arg( Arg::new("DAEMONIZE") .short('d') .long("daemonize") .action(ArgAction::SetTrue) .help("Daemonize"), ) .arg( Arg::new("DAEMONIZE_PID_PATH") .long("daemonize-pid") .num_args(1) .action(ArgAction::Set) .value_parser(clap::value_parser!(PathBuf)) .value_hint(ValueHint::FilePath) .help("File path to store daemonized process's PID"), ) .arg( Arg::new("MANAGER_SERVER_MODE") .long("manager-server-mode") .num_args(1) .action(ArgAction::Set) .value_parser(vparser::parse_manager_server_mode) // .possible_values(["builtin", "standalone"]) .help("Servers mode: builtin (default) or standalone"), ) .arg( Arg::new("MANAGER_SERVER_WORKING_DIRECTORY") .long("manager-server-working-directory") .num_args(1) .action(ArgAction::Set) .value_parser(clap::value_parser!(PathBuf)) .value_hint(ValueHint::DirPath) .help("Folder for putting servers' configuration and pid files, default is current directory"), ); } #[cfg(all(unix, not(target_os = "android")))] { app = app.arg( Arg::new("NOFILE") .short('n') .long("nofile") .num_args(1) .action(ArgAction::Set) .value_parser(clap::value_parser!(u64)) .help("Set RLIMIT_NOFILE with both soft and hard limit"), ); } #[cfg(any(target_os = "linux", target_os = "android"))] { app = app.arg( Arg::new("OUTBOUND_FWMARK") .long("outbound-fwmark") .num_args(1) .action(ArgAction::Set) .value_parser(clap::value_parser!(u32)) .help("Set SO_MARK option for outbound sockets"), ); } #[cfg(target_os = "freebsd")] { app = app.arg( Arg::new("OUTBOUND_USER_COOKIE") .long("outbound-user-cookie") .num_args(1) .action(ArgAction::Set) .value_parser(clap::value_parser!(u32)) .help("Set SO_USER_COOKIE option for outbound sockets"), ); } #[cfg(feature = "multi-threaded")] { app = app .arg( Arg::new("SINGLE_THREADED") .long("single-threaded") .action(ArgAction::SetTrue) .help("Run the program all in one thread"), ) .arg( Arg::new("WORKER_THREADS") .long("worker-threads") .num_args(1) .action(ArgAction::Set) .value_parser(clap::value_parser!(usize)) .help("Sets the number of worker threads the `Runtime` will use"), ); } #[cfg(unix)] { app = app.arg( Arg::new("USER") .long("user") .short('a') .num_args(1) .action(ArgAction::Set) .value_hint(ValueHint::Username) .help("Run as another user"), ); } app } /// Create `Runtime` and `main` entry pub fn create(matches: &ArgMatches) -> ShadowsocksResult<(Runtime, impl Future + use<>)> { let (config, runtime) = { let config_path_opt = matches.get_one::("CONFIG").cloned().or_else(|| { if !matches.contains_id("SERVER_CONFIG") { match crate::config::get_default_config_path("manager.json") { None => None, Some(p) => { println!("loading default config {p:?}"); Some(p) } } } else { None } }); let mut service_config = match config_path_opt { Some(ref config_path) => ServiceConfig::load_from_file(config_path) .map_err(|err| ShadowsocksError::LoadConfigFailure(format!("loading config {config_path:?}, {err}")))?, None => ServiceConfig::default(), }; service_config.set_options(matches); #[cfg(feature = "logging")] match service_config.log.config_path { Some(ref path) => { logging::init_with_file(path); } None => { logging::init_with_config("ssmanager", &service_config.log); } } trace!("{:?}", service_config); let mut config = match config_path_opt { Some(cpath) => Config::load_from_file(&cpath, ConfigType::Manager) .map_err(|err| ShadowsocksError::LoadConfigFailure(format!("loading config {cpath:?}, {err}")))?, None => Config::new(ConfigType::Manager), }; if matches.get_flag("TCP_NO_DELAY") { config.no_delay = true; } if matches.get_flag("TCP_FAST_OPEN") { config.fast_open = true; } if let Some(keep_alive) = matches.get_one::("TCP_KEEP_ALIVE") { config.keep_alive = Some(Duration::from_secs(*keep_alive)); } if matches.get_flag("TCP_MULTIPATH") { config.mptcp = true; } #[cfg(any(target_os = "linux", target_os = "android"))] if let Some(mark) = matches.get_one::("OUTBOUND_FWMARK") { config.outbound_fwmark = Some(*mark); } #[cfg(target_os = "freebsd")] if let Some(user_cookie) = matches.get_one::("OUTBOUND_USER_COOKIE") { config.outbound_user_cookie = Some(*user_cookie); } if let Some(iface) = matches.get_one::("OUTBOUND_BIND_INTERFACE").cloned() { config.outbound_bind_interface = Some(iface); } if let Some(addr) = matches.get_one::("MANAGER_ADDR").cloned() { match config.manager { Some(ref mut manager_config) => { manager_config.addr = addr; } _ => { config.manager = Some(ManagerConfig::new(addr)); } } } #[cfg(all(unix, not(target_os = "android")))] match matches.get_one::("NOFILE") { Some(nofile) => config.nofile = Some(*nofile), None => { if config.nofile.is_none() { crate::sys::adjust_nofile(); } } } if let Some(ref mut manager_config) = config.manager { if let Some(m) = matches.get_one::("ENCRYPT_METHOD").cloned() { manager_config.method = Some(m.parse::().expect("method")); } if let Some(t) = matches.get_one::("TIMEOUT") { manager_config.timeout = Some(Duration::from_secs(*t)); } if let Some(sh) = matches.get_one::("SERVER_HOST").cloned() { manager_config.server_host = sh; } if let Some(p) = matches.get_one::("PLUGIN").cloned() { manager_config.plugin = Some(PluginConfig { plugin: p, plugin_opts: matches.get_one::("PLUGIN_OPT").cloned(), plugin_args: Vec::new(), plugin_mode: matches .get_one::("PLUGIN_MODE") .map(|x| { x.parse::() .expect("plugin-mode must be one of `tcp_only` (default), `udp_only` and `tcp_and_udp`") }) .unwrap_or(Mode::TcpOnly), }); } #[cfg(unix)] if let Some(server_mode) = matches.get_one::("MANAGER_SERVER_MODE").cloned() { manager_config.server_mode = server_mode; } #[cfg(unix)] if let Some(server_working_directory) = matches.get_one::("MANAGER_SERVER_WORKING_DIRECTORY").cloned() { manager_config.server_working_directory = server_working_directory; } } // Overrides if matches.get_flag("UDP_ONLY") && let Some(ref mut m) = config.manager { m.mode = Mode::UdpOnly; } if matches.get_flag("TCP_AND_UDP") && let Some(ref mut m) = config.manager { m.mode = Mode::TcpAndUdp; } if let Some(acl_file) = matches.get_one::("ACL") { let acl = AccessControl::load_from_file(acl_file) .map_err(|err| ShadowsocksError::LoadAclFailure(format!("loading ACL \"{acl_file}\", {err}")))?; config.acl = Some(acl); } if let Some(dns) = matches.get_one::("DNS") { config.set_dns_formatted(dns).expect("dns"); } if let Some(dns_cache_size) = matches.get_one::("DNS_CACHE_SIZE") { config.dns_cache_size = Some(*dns_cache_size); } if matches.get_flag("IPV6_FIRST") { config.ipv6_first = true; } if let Some(udp_timeout) = matches.get_one::("UDP_TIMEOUT") { config.udp_timeout = Some(Duration::from_secs(*udp_timeout)); } if let Some(udp_max_assoc) = matches.get_one::("UDP_MAX_ASSOCIATIONS") { config.udp_max_associations = Some(*udp_max_assoc); } if let Some(bs) = matches.get_one::("INBOUND_SEND_BUFFER_SIZE") { config.inbound_send_buffer_size = Some(*bs); } if let Some(bs) = matches.get_one::("INBOUND_RECV_BUFFER_SIZE") { config.inbound_recv_buffer_size = Some(*bs); } if let Some(bs) = matches.get_one::("OUTBOUND_SEND_BUFFER_SIZE") { config.outbound_send_buffer_size = Some(*bs); } if let Some(bs) = matches.get_one::("OUTBOUND_RECV_BUFFER_SIZE") { config.outbound_recv_buffer_size = Some(*bs); } if let Some(bind_addr) = matches.get_one::("OUTBOUND_BIND_ADDR") { config.outbound_bind_addr = Some(*bind_addr); } // DONE reading options config.manager.as_ref().ok_or_else(|| { ShadowsocksError::InsufficientParams( "missing `manager_address`, consider specifying it by --manager-address command line option, \ or \"manager_address\" and \"manager_port\" keys in configuration file" .to_string(), ) })?; config .check_integrity() .map_err(|err| ShadowsocksError::LoadConfigFailure(format!("config integrity check failed, {err}")))?; #[cfg(unix)] if matches.get_flag("DAEMONIZE") || matches.get_raw("DAEMONIZE_PID_PATH").is_some() { use crate::daemonize; daemonize::daemonize(matches.get_one::("DAEMONIZE_PID_PATH")); } #[cfg(unix)] if let Some(uname) = matches.get_one::("USER") { crate::sys::run_as_user(uname).map_err(|err| { ShadowsocksError::InsufficientParams(format!("failed to change as user, error: {err}")) })?; } info!("shadowsocks manager {} build {}", crate::VERSION, crate::BUILD_TIME); let mut builder = match service_config.runtime.mode { RuntimeMode::SingleThread => Builder::new_current_thread(), #[cfg(feature = "multi-threaded")] RuntimeMode::MultiThread => { let mut builder = Builder::new_multi_thread(); if let Some(worker_threads) = service_config.runtime.worker_count { builder.worker_threads(worker_threads); } builder } }; let runtime = builder.enable_all().build().expect("create tokio Runtime"); (config, runtime) }; let main_fut = async move { let abort_signal = monitor::create_signal_monitor(); let server = run_manager(config); tokio::pin!(abort_signal); tokio::pin!(server); match future::select(server, abort_signal).await { // Server future resolved without an error. This should never happen. Either::Left((Ok(..), ..)) => Err(ShadowsocksError::ServerExitUnexpectedly( "server exited unexpectedly".to_owned(), )), // Server future resolved with error, which are listener errors in most cases Either::Left((Err(err), ..)) => Err(ShadowsocksError::ServerAborted(format!("server aborted with {err}"))), // The abort signal future resolved. Means we should just exit. Either::Right(_) => Ok(()), } }; Ok((runtime, main_fut)) } /// Program entrance `main` #[inline] pub fn main(matches: &ArgMatches) -> ExitCode { match create(matches).and_then(|(runtime, main_fut)| runtime.block_on(main_fut)) { Ok(()) => ExitCode::SUCCESS, Err(err) => { eprintln!("{err}"); err.exit_code().into() } } } #[cfg(test)] mod test { use clap::Command; #[test] fn verify_manager_command() { let mut app = Command::new("shadowsocks") .version(crate::VERSION) .about("A fast tunnel proxy that helps you bypass firewalls. (https://shadowsocks.org)"); app = super::define_command_line_options(app); app.debug_assert(); } } ================================================ FILE: src/service/mod.rs ================================================ //! Service launchers pub mod genkey; #[cfg(feature = "local")] pub mod local; #[cfg(feature = "manager")] pub mod manager; #[cfg(feature = "server")] pub mod server; ================================================ FILE: src/service/server.rs ================================================ //! Server launchers use std::{future::Future, net::IpAddr, path::PathBuf, process::ExitCode, time::Duration}; use clap::{Arg, ArgAction, ArgGroup, ArgMatches, Command, ValueHint, builder::PossibleValuesParser}; use futures::future::{self, Either}; use log::{info, trace}; use tokio::{ self, runtime::{Builder, Runtime}, }; use shadowsocks_service::{ acl::AccessControl, config::{Config, ConfigType, ManagerConfig, ServerInstanceConfig, read_variable_field_value}, run_server, shadowsocks::{ config::{ManagerAddr, Mode, ServerAddr, ServerConfig}, crypto::{CipherKind, available_ciphers}, plugin::PluginConfig, }, }; #[cfg(feature = "logging")] use crate::logging; use crate::{ config::{Config as ServiceConfig, RuntimeMode}, error::{ShadowsocksError, ShadowsocksResult}, monitor, vparser, }; /// Defines command line options pub fn define_command_line_options(mut app: Command) -> Command { app = app .arg( Arg::new("CONFIG") .short('c') .long("config") .num_args(1) .action(ArgAction::Set) .value_parser(clap::value_parser!(PathBuf)) .value_hint(ValueHint::FilePath) .help("Shadowsocks configuration file (https://shadowsocks.org/doc/configs.html)"), ) .arg( Arg::new("OUTBOUND_BIND_ADDR") .short('b') .long("outbound-bind-addr") .num_args(1) .action(ArgAction::Set) .alias("bind-addr") .value_parser(vparser::parse_ip_addr) .help("Bind address, outbound socket will bind this address"), ) .arg( Arg::new("OUTBOUND_BIND_INTERFACE") .long("outbound-bind-interface") .num_args(1) .action(ArgAction::Set) .help("Set SO_BINDTODEVICE / IP_BOUND_IF / IP_UNICAST_IF option for outbound socket"), ) .arg( Arg::new("SERVER_ADDR") .short('s') .long("server-addr") .num_args(1) .action(ArgAction::Set) .requires("ENCRYPT_METHOD") .help("Server address"), ) .arg( Arg::new("PASSWORD") .short('k') .long("password") .num_args(1) .action(ArgAction::Set) .requires("SERVER_ADDR") .help("Server's password"), ) .arg( Arg::new("ENCRYPT_METHOD") .short('m') .long("encrypt-method") .num_args(1) .action(ArgAction::Set) .value_parser(PossibleValuesParser::new(available_ciphers())) .requires("SERVER_ADDR") .help("Server's encryption method"), ) .arg( Arg::new("TIMEOUT") .long("timeout") .num_args(1) .action(ArgAction::Set) .value_parser(clap::value_parser!(u64)) .requires("SERVER_ADDR") .help("Server's timeout seconds for TCP relay"), ) .group( ArgGroup::new("SERVER_CONFIG").arg("SERVER_ADDR") ) .arg( Arg::new("UDP_ONLY") .short('u') .action(ArgAction::SetTrue) .conflicts_with("TCP_AND_UDP") .requires("SERVER_ADDR") .help("Server mode UDP_ONLY"), ) .arg( Arg::new("TCP_AND_UDP") .short('U') .action(ArgAction::SetTrue) .requires("SERVER_ADDR") .help("Server mode TCP_AND_UDP"), ) .arg( Arg::new("PLUGIN") .long("plugin") .num_args(1) .action(ArgAction::Set) .value_hint(ValueHint::CommandName) .requires("SERVER_ADDR") .help("SIP003 (https://shadowsocks.org/doc/sip003.html) plugin"), ) .arg( Arg::new("PLUGIN_MODE") .long("plugin-mode") .num_args(1) .action(ArgAction::Set) .requires("PLUGIN") .help("SIP003/SIP003u plugin mode, must be one of `tcp_only` (default), `udp_only` and `tcp_and_udp`"), ) .arg( Arg::new("PLUGIN_OPT") .long("plugin-opts") .num_args(1) .action(ArgAction::Set) .requires("PLUGIN") .help("Set SIP003 plugin options"), ) .arg(Arg::new("MANAGER_ADDR").long("manager-addr").num_args(1).action(ArgAction::Set).value_parser(vparser::parse_manager_addr).alias("manager-address").help("ShadowSocks Manager (ssmgr) address, could be \"IP:Port\", \"Domain:Port\" or \"/path/to/unix.sock\"")) .arg(Arg::new("ACL").long("acl").num_args(1).action(ArgAction::Set).value_hint(ValueHint::FilePath).help("Path to ACL (Access Control List)")) .arg(Arg::new("DNS").long("dns").num_args(1).action(ArgAction::Set).help("DNS nameservers, formatted like [(tcp|udp)://]host[:port][,host[:port]]..., or unix:///path/to/dns, or predefined keys like \"google\", \"cloudflare\"")) .arg(Arg::new("DNS_CACHE_SIZE").long("dns-cache-size").num_args(1).action(ArgAction::Set).value_parser(clap::value_parser!(usize)).help("DNS cache size in number of records. Works when trust-dns DNS backend is enabled.")) .arg(Arg::new("TCP_NO_DELAY").long("tcp-no-delay").alias("no-delay").action(ArgAction::SetTrue).help("Set TCP_NODELAY option for sockets")) .arg(Arg::new("TCP_FAST_OPEN").long("tcp-fast-open").alias("fast-open").action(ArgAction::SetTrue).help("Enable TCP Fast Open (TFO)")) .arg(Arg::new("TCP_KEEP_ALIVE").long("tcp-keep-alive").num_args(1).action(ArgAction::Set).value_parser(clap::value_parser!(u64)).help("Set TCP keep alive timeout seconds")) .arg(Arg::new("TCP_MULTIPATH").long("tcp-multipath").alias("mptcp").action(ArgAction::SetTrue).help("Enable Multipath-TCP (MPTCP)")) .arg(Arg::new("UDP_TIMEOUT").long("udp-timeout").num_args(1).action(ArgAction::Set).value_parser(clap::value_parser!(u64)).help("Timeout seconds for UDP relay")) .arg(Arg::new("UDP_MAX_ASSOCIATIONS").long("udp-max-associations").num_args(1).action(ArgAction::Set).value_parser(clap::value_parser!(usize)).help("Maximum associations to be kept simultaneously for UDP relay")) .arg(Arg::new("INBOUND_SEND_BUFFER_SIZE").long("inbound-send-buffer-size").num_args(1).action(ArgAction::Set).value_parser(clap::value_parser!(u32)).help("Set inbound sockets' SO_SNDBUF option")) .arg(Arg::new("INBOUND_RECV_BUFFER_SIZE").long("inbound-recv-buffer-size").num_args(1).action(ArgAction::Set).value_parser(clap::value_parser!(u32)).help("Set inbound sockets' SO_RCVBUF option")) .arg(Arg::new("OUTBOUND_SEND_BUFFER_SIZE").long("outbound-send-buffer-size").num_args(1).action(ArgAction::Set).value_parser(clap::value_parser!(u32)).help("Set outbound sockets' SO_SNDBUF option")) .arg(Arg::new("OUTBOUND_RECV_BUFFER_SIZE").long("outbound-recv-buffer-size").num_args(1).action(ArgAction::Set).value_parser(clap::value_parser!(u32)).help("Set outbound sockets' SO_RCVBUF option")) .arg( Arg::new("IPV6_FIRST") .short('6') .action(ArgAction::SetTrue) .help("Resolve hostname to IPv6 address first"), ); #[cfg(feature = "logging")] { app = app .arg( Arg::new("VERBOSE") .short('v') .action(ArgAction::Count) .help("Set log level"), ) .arg( Arg::new("LOG_WITHOUT_TIME") .long("log-without-time") .action(ArgAction::SetTrue) .help("Log without datetime prefix"), ) .arg( Arg::new("LOG_CONFIG") .long("log-config") // deprecated for removal .hide(true) .num_args(1) .action(ArgAction::Set) .value_parser(clap::value_parser!(PathBuf)) .value_hint(ValueHint::FilePath) .help("log4rs configuration file"), ); } #[cfg(unix)] { app = app .arg( Arg::new("DAEMONIZE") .short('d') .long("daemonize") .action(ArgAction::SetTrue) .help("Daemonize"), ) .arg( Arg::new("DAEMONIZE_PID_PATH") .long("daemonize-pid") .num_args(1) .action(ArgAction::Set) .value_parser(clap::value_parser!(PathBuf)) .value_hint(ValueHint::FilePath) .help("File path to store daemonized process's PID"), ); } #[cfg(all(unix, not(target_os = "android")))] { app = app.arg( Arg::new("NOFILE") .short('n') .long("nofile") .num_args(1) .action(ArgAction::Set) .value_parser(clap::value_parser!(u64)) .help("Set RLIMIT_NOFILE with both soft and hard limit"), ); } #[cfg(any(target_os = "linux", target_os = "android"))] { app = app.arg( Arg::new("OUTBOUND_FWMARK") .long("outbound-fwmark") .num_args(1) .action(ArgAction::Set) .value_parser(clap::value_parser!(u32)) .help("Set SO_MARK option for outbound sockets"), ); } #[cfg(target_os = "freebsd")] { app = app.arg( Arg::new("OUTBOUND_USER_COOKIE") .long("outbound-user-cookie") .num_args(1) .action(ArgAction::Set) .value_parser(clap::value_parser!(u32)) .help("Set SO_USER_COOKIE option for outbound sockets"), ); } #[cfg(feature = "multi-threaded")] { app = app .arg( Arg::new("SINGLE_THREADED") .long("single-threaded") .action(ArgAction::SetTrue) .help("Run the program all in one thread"), ) .arg( Arg::new("WORKER_THREADS") .long("worker-threads") .num_args(1) .action(ArgAction::Set) .value_parser(clap::value_parser!(usize)) .help("Sets the number of worker threads the `Runtime` will use"), ); } #[cfg(unix)] { app = app.arg( Arg::new("USER") .long("user") .short('a') .num_args(1) .action(ArgAction::Set) .value_hint(ValueHint::Username) .help("Run as another user"), ); } app } /// Create `Runtime` and `main` entry pub fn create(matches: &ArgMatches) -> ShadowsocksResult<(Runtime, impl Future + use<>)> { let (config, runtime) = { let config_path_opt = matches.get_one::("CONFIG").cloned().or_else(|| { if !matches.contains_id("SERVER_CONFIG") { match crate::config::get_default_config_path("server.json") { None => None, Some(p) => { println!("loading default config {p:?}"); Some(p) } } } else { None } }); let mut service_config = match config_path_opt { Some(ref config_path) => ServiceConfig::load_from_file(config_path) .map_err(|err| ShadowsocksError::LoadConfigFailure(format!("loading config {config_path:?}, {err}")))?, None => ServiceConfig::default(), }; service_config.set_options(matches); #[cfg(feature = "logging")] match service_config.log.config_path { Some(ref path) => { logging::init_with_file(path); } None => { logging::init_with_config("ssserver", &service_config.log); } } trace!("{:?}", service_config); let mut config = match config_path_opt { Some(cpath) => Config::load_from_file(&cpath, ConfigType::Server) .map_err(|err| ShadowsocksError::LoadConfigFailure(format!("loading config {cpath:?}, {err}")))?, None => Config::new(ConfigType::Server), }; if let Some(svr_addr) = matches.get_one::("SERVER_ADDR") { let method = matches .get_one::("ENCRYPT_METHOD") .map(|x| x.parse::().expect("method")) .expect("`method` is required"); let password = match matches.get_one::("PASSWORD") { Some(pwd) => read_variable_field_value(pwd).into(), None => { // NOTE: svr_addr should have been checked by crate::vparser if method.is_none() { // If method doesn't need a key (none, plain), then we can leave it empty String::new() } else { match crate::password::read_server_password(svr_addr) { Ok(pwd) => pwd, Err(..) => panic!("`password` is required for server {svr_addr}"), } } } }; let svr_addr = svr_addr.parse::().expect("server-addr"); let timeout = matches.get_one::("TIMEOUT").map(|x| Duration::from_secs(*x)); let mut sc = match ServerConfig::new(svr_addr, password, method) { Ok(sc) => sc, Err(err) => { panic!("failed to create ServerConfig, error: {}", err); } }; if let Some(timeout) = timeout { sc.set_timeout(timeout); } if let Some(p) = matches.get_one::("PLUGIN").cloned() { let plugin = PluginConfig { plugin: p, plugin_opts: matches.get_one::("PLUGIN_OPT").cloned(), plugin_args: Vec::new(), plugin_mode: matches .get_one::("PLUGIN_MODE") .map(|x| { x.parse::() .expect("plugin-mode must be one of `tcp_only` (default), `udp_only` and `tcp_and_udp`") }) .unwrap_or(Mode::TcpOnly), }; sc.set_plugin(plugin); } // For historical reason, servers that are created from command-line have to be tcp_only. sc.set_mode(Mode::TcpOnly); if matches.get_flag("UDP_ONLY") { sc.set_mode(Mode::UdpOnly); } if matches.get_flag("TCP_AND_UDP") { sc.set_mode(Mode::TcpAndUdp); } config.server.push(ServerInstanceConfig::with_server_config(sc)); } if matches.get_flag("TCP_NO_DELAY") { config.no_delay = true; } if matches.get_flag("TCP_FAST_OPEN") { config.fast_open = true; } if let Some(keep_alive) = matches.get_one::("TCP_KEEP_ALIVE") { config.keep_alive = Some(Duration::from_secs(*keep_alive)); } if matches.get_flag("TCP_MULTIPATH") { config.mptcp = true; } #[cfg(any(target_os = "linux", target_os = "android"))] if let Some(mark) = matches.get_one::("OUTBOUND_FWMARK") { config.outbound_fwmark = Some(*mark); } #[cfg(target_os = "freebsd")] if let Some(user_cookie) = matches.get_one::("OUTBOUND_USER_COOKIE") { config.outbound_user_cookie = Some(*user_cookie); } if let Some(iface) = matches.get_one::("OUTBOUND_BIND_INTERFACE").cloned() { config.outbound_bind_interface = Some(iface); } if let Some(addr) = matches.get_one::("MANAGER_ADDR").cloned() { match config.manager { Some(ref mut manager_config) => { manager_config.addr = addr; } _ => { config.manager = Some(ManagerConfig::new(addr)); } } } #[cfg(all(unix, not(target_os = "android")))] match matches.get_one::("NOFILE") { Some(nofile) => config.nofile = Some(*nofile), None => { if config.nofile.is_none() { crate::sys::adjust_nofile(); } } } if let Some(acl_file) = matches.get_one::("ACL") { let acl = AccessControl::load_from_file(acl_file) .map_err(|err| ShadowsocksError::LoadAclFailure(format!("loading ACL \"{acl_file}\", {err}")))?; config.acl = Some(acl); } if let Some(dns) = matches.get_one::("DNS") { config.set_dns_formatted(dns).expect("dns"); } if let Some(dns_cache_size) = matches.get_one::("DNS_CACHE_SIZE") { config.dns_cache_size = Some(*dns_cache_size); } if matches.get_flag("IPV6_FIRST") { config.ipv6_first = true; } if let Some(udp_timeout) = matches.get_one::("UDP_TIMEOUT") { config.udp_timeout = Some(Duration::from_secs(*udp_timeout)); } if let Some(udp_max_assoc) = matches.get_one::("UDP_MAX_ASSOCIATIONS") { config.udp_max_associations = Some(*udp_max_assoc); } if let Some(bs) = matches.get_one::("INBOUND_SEND_BUFFER_SIZE") { config.inbound_send_buffer_size = Some(*bs); } if let Some(bs) = matches.get_one::("INBOUND_RECV_BUFFER_SIZE") { config.inbound_recv_buffer_size = Some(*bs); } if let Some(bs) = matches.get_one::("OUTBOUND_SEND_BUFFER_SIZE") { config.outbound_send_buffer_size = Some(*bs); } if let Some(bs) = matches.get_one::("OUTBOUND_RECV_BUFFER_SIZE") { config.outbound_recv_buffer_size = Some(*bs); } if let Some(bind_addr) = matches.get_one::("OUTBOUND_BIND_ADDR") { config.outbound_bind_addr = Some(*bind_addr); } // DONE READING options if config.server.is_empty() { return Err(ShadowsocksError::InsufficientParams( "missing proxy servers, consider specifying it by \ --server-addr, --encrypt-method, --password command line option, \ or configuration file, check more details in https://shadowsocks.org/doc/configs.html" .to_string(), )); } config .check_integrity() .map_err(|err| ShadowsocksError::LoadConfigFailure(format!("config integrity check failed, {err}")))?; #[cfg(unix)] if matches.get_flag("DAEMONIZE") || matches.get_raw("DAEMONIZE_PID_PATH").is_some() { use crate::daemonize; daemonize::daemonize(matches.get_one::("DAEMONIZE_PID_PATH")); } #[cfg(unix)] if let Some(uname) = matches.get_one::("USER") { crate::sys::run_as_user(uname).map_err(|err| { ShadowsocksError::InsufficientParams(format!("failed to change as user, error: {err}")) })?; } info!("shadowsocks server {} build {}", crate::VERSION, crate::BUILD_TIME); let mut builder = match service_config.runtime.mode { RuntimeMode::SingleThread => Builder::new_current_thread(), #[cfg(feature = "multi-threaded")] RuntimeMode::MultiThread => { let mut builder = Builder::new_multi_thread(); if let Some(worker_threads) = service_config.runtime.worker_count { builder.worker_threads(worker_threads); } builder } }; let runtime = builder.enable_all().build().expect("create tokio Runtime"); (config, runtime) }; let main_fut = async move { let abort_signal = monitor::create_signal_monitor(); let server = run_server(config); tokio::pin!(abort_signal); tokio::pin!(server); match future::select(server, abort_signal).await { // Server future resolved without an error. This should never happen. Either::Left((Ok(..), ..)) => Err(ShadowsocksError::ServerExitUnexpectedly( "server exited unexpectedly".to_owned(), )), // Server future resolved with error, which are listener errors in most cases Either::Left((Err(err), ..)) => Err(ShadowsocksError::ServerAborted(format!("server aborted with {err}"))), // The abort signal future resolved. Means we should just exit. Either::Right(_) => Ok(()), } }; Ok((runtime, main_fut)) } /// Program entrance `main` #[inline] pub fn main(matches: &ArgMatches) -> ExitCode { match create(matches).and_then(|(runtime, main_fut)| runtime.block_on(main_fut)) { Ok(()) => ExitCode::SUCCESS, Err(err) => { eprintln!("{err}"); err.exit_code().into() } } } #[cfg(test)] mod test { use clap::Command; #[test] fn verify_server_command() { let mut app = Command::new("shadowsocks") .version(crate::VERSION) .about("A fast tunnel proxy that helps you bypass firewalls. (https://shadowsocks.org)"); app = super::define_command_line_options(app); app.debug_assert(); } } ================================================ FILE: src/sys.rs ================================================ //! System related APIs /// Some systems set an artificially low soft limit on open file count, for compatibility /// with code that uses select and its hard-coded maximum file descriptor /// (limited by the size of fd_set). /// /// Tokio (Mio) doesn't use select. /// /// http://0pointer.net/blog/file-descriptor-limits.html /// https://github.com/golang/go/issues/46279 #[cfg(all(unix, not(target_os = "android")))] pub fn adjust_nofile() { use log::{debug, trace}; use std::{io::Error, mem}; unsafe { let mut lim: libc::rlimit = mem::zeroed(); let ret = libc::getrlimit(libc::RLIMIT_NOFILE, &mut lim); if ret < 0 { debug!("getrlimit NOFILE failed, {}", Error::last_os_error()); return; } if lim.rlim_cur != lim.rlim_max { trace!("rlimit NOFILE {:?} require adjustion", lim); lim.rlim_cur = lim.rlim_max; // On older macOS, setrlimit with rlim_cur = infinity will fail. #[cfg(any(target_os = "macos", target_os = "ios", target_os = "watchos", target_os = "tvos"))] { use std::ptr; unsafe extern "C" { fn sysctlbyname( name: *const libc::c_char, oldp: *mut libc::c_void, oldlenp: *mut libc::size_t, newp: *mut libc::c_void, newlen: libc::size_t, ) -> libc::c_int; } // CTL_KERN // // Name Type Changeable // kern.maxfiles int32_t yes // kern.maxfilesperproc int32_t yes let name = b"kern.maxfilesperproc\0"; let mut nfile: i32 = 0; let mut nfile_len: libc::size_t = mem::size_of_val(&nfile); let ret = sysctlbyname( name.as_ptr() as *const _, &mut nfile as *mut _ as *mut _, &mut nfile_len, ptr::null_mut(), 0, ); if ret < 0 { debug!("sysctlbyname kern.maxfilesperproc failed, {}", Error::last_os_error()); } else { lim.rlim_cur = nfile as libc::rlim_t; } } let ret = libc::setrlimit(libc::RLIMIT_NOFILE, &lim); if ret < 0 { debug!("setrlimit NOFILE {:?} failed, {}", lim, Error::last_os_error()); } else { debug!("rlimit NOFILE adjusted {:?}", lim); } } } } /// setuid(), setgid() for a specific user or uid #[cfg(unix)] pub fn run_as_user(uname: &str) -> std::io::Result<()> { use log::error; use std::{ ffi::{CStr, CString}, io::{Error, ErrorKind}, }; unsafe { let pwd = match uname.parse::() { Ok(uid) => { let mut pwd = libc::getpwuid(uid); if pwd.is_null() { let uname = CString::new(uname).expect("username"); pwd = libc::getpwnam(uname.as_ptr()) } pwd } Err(..) => { let uname = CString::new(uname).expect("username"); libc::getpwnam(uname.as_ptr()) } }; if pwd.is_null() { return Err(Error::new(ErrorKind::InvalidInput, format!("user {} not found", uname))); } let pwd = &*pwd; // setgid first, because we may not allowed to do it anymore after setuid if libc::setgid(pwd.pw_gid as libc::gid_t) != 0 { let err = Error::last_os_error(); error!( "could not change group id to user {:?}'s gid: {}, uid: {}, error: {}", CStr::from_ptr(pwd.pw_name), pwd.pw_gid, pwd.pw_uid, err ); return Err(err); } if libc::initgroups(pwd.pw_name, pwd.pw_gid as _) != 0 { let err = Error::last_os_error(); error!( "could not change supplementary groups to user {:?}'s gid: {}, uid: {}, error: {}", CStr::from_ptr(pwd.pw_name), pwd.pw_gid, pwd.pw_uid, err ); return Err(err); } if libc::setuid(pwd.pw_uid) != 0 { let err = Error::last_os_error(); error!( "could not change user id to user {:?}'s gid: {}, uid: {}, error: {}", CStr::from_ptr(pwd.pw_name), pwd.pw_gid, pwd.pw_uid, err ); return Err(err); } } Ok(()) } ================================================ FILE: src/vparser/mod.rs ================================================ //! Command line argument validator #![allow(dead_code)] use std::net::{IpAddr, SocketAddr}; #[cfg(any(feature = "local-tun", feature = "local-fake-dns"))] use ipnet::IpNet; #[cfg(feature = "local-redir")] use shadowsocks_service::config::RedirType; #[cfg(feature = "local-dns")] use shadowsocks_service::local::dns::NameServerAddr; use shadowsocks_service::{ config::{ManagerServerHost, ManagerServerMode}, shadowsocks::{ManagerAddr, ServerAddr, ServerConfig, crypto::CipherKind, relay::socks5::Address}, }; macro_rules! value_parser_type { ($name:ident, $ty:ty, $help:expr) => { pub fn $name(v: &str) -> Result<$ty, String> { match v.parse::<$ty>() { Ok(t) => Ok(t), Err(..) => Err($help.to_owned()), } } }; } value_parser_type!(parse_server_addr, ServerAddr, "should be either ip:port or domain:port"); value_parser_type!(parse_ip_addr, IpAddr, "should be a valid IPv4 or IPv6 address"); value_parser_type!(parse_socket_addr, SocketAddr, "should be ip:port"); value_parser_type!(parse_address, Address, "should be either ip:port or domain:port"); value_parser_type!( parse_manager_addr, ManagerAddr, "should be either ip:port, domain:port or /path/to/unix.sock" ); value_parser_type!(parse_manager_server_host, ManagerServerHost, "invalid server-host"); value_parser_type!( parse_manager_server_mode, ManagerServerMode, "should be \"builtin\" or \"standalone\"" ); #[cfg(feature = "local-dns")] value_parser_type!( parse_name_server_addr, NameServerAddr, "should be either ip:port or a path to unix domain socket" ); value_parser_type!(parse_cipher_kind, CipherKind, "invalid cipher"); pub fn parse_server_url(v: &str) -> Result { match ServerConfig::from_url(v) { Ok(t) => Ok(t), Err(..) => Err("should be SIP002 (https://shadowsocks.org/doc/sip002.html) format".to_owned()), } } #[cfg(any(feature = "local-tun", feature = "local-fake-dns"))] pub fn parse_ipnet(v: &str) -> Result { match v.parse::() { Err(..) => Err("should be a CIDR address like 10.1.2.3/24".to_owned()), Ok(n) => Ok(n), } } #[cfg(feature = "local-redir")] value_parser_type!(parse_redir_type, RedirType, "invalid redir-type"); ================================================ FILE: tests/dns.rs ================================================ #![cfg(all(feature = "local-dns", feature = "server"))] use std::time::Duration; use byteorder::{BigEndian, ByteOrder}; use tokio::{ io::{AsyncReadExt, AsyncWriteExt}, net::{TcpStream, UdpSocket}, time, }; use shadowsocks_service::{ config::{Config, ConfigType}, run_local, run_server, }; #[tokio::test] async fn dns_relay() { let _ = env_logger::try_init(); let local_config = Config::load_from_str( r#"{ "locals": [ { "local_address": "127.0.0.1", "local_port": 6110, "protocol": "dns", "local_dns_address": "114.114.114.114", "remote_dns_address": "8.8.8.8" } ], "server": "127.0.0.1", "server_port": 6120, "password": "password", "method": "aes-256-gcm" }"#, ConfigType::Local, ) .unwrap(); let server_config = Config::load_from_str( r#"{ "server": "127.0.0.1", "server_port": 6120, "password": "password", "method": "aes-256-gcm", "mode": "tcp_and_udp" }"#, ConfigType::Server, ) .unwrap(); tokio::spawn(run_local(local_config)); tokio::spawn(run_server(server_config)); time::sleep(Duration::from_secs(1)).await; // Query firefox.com, TransactionID: 0x1234 const DNS_QUERY: &[u8] = b"\x12\x34\x01\x00\x00\x01\x00\x00\x00\x00\x00\x00\x07firefox\x03com\x00\x00\x01\x00\x01"; // 1. DoT { let mut c = TcpStream::connect("127.0.0.1:6110").await.unwrap(); let mut len_buf = [0u8; 2]; BigEndian::write_u16(&mut len_buf, DNS_QUERY.len() as u16); c.write_all(&len_buf).await.unwrap(); c.write_all(DNS_QUERY).await.unwrap(); c.flush().await.unwrap(); c.read_exact(&mut len_buf).await.unwrap(); let resp_len = BigEndian::read_u16(&len_buf); let mut buf = vec![0u8; resp_len as usize]; c.read_exact(&mut buf).await.unwrap(); assert!(buf.starts_with(b"\x12\x34")); } // 2. DoU { let c = UdpSocket::bind("0.0.0.0:0").await.unwrap(); c.send_to(DNS_QUERY, "127.0.0.1:6110").await.unwrap(); let mut buf = [0u8; 65536]; let n = c.recv(&mut buf).await.unwrap(); assert!(n >= 12); let pkt = &buf[..n]; assert_eq!(&pkt[..2], b"\x12\x34"); } } ================================================ FILE: tests/http.rs ================================================ #![cfg(all(feature = "local-http", feature = "server"))] use std::time::Duration; use tokio::{ io::{AsyncBufReadExt, AsyncReadExt, AsyncWriteExt, BufReader}, net::TcpStream, time, }; use shadowsocks_service::{ config::{Config, ConfigType}, run_local, run_server, }; #[tokio::test] async fn http_proxy() { let _ = env_logger::try_init(); let local_config = Config::load_from_str( r#"{ "locals": [ { "local_port": 5110, "local_address": "127.0.0.1", "protocol": "http" } ], "server": "127.0.0.1", "server_port": 5120, "password": "password", "method": "aes-256-gcm" }"#, ConfigType::Local, ) .unwrap(); let server_config = Config::load_from_str( r#"{ "server": "127.0.0.1", "server_port": 5120, "password": "password", "method": "aes-256-gcm" }"#, ConfigType::Server, ) .unwrap(); tokio::spawn(run_local(local_config)); tokio::spawn(run_server(server_config)); time::sleep(Duration::from_secs(1)).await; { let mut c = TcpStream::connect("127.0.0.1:5110").await.unwrap(); c.write_all(b"GET http://www.example.com/ HTTP/1.0\r\nHost: www.example.com\r\nAccept: */*\r\n\r\n") .await .unwrap(); c.flush().await.unwrap(); // Proxy should close connection actively because HTTP/1.0 use short connection by default let mut buf = Vec::new(); c.read_to_end(&mut buf).await.unwrap(); assert!(buf.starts_with(b"HTTP/1.0 200 OK\r\n")); } { let mut c = TcpStream::connect("127.0.0.1:5110").await.unwrap(); c.write_all(b"CONNECT http://www.example.com/ HTTP/1.0\r\n\r\n") .await .unwrap(); c.flush().await.unwrap(); c.write_all(b"GET / HTTP/1.0\r\nHost: www.example.com\r\nAccept: */*\r\n\r\n") .await .unwrap(); c.flush().await.unwrap(); let mut r = BufReader::new(c); let mut buf = Vec::new(); r.read_until(b'\n', &mut buf).await.unwrap(); assert!(buf.starts_with(b"HTTP/1.0 200 OK\r\n")); } } ================================================ FILE: tests/socks4.rs ================================================ #![cfg(all(feature = "local-socks4", feature = "server"))] use std::{ net::{SocketAddr, ToSocketAddrs}, str, }; use tokio::{ io::{AsyncBufReadExt, AsyncWriteExt, BufReader}, time::{self, Duration}, }; use shadowsocks_service::{ config::{Config, ConfigType, LocalConfig, LocalInstanceConfig, ProtocolType, ServerInstanceConfig}, local::socks::client::Socks4TcpClient, run_local, run_server, shadowsocks::{ config::{ServerAddr, ServerConfig}, crypto::CipherKind, }, }; pub struct Socks4TestServer { local_addr: SocketAddr, svr_config: Config, cli_config: Config, } impl Socks4TestServer { pub fn new(svr_addr: S, local_addr: L, pwd: &str, method: CipherKind) -> Self where S: ToSocketAddrs, L: ToSocketAddrs, { let svr_addr = svr_addr.to_socket_addrs().unwrap().next().unwrap(); let local_addr = local_addr.to_socket_addrs().unwrap().next().unwrap(); Self { local_addr, svr_config: { let mut cfg = Config::new(ConfigType::Server); cfg.server = vec![ServerInstanceConfig::with_server_config( ServerConfig::new(svr_addr, pwd.to_owned(), method).unwrap(), )]; cfg }, cli_config: { let mut cfg = Config::new(ConfigType::Local); cfg.local = vec![LocalInstanceConfig::with_local_config(LocalConfig::new_with_addr( ServerAddr::from(local_addr), ProtocolType::Socks, ))]; cfg.server = vec![ServerInstanceConfig::with_server_config( ServerConfig::new(svr_addr, pwd.to_owned(), method).unwrap(), )]; cfg }, } } pub fn client_addr(&self) -> &SocketAddr { &self.local_addr } pub async fn run(&self) { let svr_cfg = self.svr_config.clone(); tokio::spawn(run_server(svr_cfg)); let client_cfg = self.cli_config.clone(); tokio::spawn(run_local(client_cfg)); time::sleep(Duration::from_secs(1)).await; } } #[tokio::test] async fn socks4_relay_connect() { let _ = env_logger::try_init(); const SERVER_ADDR: &str = "127.0.0.1:7100"; const LOCAL_ADDR: &str = "127.0.0.1:7200"; const PASSWORD: &str = "test-password"; const METHOD: CipherKind = CipherKind::AES_128_GCM; let svr = Socks4TestServer::new(SERVER_ADDR, LOCAL_ADDR, PASSWORD, METHOD); svr.run().await; const HTTP_REQUEST: &[u8] = b"GET /success.txt HTTP/1.0\r\nHost: detectportal.firefox.com\r\nAccept: */*\r\n\r\n"; let mut c = Socks4TcpClient::connect(("detectportal.firefox.com", 80), LOCAL_ADDR, Vec::new()) .await .unwrap(); c.write_all(HTTP_REQUEST).await.unwrap(); c.flush().await.unwrap(); let mut r = BufReader::new(c); let mut buf = Vec::new(); r.read_until(b'\n', &mut buf).await.unwrap(); let http_status = b"HTTP/1.0 200 OK\r\n"; assert!(buf.starts_with(http_status)); } ================================================ FILE: tests/socks5.rs ================================================ #![cfg(all(feature = "local", feature = "server"))] use std::{ net::{SocketAddr, ToSocketAddrs}, str, }; use tokio::{ io::{AsyncBufReadExt, AsyncWriteExt, BufReader}, time::{self, Duration}, }; use shadowsocks_service::{ config::{Config, ConfigType, LocalConfig, LocalInstanceConfig, ProtocolType, ServerInstanceConfig}, local::socks::client::socks5::Socks5TcpClient, run_local, run_server, shadowsocks::{ config::{Mode, ServerAddr, ServerConfig}, crypto::CipherKind, relay::socks5::Address, }, }; pub struct Socks5TestServer { local_addr: SocketAddr, svr_config: Config, cli_config: Config, } impl Socks5TestServer { pub fn new(svr_addr: S, local_addr: L, pwd: &str, method: CipherKind, enable_udp: bool) -> Self where S: ToSocketAddrs, L: ToSocketAddrs, { let svr_addr = svr_addr.to_socket_addrs().unwrap().next().unwrap(); let local_addr = local_addr.to_socket_addrs().unwrap().next().unwrap(); Self { local_addr, svr_config: { let mut cfg = Config::new(ConfigType::Server); cfg.server = vec![ServerInstanceConfig::with_server_config( ServerConfig::new(svr_addr, pwd.to_owned(), method).unwrap(), )]; cfg.server[0] .config .set_mode(if enable_udp { Mode::TcpAndUdp } else { Mode::TcpOnly }); cfg }, cli_config: { let mut cfg = Config::new(ConfigType::Local); cfg.local = vec![LocalInstanceConfig::with_local_config(LocalConfig::new_with_addr( ServerAddr::from(local_addr), ProtocolType::Socks, ))]; cfg.local[0].config.mode = if enable_udp { Mode::TcpAndUdp } else { Mode::TcpOnly }; cfg.server = vec![ServerInstanceConfig::with_server_config( ServerConfig::new(svr_addr, pwd.to_owned(), method).unwrap(), )]; cfg }, } } pub fn client_addr(&self) -> &SocketAddr { &self.local_addr } pub async fn run(&self) { let svr_cfg = self.svr_config.clone(); tokio::spawn(run_server(svr_cfg)); let client_cfg = self.cli_config.clone(); tokio::spawn(run_local(client_cfg)); time::sleep(Duration::from_secs(1)).await; } } #[cfg(feature = "stream-cipher")] #[tokio::test] async fn socks5_relay_stream() { let _ = env_logger::try_init(); const SERVER_ADDR: &str = "127.0.0.1:8100"; const LOCAL_ADDR: &str = "127.0.0.1:8200"; const PASSWORD: &str = "test-password"; const METHOD: CipherKind = CipherKind::AES_128_CFB128; let svr = Socks5TestServer::new(SERVER_ADDR, LOCAL_ADDR, PASSWORD, METHOD, false); svr.run().await; let mut c = Socks5TcpClient::connect( Address::DomainNameAddress("www.example.com".to_owned(), 80), svr.client_addr(), ) .await .unwrap(); let req = b"GET / HTTP/1.1\r\nHost: www.example.com\r\nAccept: */*\r\nConnection: close\r\n\r\n"; c.write_all(req).await.unwrap(); c.flush().await.unwrap(); let mut r = BufReader::new(c); let mut buf = Vec::new(); r.read_until(b'\n', &mut buf).await.unwrap(); let http_status = b"HTTP/1.1 200 OK\r\n"; assert!(buf.starts_with(http_status), "buf: {:?}", str::from_utf8(&buf)); } #[tokio::test] async fn socks5_relay_aead() { let _ = env_logger::try_init(); const SERVER_ADDR: &str = "127.0.0.1:8110"; const LOCAL_ADDR: &str = "127.0.0.1:8210"; const PASSWORD: &str = "test-password"; const METHOD: CipherKind = CipherKind::AES_256_GCM; let svr = Socks5TestServer::new(SERVER_ADDR, LOCAL_ADDR, PASSWORD, METHOD, false); svr.run().await; let mut c = Socks5TcpClient::connect( Address::DomainNameAddress("detectportal.firefox.com".to_owned(), 80), svr.client_addr(), ) .await .unwrap(); let req = b"GET /success.txt HTTP/1.0\r\nHost: detectportal.firefox.com\r\nAccept: */*\r\n\r\n"; c.write_all(req).await.unwrap(); c.flush().await.unwrap(); let mut r = BufReader::new(c); let mut buf = Vec::new(); r.read_until(b'\n', &mut buf).await.unwrap(); let http_status = b"HTTP/1.0 200 OK\r\n"; assert!(buf.starts_with(http_status)); } ================================================ FILE: tests/tunnel.rs ================================================ #![cfg(all(feature = "local-tunnel", feature = "server"))] use byte_string::ByteStr; use log::debug; use tokio::{ self, io::{AsyncBufReadExt, AsyncWriteExt, BufReader}, net::{TcpStream, UdpSocket}, time::{self, Duration}, }; use shadowsocks_service::{ config::{Config, ConfigType}, run_local, run_server, }; fn random_local_tcp_port_pair() -> (u16, u16) { let listener1 = std::net::TcpListener::bind("127.0.0.1:0").unwrap(); let port1 = listener1.local_addr().unwrap().port(); let listener2 = std::net::TcpListener::bind("127.0.0.1:0").unwrap(); let port2 = listener2.local_addr().unwrap().port(); (port1, port2) } #[tokio::test] async fn tcp_tunnel() { let _ = env_logger::try_init(); let (local_port, server_port) = random_local_tcp_port_pair(); let local_config = Config::load_from_str( &format!( r#"{{ "locals": [ {{ "local_port": {local_port}, "local_address": "127.0.0.1", "protocol": "tunnel", "forward_address": "detectportal.firefox.com", "forward_port": 80 }} ], "server": "127.0.0.1", "server_port": {server_port}, "password": "password", "method": "aes-256-gcm" }}"# ), ConfigType::Local, ) .unwrap(); let server_config = Config::load_from_str( &format!( r#"{{ "server": "127.0.0.1", "server_port": {server_port}, "password": "password", "method": "aes-256-gcm" }}"# ), ConfigType::Server, ) .unwrap(); tokio::spawn(run_local(local_config)); tokio::spawn(run_server(server_config)); time::sleep(Duration::from_secs(5)).await; // Connect it directly, because it is now established a TCP tunnel with detectportal.firefox.com let mut stream = TcpStream::connect(("127.0.0.1", local_port)).await.unwrap(); let req = b"GET /success.txt HTTP/1.0\r\nHost: detectportal.firefox.com\r\nAccept: */*\r\n\r\n"; stream.write_all(req).await.unwrap(); stream.flush().await.unwrap(); let mut r = BufReader::new(stream); let mut buf = Vec::new(); r.read_until(b'\n', &mut buf).await.unwrap(); let http_status = b"HTTP/1.0 200 OK\r\n"; assert!(buf.starts_with(http_status)); } #[tokio::test] async fn udp_tunnel() { let _ = env_logger::try_init(); let socket = UdpSocket::bind("127.0.0.1:0").await.unwrap(); let socket_local_addr = socket.local_addr().unwrap(); let echo_server_port = socket_local_addr.port(); // A UDP echo server tokio::spawn(async move { debug!("UDP echo server listening on {socket_local_addr}"); let mut buffer = [0u8; 65536]; loop { let (n, peer_addr) = socket.recv_from(&mut buffer).await.unwrap(); debug!("UDP echo server received {} bytes from {}, echoing", n, peer_addr); socket.send_to(&buffer[..n], peer_addr).await.unwrap(); } }); time::sleep(Duration::from_secs(1)).await; let (local_port, server_port) = random_local_tcp_port_pair(); let local_config = Config::load_from_str( &format!( r#"{{ "locals": [ {{ "local_port": {local_port}, "local_address": "127.0.0.1", "protocol": "tunnel", "forward_address": "127.0.0.1", "forward_port": {echo_server_port} }} ], "server": "127.0.0.1", "server_port": {server_port}, "password": "password", "method": "aes-256-gcm", "mode": "tcp_and_udp" }}"# ), ConfigType::Local, ) .unwrap(); let server_config = Config::load_from_str( &format!( r#"{{ "server": "127.0.0.1", "server_port": {server_port}, "password": "password", "method": "aes-256-gcm", "mode": "udp_only" }}"# ), ConfigType::Server, ) .unwrap(); tokio::spawn(run_local(local_config)); tokio::spawn(run_server(server_config)); time::sleep(Duration::from_secs(5)).await; const MESSAGE: &[u8] = b"hello shadowsocks"; let socket = UdpSocket::bind("0.0.0.0:0").await.unwrap(); socket.send_to(MESSAGE, ("127.0.0.1", local_port)).await.unwrap(); let mut buf = vec![0u8; 65536]; let n = socket.recv(&mut buf).await.unwrap(); let recv_payload = &buf[..n]; println!("Got reply from server: {:?}", ByteStr::new(recv_payload)); assert_eq!(MESSAGE, recv_payload); } ================================================ FILE: tests/udp.rs ================================================ #![cfg(all(feature = "local", feature = "server"))] use std::net::SocketAddr; use log::debug; use tokio::time::{self, Duration}; use shadowsocks_service::{ config::{Config, ConfigType, LocalConfig, LocalInstanceConfig, ProtocolType, ServerInstanceConfig}, local::socks::client::socks5::Socks5UdpClient, run_local, run_server, shadowsocks::{ServerConfig, config::Mode, crypto::CipherKind, relay::socks5::Address}, }; const SERVER_ADDR: &str = "127.0.0.1:8093"; const LOCAL_ADDR: &str = "127.0.0.1:8291"; const UDP_ECHO_SERVER_ADDR: &str = "127.0.0.1:50403"; const PASSWORD: &str = "test-password"; const METHOD: CipherKind = CipherKind::AES_128_GCM; fn get_svr_config() -> Config { let mut cfg = Config::new(ConfigType::Server); cfg.server = vec![ServerInstanceConfig::with_server_config( ServerConfig::new(SERVER_ADDR.parse::().unwrap(), PASSWORD.to_owned(), METHOD).unwrap(), )]; cfg.server[0].config.set_mode(Mode::TcpAndUdp); cfg } fn get_cli_config() -> Config { let mut cfg = Config::new(ConfigType::Local); cfg.local = vec![LocalInstanceConfig::with_local_config(LocalConfig::new_with_addr( LOCAL_ADDR.parse().unwrap(), ProtocolType::Socks, ))]; cfg.local[0].config.mode = Mode::TcpAndUdp; cfg.server = vec![ServerInstanceConfig::with_server_config( ServerConfig::new(SERVER_ADDR.parse::().unwrap(), PASSWORD.to_owned(), METHOD).unwrap(), )]; cfg } fn get_client_addr() -> SocketAddr { LOCAL_ADDR.parse().unwrap() } fn start_server() { tokio::spawn(run_server(get_svr_config())); } fn start_local() { tokio::spawn(run_local(get_cli_config())); } fn start_udp_echo_server() { use tokio::net::UdpSocket; tokio::spawn(async { let l = UdpSocket::bind(UDP_ECHO_SERVER_ADDR).await.unwrap(); debug!("UDP echo server started {}", UDP_ECHO_SERVER_ADDR); let mut buf = vec![0u8; 65536]; let (amt, src) = l.recv_from(&mut buf).await.unwrap(); debug!("UDP echo received {} bytes from {}", amt, src); l.send_to(&buf[..amt], &src).await.unwrap(); debug!("UDP echo sent {} bytes to {}", amt, src); }); } #[tokio::test] async fn udp_relay() { let _ = env_logger::try_init(); let remote_addr = Address::SocketAddress(UDP_ECHO_SERVER_ADDR.parse().unwrap()); start_server(); start_local(); start_udp_echo_server(); // Wait until all server starts time::sleep(Duration::from_secs(1)).await; let mut l = Socks5UdpClient::bind("127.0.0.1:0".parse::().unwrap()) .await .unwrap(); l.associate(&get_client_addr()).await.unwrap(); let payload = b"HEllo WORld"; l.send_to(0, payload, &remote_addr).await.unwrap(); let mut buf = vec![0u8; 65536]; let (amt, _, recv_addr) = time::timeout(Duration::from_secs(5), l.recv_from(&mut buf)) .await .unwrap() .unwrap(); println!("Received {} buf size={} {:?}", recv_addr, amt, &buf[..amt]); assert_eq!(recv_addr, remote_addr); assert_eq!(&buf[..amt], payload); }