mirror of
https://github.com/bol-van/zapret2.git
synced 2026-03-14 06:13:09 +00:00
Compare commits
156 Commits
6638140880
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7cdc75d0db | ||
|
|
348f907b47 | ||
|
|
d641b00083 | ||
|
|
d3b3011000 | ||
|
|
2ec512af17 | ||
|
|
d41151ef6f | ||
|
|
60ac3693fc | ||
|
|
766b60544f | ||
|
|
e563f60153 | ||
|
|
6d7f8efc49 | ||
|
|
e46cde8e6e | ||
|
|
52072359f0 | ||
|
|
cafacf35bc | ||
|
|
55dc47bae4 | ||
|
|
14a2548bf5 | ||
|
|
f59ddbb645 | ||
|
|
96f58adc7a | ||
|
|
b20ee9adbe | ||
|
|
7bfb4066cd | ||
|
|
a8a742f48c | ||
|
|
03f1fc4788 | ||
|
|
3ae875f8aa | ||
|
|
300084a654 | ||
|
|
ccef4377df | ||
|
|
3ebb24930e | ||
|
|
aff6fe3966 | ||
|
|
f43030c0b8 | ||
|
|
69e8bb3c7f | ||
|
|
038f64ddad | ||
|
|
abdf88574c | ||
|
|
318c625247 | ||
|
|
3e52d53df0 | ||
|
|
410ba5ae6e | ||
|
|
bee761f0f7 | ||
|
|
863267e659 | ||
|
|
c0299a27e3 | ||
|
|
b9e22fd97e | ||
|
|
b3a6445d13 | ||
|
|
75e3c83d07 | ||
|
|
1aaf73858c | ||
|
|
827b1cf065 | ||
|
|
e0f67fb203 | ||
|
|
da6f4c8536 | ||
|
|
f83ecb64bb | ||
|
|
c634fd156c | ||
|
|
c10cc5b83e | ||
|
|
60988755b7 | ||
|
|
7584d5e38f | ||
|
|
d019627fba | ||
|
|
1ac067ec32 | ||
|
|
1b5811aa9a | ||
|
|
60c3f56c36 | ||
|
|
a0cfbbf958 | ||
|
|
437c988f48 | ||
|
|
a9a64b0462 | ||
|
|
9887e470dc | ||
|
|
5bacfcb65f | ||
|
|
0f04698f07 | ||
|
|
31d5e5598b | ||
|
|
66e2cc2bc4 | ||
|
|
8fcc64ad0c | ||
|
|
d2f3271542 | ||
|
|
942c4956b8 | ||
|
|
77a24a7ec1 | ||
|
|
43999d6077 | ||
|
|
697f9fc986 | ||
|
|
8e76197dff | ||
|
|
190f46b6d7 | ||
|
|
41e26b3ace | ||
|
|
8b6ea88a23 | ||
|
|
59235827c4 | ||
|
|
7073e1fd77 | ||
|
|
340261da72 | ||
|
|
937aa91e5d | ||
|
|
dbf673e24a | ||
|
|
61b0a70fa7 | ||
|
|
d985bb316f | ||
|
|
59b3734643 | ||
|
|
37f45a132f | ||
|
|
4d753ecdc6 | ||
|
|
272f086639 | ||
|
|
d9ae16e56f | ||
|
|
46d4208c76 | ||
|
|
2a4195070f | ||
|
|
8e974e78e2 | ||
|
|
7df42bc486 | ||
|
|
7c12f60e1e | ||
|
|
4c7a3d08d8 | ||
|
|
e146fc24c5 | ||
|
|
6165c13468 | ||
|
|
f7b3946ec2 | ||
|
|
9f29f2c0ae | ||
|
|
c13284b776 | ||
|
|
6e85c9650d | ||
|
|
7f3b5f659f | ||
|
|
8e62b2e743 | ||
|
|
94dfd5fded | ||
|
|
70d8e5ad15 | ||
|
|
a80aed5ccc | ||
|
|
2b35dc8ecd | ||
|
|
75fadab371 | ||
|
|
e70f4a000a | ||
|
|
755c792797 | ||
|
|
b17894eec1 | ||
|
|
9e22ec883c | ||
|
|
f70fb89754 | ||
|
|
e30f99e106 | ||
|
|
fce76e59aa | ||
|
|
1b1c8ddb38 | ||
|
|
5ced6811c8 | ||
|
|
371612b000 | ||
|
|
3c87be3cba | ||
|
|
c642fb3845 | ||
|
|
847e689bfb | ||
|
|
287527092a | ||
|
|
a9514f39f5 | ||
|
|
4b7ff505e4 | ||
|
|
2120264e0b | ||
|
|
178bced5f3 | ||
|
|
ff78968807 | ||
|
|
e4535d2646 | ||
|
|
7c60ad3a7a | ||
|
|
a621edf898 | ||
|
|
2809f8d7e4 | ||
|
|
97819327cd | ||
|
|
eb9a1e9f6b | ||
|
|
6f6850707a | ||
|
|
f702865311 | ||
|
|
6447081a01 | ||
|
|
e4e513ec66 | ||
|
|
47630450bd | ||
|
|
e4129fec63 | ||
|
|
f71ba91e7c | ||
|
|
59e6603b83 | ||
|
|
14a061859f | ||
|
|
9aaa419f68 | ||
|
|
d5231bc4fc | ||
|
|
35cebfba73 | ||
|
|
811d16054b | ||
|
|
a9ee072a14 | ||
|
|
1dbf5ecfe6 | ||
|
|
b210db168f | ||
|
|
5306a043d0 | ||
|
|
b375a94036 | ||
|
|
8b2bff4187 | ||
|
|
827ab7cdcc | ||
|
|
bfa1d8c5dd | ||
|
|
52ea6270f4 | ||
|
|
0fb21856c6 | ||
|
|
48e4d3a6e7 | ||
|
|
6204c74993 | ||
|
|
d981391120 | ||
|
|
7db676e02c | ||
|
|
c91cae0903 | ||
|
|
c06712a0d5 | ||
|
|
2e2f118e10 |
127
.github/workflows/build.yml
vendored
127
.github/workflows/build.yml
vendored
@@ -25,33 +25,21 @@ jobs:
|
||||
- arch: arm64
|
||||
tool: aarch64-unknown-linux-musl
|
||||
- arch: arm
|
||||
tool: arm-unknown-linux-musleabi
|
||||
# - arch: armhf
|
||||
# tool: arm-unknown-linux-musleabihf
|
||||
# - arch: armv7
|
||||
# tool: armv7-unknown-linux-musleabi
|
||||
# - arch: armv7hf
|
||||
# tool: armv7-unknown-linux-musleabihf
|
||||
# - arch: mips64el
|
||||
# tool: mips64el-unknown-linux-musl
|
||||
tool: armv6-unknown-linux-musleabi
|
||||
- arch: mips64
|
||||
tool: mips64-unknown-linux-musl
|
||||
# - arch: mipsel
|
||||
# tool: mipsel-unknown-linux-musl
|
||||
- arch: mipselsf
|
||||
tool: mipsel-unknown-linux-muslsf
|
||||
# - arch: mips
|
||||
# tool: mips-unknown-linux-musl
|
||||
- arch: mipssf
|
||||
tool: mips-unknown-linux-muslsf
|
||||
# - arch: ppc64
|
||||
# tool: powerpc64-unknown-linux-musl
|
||||
- arch: ppc
|
||||
tool: powerpc-unknown-linux-musl
|
||||
- arch: x86
|
||||
tool: i586-unknown-linux-musl
|
||||
- arch: x86_64
|
||||
tool: x86_64-unknown-linux-musl
|
||||
- arch: riscv64
|
||||
tool: riscv64-unknown-linux-musl
|
||||
- arch: lexra
|
||||
tool: mips-linux
|
||||
dir: rsdk-4.6.4-5281-EB-3.10-0.9.33-m32ub-20141001
|
||||
@@ -69,7 +57,7 @@ jobs:
|
||||
env:
|
||||
ARCH: ${{ matrix.arch }}
|
||||
TOOL: ${{ matrix.tool }}
|
||||
REPO: ${{ matrix.arch == 'lexra' && matrix.repo || 'spvkgn/musl-cross' }}
|
||||
REPO: ${{ matrix.arch == 'lexra' && matrix.repo || 'bol-van/musl-cross' }}
|
||||
DIR: ${{ matrix.arch == 'lexra' && matrix.dir || matrix.tool }}
|
||||
run: |
|
||||
sudo dpkg --add-architecture i386
|
||||
@@ -98,6 +86,10 @@ jobs:
|
||||
LUAJIT_VER: 2.1
|
||||
LUAJIT_RELEASE: 2.1-20250826
|
||||
LUAJIT_LUAVER: 5.1
|
||||
MINSIZE: -flto=auto -ffunction-sections -fdata-sections
|
||||
LDMINSIZE: -Wl,--gc-sections -flto=auto
|
||||
#current toolchain's musl is not PIC. will be broken by upx
|
||||
#PIC: -fpic
|
||||
run: |
|
||||
DEPS_DIR=$GITHUB_WORKSPACE/deps
|
||||
export CC="$TARGET-gcc"
|
||||
@@ -107,13 +99,28 @@ jobs:
|
||||
export STRIP=$TARGET-strip
|
||||
export PKG_CONFIG_PATH=$DEPS_DIR/lib/pkgconfig
|
||||
export STAGING_DIR=$RUNNER_TEMP
|
||||
OPTIMIZE=-Oz
|
||||
SYSMALLOC=-DLUAJIT_USE_SYSMALLOC
|
||||
case "$ARCH" in
|
||||
lexra)
|
||||
OPTIMIZE=-Os
|
||||
;;
|
||||
arm)
|
||||
CPU="-mcpu=arm1176jzf-s -mthumb"
|
||||
;;
|
||||
arm64|mips64)
|
||||
# not safe without GC64
|
||||
SYSMALLOC=
|
||||
;;
|
||||
esac
|
||||
MINSIZE="$OPTIMIZE $MINSIZE"
|
||||
|
||||
if [[ "$ARCH" == lexra ]] || [[ "$ARCH" == ppc ]] || [[ "$ARCH" == x86 ]] ; then
|
||||
if [[ "$ARCH" == lexra ]] || [[ "$ARCH" == riscv64 ]] || [[ "$ARCH" == x86 ]] ; then
|
||||
# use classic lua
|
||||
wget -qO- https://www.lua.org/ftp/lua-${LUA_RELEASE}.tar.gz | tar -xz
|
||||
(
|
||||
cd lua-${LUA_RELEASE}
|
||||
make CC=$CC CFLAGS="-Os -flto=auto $CFLAGS" linux -j$(nproc)
|
||||
make CC=$CC AR="$AR rc" CFLAGS="$CPU $MINSIZE $CFLAGS" LDFLAGS="$LDMINSIZE $LDFLAGS" linux -j$(nproc)
|
||||
make install INSTALL_TOP=$DEPS_DIR INSTALL_BIN=$DEPS_DIR/bin INSTALL_INC=$DEPS_DIR/include/lua${LUA_VER} INSTALL_LIB=$DEPS_DIR/lib
|
||||
)
|
||||
LJIT=0
|
||||
@@ -129,9 +136,10 @@ jobs:
|
||||
*)
|
||||
HOSTCC="cc -m32"
|
||||
esac
|
||||
echo ARCH=$ARCH SYSMALLOC=$SYSMALLOC
|
||||
(
|
||||
cd luajit2-*
|
||||
make BUILDMODE=static XCFLAGS=-DLUAJIT_DISABLE_FFI HOST_CC="$HOSTCC" CROSS= CC="$CC" TARGET_AR="$AR rcus" TARGET_STRIP=$STRIP CFLAGS="-Os -s -flto=auto $CFLAGS" -j$(nproc)
|
||||
make BUILDMODE=static XCFLAGS="$SYSMALLOC -DLUAJIT_DISABLE_FFI" HOST_CC="$HOSTCC" CROSS= CC="$CC" TARGET_AR="$AR rcus" TARGET_STRIP=$STRIP TARGET_CFLAGS="$CPU $MINSIZE $CFLAGS" TARGET_LDFLAGS="$CPU $LDMINSIZE $LDFLAGS" -j$(nproc)
|
||||
make install PREFIX= DESTDIR=$DEPS_DIR
|
||||
)
|
||||
LJIT=1
|
||||
@@ -147,7 +155,8 @@ jobs:
|
||||
for i in libmnl libnfnetlink libnetfilter_queue ; do
|
||||
(
|
||||
cd $i-*
|
||||
CFLAGS="-Os -flto=auto $CFLAGS" \
|
||||
CFLAGS="$CPU $MINSIZE $CFLAGS" \
|
||||
LDFLAGS="$LDMINSIZE $LDFLAGS" \
|
||||
./configure --prefix= --host=$TARGET --enable-static --disable-shared --disable-dependency-tracking
|
||||
make install -j$(nproc) DESTDIR=$DEPS_DIR
|
||||
)
|
||||
@@ -159,7 +168,7 @@ jobs:
|
||||
xargs -I{} wget -qO- https://github.com/madler/zlib/archive/refs/tags/{}.tar.gz | tar -xz
|
||||
(
|
||||
cd zlib-*
|
||||
CFLAGS="-Os -flto=auto $CFLAGS" \
|
||||
CFLAGS="$CPU $MINSIZE $CFLAGS" \
|
||||
./configure --prefix= --static
|
||||
make install -j$(nproc) DESTDIR=$DEPS_DIR
|
||||
)
|
||||
@@ -170,9 +179,10 @@ jobs:
|
||||
install -Dm644 -t $DEPS_DIR/include/sys /usr/include/x86_64-linux-gnu/sys/queue.h /usr/include/sys/capability.h
|
||||
|
||||
# zapret2
|
||||
CFLAGS="-DZAPRET_GH_VER=${{ github.ref_name }} -DZAPRET_GH_HASH=${{ github.sha }} -static-libgcc -static -I$DEPS_DIR/include $CFLAGS" \
|
||||
OPTIMIZE=$OPTIMIZE \
|
||||
CFLAGS="-DZAPRET_GH_VER=${{ github.ref_name }} -DZAPRET_GH_HASH=${{ github.sha }} -static-libgcc -I$DEPS_DIR/include $CPU $CFLAGS" \
|
||||
LDFLAGS="-L$DEPS_DIR/lib $LDFLAGS" \
|
||||
make -C zapret2 LUA_JIT=$LJIT LUA_CFLAGS="$LCFLAGS" LUA_LIB="$LLIB" -j$(nproc)
|
||||
make -C zapret2 CFLAGS_PIC= LDFLAGS_PIE=-static LUA_JIT=$LJIT LUA_CFLAGS="$LCFLAGS" LUA_LIB="$LLIB" -j$(nproc)
|
||||
|
||||
tar -C zapret2/binaries/my -cJf zapret2-linux-$ARCH.tar.xz .
|
||||
|
||||
@@ -220,6 +230,8 @@ jobs:
|
||||
LUAJIT_VER: 2.1
|
||||
LUAJIT_RELEASE: 2.1-20250826
|
||||
LUAJIT_LUAVER: 5.1
|
||||
MINSIZE: -Oz -flto=auto -ffunction-sections -fdata-sections
|
||||
LDMINSIZE: -Wl,--gc-sections -flto=auto
|
||||
run: |
|
||||
DEPS_DIR=$GITHUB_WORKSPACE/deps
|
||||
export TOOLCHAIN=$ANDROID_NDK_HOME/toolchains/llvm/prebuilt/linux-x86_64
|
||||
@@ -230,6 +242,17 @@ jobs:
|
||||
export RANLIB=$TOOLCHAIN/bin/llvm-ranlib
|
||||
export STRIP=$TOOLCHAIN/bin/llvm-strip
|
||||
export PKG_CONFIG_PATH=$DEPS_DIR/lib/pkgconfig
|
||||
SYSMALLOC=-DLUAJIT_USE_SYSMALLOC
|
||||
case "$ABI" in
|
||||
armeabi-v7a)
|
||||
CPU="-mthumb"
|
||||
;;
|
||||
arm64-v8a)
|
||||
# not safe without GC64
|
||||
SYSMALLOC=
|
||||
PAGESIZE="-Wl,-z,max-page-size=16384"
|
||||
;;
|
||||
esac
|
||||
|
||||
# luajit
|
||||
wget -qO- https://github.com/openresty/luajit2/archive/refs/tags/v${LUAJIT_RELEASE}.tar.gz | tar -xz
|
||||
@@ -242,7 +265,7 @@ jobs:
|
||||
esac
|
||||
(
|
||||
cd luajit2-*
|
||||
make BUILDMODE=static XCFLAGS=-DLUAJIT_DISABLE_FFI HOST_CC="$HOSTCC" CROSS= CC="$CC" TARGET_AR="$AR rcus" TARGET_STRIP=$STRIP CFLAGS="-Os -flto=auto $CFLAGS" -j$(nproc)
|
||||
make BUILDMODE=static XCFLAGS="$SYSMALLOC -DLUAJIT_DISABLE_FFI" HOST_CC="$HOSTCC" CROSS= CC="$CC" TARGET_AR="$AR rcus" TARGET_STRIP=$STRIP TARGET_CFLAGS="$CPU $MINSIZE $CFLAGS" TARGET_LDFLAGS="$LDMINSIZE $LDFLAGS" -j$(nproc)
|
||||
make install PREFIX= DESTDIR=$DEPS_DIR
|
||||
)
|
||||
LJIT=1
|
||||
@@ -258,7 +281,8 @@ jobs:
|
||||
for i in libmnl libnfnetlink libnetfilter_queue ; do
|
||||
(
|
||||
cd $i-*
|
||||
CFLAGS="-Os -flto=auto -Wno-implicit-function-declaration" \
|
||||
CFLAGS="$CPU $MINSIZE -Wno-implicit-function-declaration $CFLAGS" \
|
||||
LDFLAGS="$LDMINSIZE $LDFLAGS" \
|
||||
./configure --prefix= --host=$TARGET --enable-static --disable-shared --disable-dependency-tracking
|
||||
make install -j$(nproc) DESTDIR=$DEPS_DIR
|
||||
)
|
||||
@@ -266,8 +290,8 @@ jobs:
|
||||
done
|
||||
|
||||
# zapret2
|
||||
CFLAGS="-DZAPRET_GH_VER=${{ github.ref_name }} -DZAPRET_GH_HASH=${{ github.sha }} -I$DEPS_DIR/include" \
|
||||
LDFLAGS="-L$DEPS_DIR/lib" \
|
||||
CFLAGS="-DZAPRET_GH_VER=${{ github.ref_name }} -DZAPRET_GH_HASH=${{ github.sha }} -I$DEPS_DIR/include $CPU" \
|
||||
LDFLAGS="-L$DEPS_DIR/lib $PAGESIZE" \
|
||||
make -C zapret2 LUA_JIT=$LJIT LUA_CFLAGS="$LCFLAGS" LUA_LIB="$LLIB" -j$(nproc) android
|
||||
|
||||
# strip unwanted ELF sections to prevent warnings on old Android versions
|
||||
@@ -313,13 +337,16 @@ jobs:
|
||||
env:
|
||||
TARGET: ${{ matrix.target }}
|
||||
ARCH: ${{ matrix.arch }}
|
||||
PIC: -fpic
|
||||
CC: ${{ matrix.target }}-freebsd11-clang
|
||||
MINSIZE: -Os -flto=auto -ffunction-sections -fdata-sections
|
||||
LDMINSIZE: -Wl,--gc-sections -flto=auto
|
||||
run: |
|
||||
|
||||
wget -qO- https://github.com/openresty/luajit2/archive/refs/tags/v${LUAJIT_RELEASE}.tar.gz | tar -xz
|
||||
(
|
||||
cd luajit2-*
|
||||
make BUILDMODE=static XCFLAGS=-DLUAJIT_DISABLE_FFI HOST_CC=gcc CC=$CC CFLAGS="-Os -flto=auto $CFLAGS"
|
||||
make BUILDMODE=static XCFLAGS="$PIC -DLUAJIT_USE_SYSMALLOC -DLUAJIT_DISABLE_FFI" HOST_CC=gcc CC=$CC TARGET_CFLAGS="$MINSIZE $CFLAGS $PIC" TARGET_LDFLAGS="$LDMINSIZE $LDFLAGS"
|
||||
make install PREFIX= DESTDIR=$DEPS_DIR
|
||||
)
|
||||
|
||||
@@ -390,7 +417,7 @@ jobs:
|
||||
uses: cygwin/cygwin-install-action@v4
|
||||
with:
|
||||
platform: ${{ matrix.arch }}
|
||||
site: ${{ matrix.arch == 'x86_64' && 'http://ctm.crouchingtigerhiddenfruitbat.org/pub/cygwin/circa/64bit/2024/01/30/231215' || null }}
|
||||
site: ${{ matrix.arch == 'x86_64' && 'http://ctm.crouchingtigerhiddenfruitbat.org/pub/cygwin/circa/64bit/2024/01/30/231215' || 'http://ctm.crouchingtigerhiddenfruitbat.org/pub/cygwin/circa/2022/11/23/063457' }}
|
||||
check-sig: 'false'
|
||||
packages: >-
|
||||
gcc-core
|
||||
@@ -424,13 +451,15 @@ jobs:
|
||||
- name: Build luajit
|
||||
env:
|
||||
LUAJIT_RELEASE: 2.1-20250826
|
||||
MINSIZE: -Os -flto=auto -ffunction-sections -fdata-sections
|
||||
LDMINSIZE: -Wl,--gc-sections -flto=auto
|
||||
shell: C:\cygwin\bin\bash.exe -eo pipefail '{0}'
|
||||
run: >-
|
||||
export MAKEFLAGS=-j$(nproc) &&
|
||||
wget -q https://github.com/openresty/luajit2/archive/refs/tags/v${LUAJIT_RELEASE}.tar.gz &&
|
||||
tar -xzf v${LUAJIT_RELEASE}.tar.gz &&
|
||||
rm -f v${LUAJIT_RELEASE}.tar.gz &&
|
||||
make -C luajit2-${LUAJIT_RELEASE} BUILDMODE=static XCFLAGS=-DLUAJIT_DISABLE_FFI CFLAGS="-Os -s" &&
|
||||
make -C luajit2-${LUAJIT_RELEASE} BUILDMODE=static XCFLAGS="-DLUAJIT_USE_SYSMALLOC -DLUAJIT_DISABLE_FFI -ffat-lto-objects" TARGET_CFLAGS="$MINSIZE $CFLAGS" TARGET_LDFLAGS="$LDMINSIZE $LDFLAGS" &&
|
||||
make -C luajit2-${LUAJIT_RELEASE} install
|
||||
|
||||
- name: Build winws
|
||||
@@ -453,6 +482,8 @@ jobs:
|
||||
cp -a -t output psmisc/psmisc-*.src/psmisc-*/inst/usr/bin/killall.exe /usr/bin/cygwin1.dll &&
|
||||
wget -O WinDivert.zip https://github.com/basil00/WinDivert/releases/download/v2.2.2/WinDivert-2.2.2-A.zip &&
|
||||
unzip -j WinDivert.zip "*/${DIR}/WinDivert.dll" "*/${DIR}/WinDivert${BITS}.sys" -d output &&
|
||||
( [ "$BITS" = 64 ] && rebase -b 0x205c00000 output/WinDivert.dll || true ) &&
|
||||
peflags --dynamicbase=true --high-entropy-va=true output/WinDivert.dll &&
|
||||
zip zapret2-win-${{ matrix.arch }}.zip -j output/*
|
||||
|
||||
- name: Upload artifacts
|
||||
@@ -485,17 +516,28 @@ jobs:
|
||||
pattern: zapret2-*
|
||||
|
||||
- name: Install upx
|
||||
uses: crazy-max/ghaction-upx@v3
|
||||
with:
|
||||
install-only: true
|
||||
version: v4.2.4
|
||||
shell: bash
|
||||
env:
|
||||
VER_OLD: 4.2.4
|
||||
VER_NEW: 5.1.0
|
||||
run: |
|
||||
# old upx works for old kernels like 2.6.26
|
||||
# new upx crashes on ~<3.10 but required for riscv64
|
||||
curl -Lo - https://github.com/upx/upx/releases/download/v$VER_OLD/upx-$VER_OLD-amd64_linux.tar.xz | tar -Jx upx-$VER_OLD-amd64_linux/upx
|
||||
sudo cp upx-$VER_OLD-amd64_linux/upx /usr/local/bin/upx_old
|
||||
curl -Lo - https://github.com/upx/upx/releases/download/v$VER_NEW/upx-$VER_NEW-amd64_linux.tar.xz | tar -Jx upx-$VER_NEW-amd64_linux/upx
|
||||
sudo cp upx-$VER_NEW-amd64_linux/upx /usr/local/bin/upx_new
|
||||
rm -r upx-$VER_OLD-amd64_linux/upx upx-$VER_NEW-amd64_linux/upx
|
||||
|
||||
- name: Prepare binaries
|
||||
shell: bash
|
||||
run: |
|
||||
cd ${{ steps.bins.outputs.download-path }}
|
||||
run_upx() {
|
||||
upx --best --lzma $@ || true
|
||||
run_upx_old() {
|
||||
upx_old --best --lzma $@ || true
|
||||
}
|
||||
run_upx_new() {
|
||||
upx_new --best --lzma $@ || true
|
||||
}
|
||||
run_dir() {
|
||||
for f in $dir/* ; do
|
||||
@@ -503,8 +545,10 @@ jobs:
|
||||
case $f in
|
||||
*.tar.xz )
|
||||
tar -C $dir -xvf $f && rm $f
|
||||
if [[ $dir =~ linux ]] && [[ $dir != *-linux-mips64 ]] && [[ $dir != *-linux-lexra ]]; then
|
||||
run_upx $dir/*
|
||||
if [[ $dir = *-linux-riscv64 ]]; then
|
||||
run_upx_new $dir/*
|
||||
elif [[ $dir =~ linux ]] && [[ $dir != *-linux-mips64 ]] && [[ $dir != *-linux-lexra ]]; then
|
||||
run_upx_old $dir/*
|
||||
fi
|
||||
;;
|
||||
*.zip )
|
||||
@@ -532,6 +576,7 @@ jobs:
|
||||
*-linux-mipselsf ) run_dir linux-mipsel ;;
|
||||
*-linux-mipssf ) run_dir linux-mips ;;
|
||||
*-linux-ppc ) run_dir linux-ppc ;;
|
||||
*-linux-riscv64 ) run_dir linux-riscv64 ;;
|
||||
*-linux-x86 ) run_dir linux-x86 ;;
|
||||
*-linux-x86_64 ) run_dir linux-x86_64 ;;
|
||||
*-linux-lexra ) run_dir linux-lexra ;;
|
||||
@@ -546,8 +591,8 @@ jobs:
|
||||
run: |
|
||||
rm -rf ${{ env.repo_dir }}/.git*
|
||||
find ${{ env.repo_dir }}/binaries -type f -exec sha256sum {} \; >sha256sum.txt
|
||||
tar --owner=0 --group=0 -czf ${{ env.repo_dir }}.tar.gz ${{ env.repo_dir }}
|
||||
zip -qr ${{ env.repo_dir }}.zip ${{ env.repo_dir }}
|
||||
tar --owner=0 --group=0 -c ${{ env.repo_dir }} | pigz -11 >${{ env.repo_dir }}.tar.gz
|
||||
zip -9qr ${{ env.repo_dir }}.zip ${{ env.repo_dir }}
|
||||
(
|
||||
cd ${{ env.repo_dir }}
|
||||
rm -rf binaries/{android*,freebsd*,win*} \
|
||||
@@ -555,7 +600,7 @@ jobs:
|
||||
nfq2 ip2net mdig docs Makefile
|
||||
pigz -11 lua/*.lua
|
||||
)
|
||||
tar --owner=0 --group=0 -czf ${{ env.repo_dir }}-openwrt-embedded.tar.gz ${{ env.repo_dir }}
|
||||
tar --owner=0 --group=0 -c ${{ env.repo_dir }} | pigz -11 >${{ env.repo_dir }}-openwrt-embedded.tar.gz
|
||||
|
||||
- name: Upload release assets
|
||||
uses: softprops/action-gh-release@v2
|
||||
|
||||
@@ -426,14 +426,6 @@ alloc_num()
|
||||
eval $1="$v"
|
||||
}
|
||||
|
||||
std_ports()
|
||||
{
|
||||
NFQWS2_PORTS_TCP_IPT=$(replace_char - : $NFQWS2_PORTS_TCP)
|
||||
NFQWS2_PORTS_TCP_KEEPALIVE_IPT=$(replace_char - : $NFQWS2_PORTS_TCP_KEEPALIVE)
|
||||
NFQWS2_PORTS_UDP_IPT=$(replace_char - : $NFQWS2_PORTS_UDP)
|
||||
NFQWS2_PORTS_UDP_KEEPALIVE_IPT=$(replace_char - : $NFQWS2_PORTS_UDP_KEEPALIVE)
|
||||
}
|
||||
|
||||
has_bad_ws_options()
|
||||
{
|
||||
# $1 - nfqws2 opts
|
||||
@@ -446,6 +438,13 @@ has_bad_ws_options()
|
||||
echo "Kernel ipsets should be used instead. Write custom scripts and filter IPs in kernel."
|
||||
echo
|
||||
}
|
||||
contains "$1" "--ipset=$ZAPRET_BASE" || contains "$1" "--ipset-exclude=$ZAPRET_BASE" ||
|
||||
contains "$1" "--hostlist=$ZAPRET_BASE" || contains "$1" "--hostlist-exclude=$ZAPRET_BASE" && {
|
||||
echo
|
||||
echo "WARNING !!! you store ipset or hostlist files inside '$ZAPRET_BASE'"
|
||||
echo "It's not recommended. install_easy.sh will delete them during update."
|
||||
echo
|
||||
}
|
||||
|
||||
return 1
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
std_ports
|
||||
ipt_connbytes="-m connbytes --connbytes-dir=original --connbytes-mode=packets --connbytes"
|
||||
IPSET_EXCLUDE="-m set ! --match-set nozapret"
|
||||
IPSET_EXCLUDE6="-m set ! --match-set nozapret6"
|
||||
IPSET_PORTS_NAME=zport
|
||||
|
||||
ipt()
|
||||
{
|
||||
@@ -227,6 +227,16 @@ fw_reverse_nfqws_rule()
|
||||
fw_reverse_nfqws_rule6 $1 "$3" $4
|
||||
}
|
||||
|
||||
ipt_port_ipset()
|
||||
{
|
||||
# $1 - ipset name
|
||||
# $2 - ports
|
||||
ipset -q flush $1 || {
|
||||
ipset create $1 bitmap:port range 0-65535 || return
|
||||
}
|
||||
echo "$2" | tr ',' '\n' | sed -nEe "s/^.+$/add $1 &/p" | ipset -! restore
|
||||
}
|
||||
|
||||
ipt_first_packets()
|
||||
{
|
||||
# $1 - packet count
|
||||
@@ -237,26 +247,31 @@ ipt_do_nfqws_in_out()
|
||||
# $1 - 1 - add, 0 - del
|
||||
# $2 - tcp,udp
|
||||
# $3 - ports
|
||||
# $4 - PKT_OUT. special value : 'keepalive'
|
||||
# $5 - PKT_IN
|
||||
local f4 f6 first_packets_only
|
||||
# $4 - PKT. special value : 'keepalive'
|
||||
# $5 - 1 - out, 0 - in
|
||||
# $6 - ipset base name
|
||||
local f f4 f6 first_packets_only ipset
|
||||
[ -n "$3" ] || return
|
||||
ipset="${6}_$2"
|
||||
[ "$4" = keepalive ] && ipset="${ipset}_k"
|
||||
[ "$1" = 1 ] && ipt_port_ipset $ipset "$3"
|
||||
[ -n "$4" -a "$4" != 0 ] &&
|
||||
{
|
||||
first_packets_only="$(ipt_first_packets $4)"
|
||||
f4="-p $2 -m multiport --dports $3 $first_packets_only"
|
||||
f4="-p $2 -m set --match-set $ipset"
|
||||
if [ "$5" = 1 ]; then
|
||||
f4="$f4 dst"
|
||||
f=fw_nfqws_post
|
||||
else
|
||||
f4="$f4 src"
|
||||
f=fw_reverse_nfqws_rule
|
||||
fi
|
||||
f4="$f4 $first_packets_only"
|
||||
f6=$f4
|
||||
filter_apply_ipset_target f4 f6
|
||||
fw_nfqws_post $1 "$f4" "$f6" $QNUM
|
||||
}
|
||||
[ -n "$5" -a "$5" != 0 ] &&
|
||||
{
|
||||
first_packets_only="$(ipt_first_packets $5)"
|
||||
f4="-p $2 -m multiport --dports $3 $first_packets_only"
|
||||
f6=$f4
|
||||
filter_apply_ipset_target f4 f6
|
||||
fw_reverse_nfqws_rule $1 "$f4" "$f6" $QNUM
|
||||
$f $1 "$f4" "$f6" $QNUM
|
||||
}
|
||||
[ "$1" = 1 ] || ipset -q destroy $ipset
|
||||
}
|
||||
|
||||
zapret_do_firewall_standard_nfqws_rules_ipt()
|
||||
@@ -264,10 +279,12 @@ zapret_do_firewall_standard_nfqws_rules_ipt()
|
||||
# $1 - 1 - add, 0 - del
|
||||
|
||||
[ "$NFQWS2_ENABLE" = 1 ] && {
|
||||
ipt_do_nfqws_in_out $1 tcp "$NFQWS2_PORTS_TCP_IPT" "$NFQWS2_TCP_PKT_OUT" "$NFQWS2_TCP_PKT_IN"
|
||||
ipt_do_nfqws_in_out $1 tcp "$NFQWS2_PORTS_TCP_KEEPALIVE_IPT" keepalive "$NFQWS2_TCP_PKT_IN"
|
||||
ipt_do_nfqws_in_out $1 udp "$NFQWS2_PORTS_UDP_IPT" "$NFQWS2_UDP_PKT_OUT" "$NFQWS2_UDP_PKT_IN"
|
||||
ipt_do_nfqws_in_out $1 udp "$NFQWS2_PORTS_UDP_KEEPALIVE_IPT" keepalive "$NFQWS2_UDP_PKT_IN"
|
||||
ipt_do_nfqws_in_out $1 tcp "$NFQWS2_PORTS_TCP" "$NFQWS2_TCP_PKT_OUT" 1 $IPSET_PORTS_NAME
|
||||
ipt_do_nfqws_in_out $1 tcp "$NFQWS2_PORTS_TCP" "$NFQWS2_TCP_PKT_IN" 0 $IPSET_PORTS_NAME
|
||||
ipt_do_nfqws_in_out $1 tcp "$NFQWS2_PORTS_TCP_KEEPALIVE" keepalive 1 $IPSET_PORTS_NAME
|
||||
ipt_do_nfqws_in_out $1 udp "$NFQWS2_PORTS_UDP" "$NFQWS2_UDP_PKT_OUT" 1 $IPSET_PORTS_NAME
|
||||
ipt_do_nfqws_in_out $1 udp "$NFQWS2_PORTS_UDP" "$NFQWS2_UDP_PKT_IN" 0 $IPSET_PORTS_NAME
|
||||
ipt_do_nfqws_in_out $1 udp "$NFQWS2_PORTS_UDP_KEEPALIVE" keepalive 1 $IPSET_PORTS_NAME
|
||||
}
|
||||
}
|
||||
zapret_do_firewall_standard_rules_ipt()
|
||||
|
||||
@@ -3,7 +3,6 @@ nft_connbytes="ct original packets"
|
||||
|
||||
# required for : nft -f -
|
||||
create_dev_stdin
|
||||
std_ports
|
||||
|
||||
nft_create_table()
|
||||
{
|
||||
|
||||
@@ -152,7 +152,7 @@ v0.8.1
|
||||
* zapret-antidpi: http_unixeol
|
||||
* blockcheck2: http_unixeol test
|
||||
|
||||
0.8.2
|
||||
v0.8.2
|
||||
|
||||
* nfqws2: do not start if NFQWS2_COMPAT_VER unexpected
|
||||
* nfqws2: cache dns response IP addresses if --ipcache-hostname enabled
|
||||
@@ -163,14 +163,14 @@ v0.8.1
|
||||
* winws2: --wf-filter-loopback
|
||||
* blockcheck2: NOTEST_MISC_HTTP[S], NOTEST_SYNDATA_HTTP[S]
|
||||
|
||||
0.8.3
|
||||
v0.8.3
|
||||
|
||||
* nfqws2, zapret-lib: gzip compression and decompression
|
||||
* nfqws2: ignore trailing spaces and tabs in hostlists and ipsets. "host.com " or "1.2.3.4 " are ok now
|
||||
* init.d: 99-lan-filter custom script
|
||||
* mdig: --eagain, --eagain-delay
|
||||
|
||||
0.8.4
|
||||
v0.8.4
|
||||
|
||||
* winws2: fix loopback large packets processing (up to 64K)
|
||||
* zapret-lib, zapret-antidpi: use numeric indexes in http dissects
|
||||
@@ -180,7 +180,7 @@ v0.8.1
|
||||
* nfqws2: gracefully shutdown on SIGINT and SIGTERM
|
||||
* nfqws2: harden wireguard detection. do not detect if reserved bytes 1..3 != 0
|
||||
|
||||
0.8.5
|
||||
v0.8.5
|
||||
|
||||
* nfqws2: do not require / in the beginning of URI in http
|
||||
* zapret-lib: rawsend_dissect_segmented support URG
|
||||
@@ -190,13 +190,13 @@ v0.8.1
|
||||
* zapret-lib: tcp_nop_del
|
||||
* blockcheck2: tcp_nop_del in SYN packets with md5 in openbsd
|
||||
|
||||
0.8.6
|
||||
v0.8.6
|
||||
|
||||
* winws2, blockcheck2: allow multiple instances in windows, linux, freebsd (not openbsd)
|
||||
* nfqws2: fix critical bug - wrong ipv6 dissection
|
||||
* zapret-auto: fix standard_failure_detector http redirect regression
|
||||
|
||||
0.9.0
|
||||
v0.9.0
|
||||
|
||||
* nfqws2: removed hard check for host: presence in http_req
|
||||
* nfqws2: file open test before destroying in-memory content of ipset/hostlist
|
||||
@@ -215,24 +215,61 @@ v0.8.1
|
||||
* winws2: use windivert bulk mode
|
||||
* nfqws2: template free import
|
||||
|
||||
0.9.1
|
||||
v0.9.1
|
||||
|
||||
* nfqws2: 'stat', 'clock_getfloattime' luacalls
|
||||
* nfqws2: bcryptorandom normalize behavior when system entropy is low. prevent blocks
|
||||
* nfqws2: --new[=name]
|
||||
* winws2: fix not setting signal handlers
|
||||
|
||||
0.9.2
|
||||
v0.9.2
|
||||
|
||||
nfqws2: bt and utp_bt protocol detectors
|
||||
nfqws2: localtime,gmtime,timelocal,timegm luacalls
|
||||
winws2: load wlanapi.dll dynamically only if needed
|
||||
winws2: fixed lost windivert deinit on logical network disappear
|
||||
* nfqws2: bt and utp_bt protocol detectors
|
||||
* nfqws2: localtime,gmtime,timelocal,timegm luacalls
|
||||
* winws2: load wlanapi.dll dynamically only if needed
|
||||
* winws2: fixed lost windivert deinit on logical network disappear
|
||||
|
||||
0.9.3
|
||||
v0.9.3
|
||||
|
||||
* nfqws2: handling of incoming fragmented packets (no reconstruct, raw ip payload)
|
||||
* zapret-auto: per_instance_condition orchestrator
|
||||
* zapret-auto: "instances" argument in condition orchestrator
|
||||
* zapret-auto: cond_tcp_has_ts, cond_lua iff functions
|
||||
* zapret-lib: replay_execution_plan and plan_clear max parameter
|
||||
* init.d: use bitmap:port ipset for standard dports
|
||||
* github: reduce executables files size
|
||||
* install_bin: added linux-riscv64 scan dir
|
||||
* github actions: added linux-riscv64 arch
|
||||
|
||||
v0.9.4
|
||||
|
||||
* github actions: update upx to 5.1.0. use upx for linux-riscv5
|
||||
* github actions: stronger zip and gz compression
|
||||
* nfqws2: --chdir
|
||||
* nfqws2: fixed wrong scale factor application to winsize
|
||||
* nfqws2: very old kernels compat
|
||||
|
||||
v0.9.4.2
|
||||
|
||||
* builder_linux: simple scripts to build static linux bins for any supported architecture
|
||||
* zapret-auto: incompatible change. cond_lua "code" parameter => "cond_code". to avoid collision with luaexec
|
||||
|
||||
v0.9.4.3
|
||||
|
||||
* nfqws2: fix broken wifi ssid update
|
||||
* github: revert to upx 4.2.4 for all archs except riscv64
|
||||
* zapret-lib: apply_fooling throws error if tcp_ts,tcp_seq,tcp_ack,ip_ttl,ip6_ttl,ip_autottl,ip6_autottl are empty or invalid
|
||||
|
||||
0.9.4.4
|
||||
|
||||
* winws2, dvtws2: ASLR
|
||||
* github, linux-builder: reduce arm executable size by 20% - move to armv7+thumb
|
||||
* init.d: warn if hostlist/ipset files are inside zapret2 root
|
||||
* zapret-lib: do not call apply_arg_prefix in apply_execution_plan - call it right before instance execute
|
||||
|
||||
0.9.4.5
|
||||
|
||||
* github: rollback to lj_alloc in luajit for arm64 and mips64
|
||||
* github: use 16K page size for android arm64 build
|
||||
* nfqws2: join fragments in quic CRYPTO reconstruction. allow intersections.
|
||||
|
||||
nfqws2: handling of incoming fragmented packets (no reconstruct, raw ip payload)
|
||||
zapret-auto: per_instance_condition orchestrator
|
||||
zapret-auto: "instances" argument in condition orchestrator
|
||||
zapret-auto: cond_tcp_has_ts, cond_lua iff functions
|
||||
zapret-lib: replay_execution_plan and plan_clear max parameter
|
||||
|
||||
@@ -1,9 +1,31 @@
|
||||
debian,ubuntu :
|
||||
* debian,ubuntu :
|
||||
|
||||
apt install make gcc zlib1g-dev libcap-dev libnetfilter-queue-dev libmnl-dev libsystemd-dev libluajit2-5.1-dev
|
||||
make -C /opt/zapret2 systemd
|
||||
|
||||
FreeBSD :
|
||||
* linux static :
|
||||
|
||||
need any x86_64 classic linux distribution
|
||||
tested on debian/ubuntu/fedora 2020+
|
||||
if your distro is very exotic, old or not glibc based you can debootstrap a modern debian/ubuntu system and chroot to it
|
||||
NOTE: it's not possible to build luajit in chroot under standard openwrt kernel. build process requires 32-bit x86 support, kernel is compiled without it.
|
||||
NOTE: toolchains are pre-compiled for x86_64 glibc. they can't run on arm or anything that is not x86_64.
|
||||
|
||||
optionally review "common.inc" for Lua and LuaJIT versions
|
||||
|
||||
debian/ubuntu: apt install curl xz-utils bzip2 unzip make gcc gcc-multilib libc6-dev libcap-dev pkg-config
|
||||
fedora: dnf install curl xz bzip2 unzip make gcc glibc-devel glibc-devel.i686 libcap-devel pkg-config
|
||||
|
||||
copy directory "builder-linux" somethere with enough free disk space (up to 2G for all toolchains)
|
||||
run "get_toolchains.sh"
|
||||
select architectures you need or "ALL"
|
||||
run "build_deps.sh", select "ALL"
|
||||
run "build_zapret2.sh", select "ALL"
|
||||
get static musl bins from "binaries" folder
|
||||
"zapret2" is downloaded from github master branch. if you need specific version - download manually to "zapret2" dir
|
||||
i586 and riscv64 targets are built with classic PUC Lua
|
||||
|
||||
* FreeBSD :
|
||||
|
||||
pkg install pkgconf
|
||||
pkg search luajit-2
|
||||
@@ -11,7 +33,7 @@ pkg search luajit-2
|
||||
pkg install luajit-2.1.0.20250728
|
||||
make -C /opt/zapret2
|
||||
|
||||
OpenBSD :
|
||||
* OpenBSD :
|
||||
|
||||
pkg_add luajit gmake
|
||||
gmake -C /opt/zapret2 bsd
|
||||
|
||||
@@ -11,9 +11,9 @@ setup-x86_64.exe --allow-unsupported-windows --no-verify --site http://ctm.crouc
|
||||
|
||||
4) install and compile luajit from here : https://github.com/openresty/luajit2
|
||||
|
||||
download latest releast, unpack, cd to it's directory
|
||||
download latest release, unpack, cd to it's directory
|
||||
|
||||
make BUILDMODE=static CFLAGS="-Os"
|
||||
make BUILDMODE=static CFLAGS="-Os -DLUAJIT_DISABLE_FFI -ffat-lto-objects -flto=auto -ffunction-sections -fdata-sections -fvisibility=hidden"
|
||||
make install
|
||||
|
||||
5) cd to %ZAPRET_BASE%/nfq2
|
||||
@@ -32,5 +32,5 @@ Choose version 2.2.2 for Windows 10 and 2.2.0 for Windows 7.
|
||||
8) Copy cygwin1.dll, winws2.exe, windivert.dll and windivert64.sys to one folder.
|
||||
|
||||
9) Run winws2.exe from cmd.exe running as administrator.
|
||||
winws will not run from cygwin shell with cygwin1.dll copy in it's folder.
|
||||
winws will not run without cygwin1.dll outside of cygwin shell.
|
||||
winws2 will not run from cygwin shell with cygwin1.dll copy in it's folder.
|
||||
winws2 will not run without cygwin1.dll outside of cygwin shell.
|
||||
|
||||
116
docs/compile/builder-linux/build_deps.sh
Executable file
116
docs/compile/builder-linux/build_deps.sh
Executable file
@@ -0,0 +1,116 @@
|
||||
#!/bin/bash
|
||||
|
||||
EXEDIR="$(dirname "$0")"
|
||||
EXEDIR="$(cd "$EXEDIR"; pwd)"
|
||||
|
||||
. "$EXEDIR/common.inc"
|
||||
|
||||
dl_deps()
|
||||
{
|
||||
[ -d "$DEPS" ] || mkdir -p "$DEPS"
|
||||
(
|
||||
cd "$DEPS"
|
||||
exists_dir libnfnetlink-* ||
|
||||
curl -Lo - https://www.netfilter.org/pub/libnfnetlink/libnfnetlink-1.0.2.tar.bz2 | tar -xj || exit 5
|
||||
exists_dir libmnl-* ||
|
||||
curl -Lo - https://www.netfilter.org/pub/libmnl/libmnl-1.0.5.tar.bz2 | tar -xj || exit 5
|
||||
exists_dir libnetfilter_queue-* ||
|
||||
curl -Lo - https://www.netfilter.org/pub/libnetfilter_queue/libnetfilter_queue-1.0.5.tar.bz2 | tar -xj || exit 5
|
||||
exists_dir zlib-* ||
|
||||
curl -Lo - https://zlib.net/fossils/zlib-1.3.1.tar.gz | tar -xz || exit 5
|
||||
exists_dir luajit2-* ||
|
||||
curl -Lo - https://github.com/openresty/luajit2/archive/refs/tags/v${LUAJIT_RELEASE}.tar.gz | tar -xz || exit 5
|
||||
exists_dir lua-* ||
|
||||
curl -Lo - https://www.lua.org/ftp/lua-${LUA_RELEASE}.tar.gz | tar -xz || exit 5
|
||||
)
|
||||
}
|
||||
|
||||
build_netlink()
|
||||
{
|
||||
for i in libmnl libnfnetlink libnetfilter_queue ; do
|
||||
(
|
||||
cd $i-*
|
||||
[ -f "Makefile" ] && make clean
|
||||
CFLAGS="$OPTIMIZE $MINSIZE $CFLAGS" \
|
||||
LDFLAGS="$LDMINSIZE $LDFLAGS" \
|
||||
./configure --prefix= --host=$TARGET CC=$CC LD=$LD --enable-static --disable-shared --disable-dependency-tracking
|
||||
make install -j$nproc DESTDIR=$STAGING_DIR
|
||||
)
|
||||
sed -i "s|^prefix=.*|prefix=$STAGING_DIR|g" $STAGING_DIR/lib/pkgconfig/$i.pc
|
||||
done
|
||||
}
|
||||
build_zlib()
|
||||
{
|
||||
(
|
||||
cd zlib-*
|
||||
[ -f "Makefile" ] && make clean
|
||||
CFLAGS="$OPTIMIZE $MINSIZE $CFLAGS" \
|
||||
LDFLAGS="$LDMINSIZE $LDFLAGS" \
|
||||
./configure --prefix= --static
|
||||
make install -j$nproc DESTDIR=$STAGING_DIR
|
||||
)
|
||||
}
|
||||
build_lua()
|
||||
{
|
||||
(
|
||||
cd lua-${LUA_RELEASE}
|
||||
make clean
|
||||
make CC="$CC" AR="$AR rc" CFLAGS="$OPTIMIZE $MINSIZE $CFLAGS" LDFLAGS="$LDMINSIZE $LDFLAGS" linux -j$nproc
|
||||
make install INSTALL_TOP="$STAGING_DIR" INSTALL_BIN="$STAGING_DIR/bin" INSTALL_INC="$STAGING_DIR/include/lua${LUA_VER}" INSTALL_LIB="$STAGING_DIR/lib"
|
||||
)
|
||||
}
|
||||
build_luajit()
|
||||
{
|
||||
local CFL="$CFLAGS"
|
||||
local SYSMALLOC=
|
||||
(
|
||||
cd luajit2-*
|
||||
CFLAGS="-Os"
|
||||
make clean
|
||||
case $TARGET in
|
||||
aarch64*|mips64*)
|
||||
# sysmalloc can cause troubles without GC64. GC64 slows down by 10-15%. better not to use sysmalloc and leave lj_alloc.
|
||||
;;
|
||||
*)
|
||||
# save some exe size
|
||||
SYSMALLOC=-DLUAJIT_USE_SYSMALLOC
|
||||
esac
|
||||
make BUILDMODE=static XCFLAGS="$SYSMALLOC -DLUAJIT_DISABLE_FFI $CFLAGS_PIC" HOST_CC="$HOST_CC" CROSS= CC="$CC" TARGET_AR="$AR rcus" TARGET_STRIP=$STRIP TARGET_CFLAGS="$OPTIMIZE $MINSIZE $CFL" TARGET_LDFLAGS="$CPU $LDMINSIZE $LDFLAGS"
|
||||
make install PREFIX= DESTDIR="$STAGING_DIR"
|
||||
)
|
||||
}
|
||||
build_luajit_for_target()
|
||||
{
|
||||
target_has_luajit $1 && {
|
||||
case "$1" in
|
||||
*64*)
|
||||
HOST_CC="$HOSTCC"
|
||||
;;
|
||||
*)
|
||||
HOST_CC="$HOSTCC -m32"
|
||||
;;
|
||||
esac
|
||||
build_luajit
|
||||
}
|
||||
}
|
||||
|
||||
check_prog curl tar gzip bzip2 sed make cc pkg-config
|
||||
check_h_files
|
||||
dl_deps
|
||||
check_toolchains
|
||||
ask_target
|
||||
|
||||
CFLAGS_BASE="$CFLAGS"
|
||||
for t in $TGT; do
|
||||
CFLAGS="$CFLAGS_BASE"
|
||||
buildenv $t
|
||||
CFLAGS="$CFLAGS $CFLAGS_PIC"
|
||||
pushd "$DEPS"
|
||||
install_h_files
|
||||
build_netlink
|
||||
build_zlib
|
||||
build_lua
|
||||
build_luajit_for_target $t
|
||||
popd
|
||||
buildenv_clear
|
||||
done
|
||||
64
docs/compile/builder-linux/build_zapret1.sh
Executable file
64
docs/compile/builder-linux/build_zapret1.sh
Executable file
@@ -0,0 +1,64 @@
|
||||
#!/bin/bash
|
||||
|
||||
EXEDIR="$(dirname "$0")"
|
||||
EXEDIR="$(cd "$EXEDIR"; pwd)"
|
||||
|
||||
. "$EXEDIR/common.inc"
|
||||
|
||||
ZDIR="zapret"
|
||||
ZBASE="$EXEDIR"
|
||||
BRANCH=master
|
||||
ZURL=https://github.com/bol-van/zapret/archive/refs/heads/${BRANCH}.zip
|
||||
ZBIN="$EXEDIR/binaries"
|
||||
|
||||
dl_zapret1()
|
||||
{
|
||||
if [ -d "$ZBASE/$ZDIR" ]; then
|
||||
dir_is_not_empty "$ZBASE/$ZDIR" && {
|
||||
echo "zapret dir is not empty. if you want to redownload - delete it."
|
||||
return
|
||||
}
|
||||
rmdir "$ZBASE/$ZDIR"
|
||||
fi
|
||||
(
|
||||
cd "$ZBASE"
|
||||
curl -Lo /tmp/zapret.zip "$ZURL"
|
||||
unzip /tmp/zapret.zip
|
||||
rm /tmp/zapret.zip
|
||||
mv zapret-${BRANCH} $ZDIR
|
||||
)
|
||||
}
|
||||
|
||||
check_prog curl unzip make
|
||||
dl_zapret1
|
||||
check_toolchains
|
||||
ask_target
|
||||
|
||||
[ -d "$ZBIN" ] || mkdir -p "$ZBIN"
|
||||
|
||||
CFLAGS_BASE="$CFLAGS"
|
||||
for t in $TGT; do
|
||||
CFLAGS="$CFLAGS_BASE $MINSIZE"
|
||||
buildenv $t
|
||||
|
||||
translate_target $t || {
|
||||
echo COULD NOT TRANSLATE TARGET $t TO BIN DIR
|
||||
continue
|
||||
}
|
||||
|
||||
pushd $ZBASE/$ZDIR
|
||||
|
||||
make clean
|
||||
OPTIMIZE=$OPTIMIZE \
|
||||
CFLAGS="-static-libgcc -I$STAGING_DIR/include $CFLAGS $CFLAGS_PIC" \
|
||||
LDFLAGS="-L$STAGING_DIR/lib $LDMINSIZE $LDFLAGS_PIE $LDFLAGS" \
|
||||
make
|
||||
|
||||
[ -d "$ZBIN/$ZBINTARGET" ] || mkdir "$ZBIN/$ZBINTARGET"
|
||||
cp -f binaries/my/* "$ZBIN/$ZBINTARGET"
|
||||
|
||||
popd
|
||||
|
||||
buildenv_clear
|
||||
done
|
||||
|
||||
75
docs/compile/builder-linux/build_zapret2.sh
Executable file
75
docs/compile/builder-linux/build_zapret2.sh
Executable file
@@ -0,0 +1,75 @@
|
||||
#!/bin/bash
|
||||
|
||||
EXEDIR="$(dirname "$0")"
|
||||
EXEDIR="$(cd "$EXEDIR"; pwd)"
|
||||
|
||||
. "$EXEDIR/common.inc"
|
||||
|
||||
ZDIR="zapret2"
|
||||
ZBASE="$EXEDIR"
|
||||
BRANCH=master
|
||||
ZURL=https://github.com/bol-van/zapret2/archive/refs/heads/${BRANCH}.zip
|
||||
ZBIN="$EXEDIR/binaries"
|
||||
|
||||
dl_zapret2()
|
||||
{
|
||||
if [ -d "$ZBASE/$ZDIR" ]; then
|
||||
dir_is_not_empty "$ZBASE/$ZDIR" && {
|
||||
echo "zapret2 dir is not empty. if you want to redownload - delete it."
|
||||
return
|
||||
}
|
||||
rmdir "$ZBASE/$ZDIR"
|
||||
fi
|
||||
(
|
||||
cd "$ZBASE"
|
||||
curl -Lo /tmp/zapret2.zip "$ZURL"
|
||||
unzip /tmp/zapret2.zip
|
||||
rm /tmp/zapret2.zip
|
||||
mv zapret2-${BRANCH} $ZDIR
|
||||
)
|
||||
}
|
||||
|
||||
check_prog curl unzip make
|
||||
dl_zapret2
|
||||
check_toolchains
|
||||
ask_target
|
||||
|
||||
[ -d "$ZBIN" ] || mkdir -p "$ZBIN"
|
||||
|
||||
CFLAGS_BASE="$CFLAGS"
|
||||
for t in $TGT; do
|
||||
CFLAGS="$CFLAGS_BASE"
|
||||
buildenv $t
|
||||
|
||||
translate_target $t || {
|
||||
echo COULD NOT TRANSLATE TARGET $t TO BIN DIR
|
||||
continue
|
||||
}
|
||||
|
||||
pushd $ZBASE/$ZDIR
|
||||
|
||||
LUA_JIT=0
|
||||
LCFLAGS="-I${STAGING_DIR}/include/lua${LUA_VER}"
|
||||
LLIB="-L${STAGING_DIR}/lib -llua"
|
||||
target_has_luajit $t && {
|
||||
LUA_JIT=1
|
||||
LCFLAGS="-I${STAGING_DIR}/include/luajit-${LUAJIT_VER}"
|
||||
LLIB="-L${STAGING_DIR}/lib -lluajit-${LUAJIT_LUA_VER}"
|
||||
}
|
||||
|
||||
make clean
|
||||
LUA_JIT=$LUA_JIT LUA_VER=$LUA_VER LUAJIT_LUA_VER=$LUAJIT_LUA_VER \
|
||||
OPTIMIZE=$OPTIMIZE \
|
||||
MINSIZE=$MINSIZE \
|
||||
CFLAGS="-static-libgcc -I$STAGING_DIR/include $CFLAGS" \
|
||||
LDFLAGS="-L$STAGING_DIR/lib $LDFLAGS" \
|
||||
make CFLAGS_PIC="$CFLAGS_PIC" LDFLAGS_PIE="$LDFLAGS_PIE" LUA_JIT=$LJIT LUA_CFLAGS="$LCFLAGS" LUA_LIB="$LLIB"
|
||||
|
||||
[ -d "$ZBIN/$ZBINTARGET" ] || mkdir "$ZBIN/$ZBINTARGET"
|
||||
cp -f binaries/my/* "$ZBIN/$ZBINTARGET"
|
||||
|
||||
popd
|
||||
|
||||
buildenv_clear
|
||||
done
|
||||
|
||||
307
docs/compile/builder-linux/common.inc
Normal file
307
docs/compile/builder-linux/common.inc
Normal file
@@ -0,0 +1,307 @@
|
||||
EXEDIR="$(dirname "$0")"
|
||||
EXEDIR="$(cd "$EXEDIR"; pwd)"
|
||||
|
||||
TOOLCHAINS="$EXEDIR/toolchain"
|
||||
DEPS="$EXEDIR/deps"
|
||||
STAGE="$EXEDIR/staging"
|
||||
OPTIMIZE=${OPTIMIZE:--Oz}
|
||||
#MINSIZE="${MINSIZE:--flto=auto -ffunction-sections -fdata-sections}"
|
||||
MINSIZE="${MINSIZE:--ffunction-sections -fdata-sections}"
|
||||
LDMINSIZE="${LDMINSIZE:--Wl,--gc-sections -flto=auto}"
|
||||
#CFLAGS=""
|
||||
LDFLAGS="-lgcc_eh $LDFLAGS"
|
||||
# PIE makes ASLR working but adds 5% to size
|
||||
# PIE does not work for arm32 and all mips
|
||||
PIE=${PIE:-0}
|
||||
HOSTCC=${HOSTCC:-cc}
|
||||
LUA_VER=${LUA_VER:-5.5}
|
||||
LUA_RELEASE=${LUA_RELEASE:-5.5.0}
|
||||
LUAJIT_VER=${LUAJIT_VER:-2.1}
|
||||
LUAJIT_RELEASE=${LUAJIT_RELEASE:-2.1-20250826}
|
||||
LUAJIT_LUA_VER=${LUAJIT_LUA_VER:-5.1}
|
||||
nproc=$(nproc)
|
||||
|
||||
TARGETS="\
|
||||
aarch64-unknown-linux-musl \
|
||||
armv6-unknown-linux-musleabi \
|
||||
i586-unknown-linux-musl \
|
||||
x86_64-unknown-linux-musl \
|
||||
mips-unknown-linux-muslsf \
|
||||
mips64-unknown-linux-musl \
|
||||
mips64el-unknown-linux-musl \
|
||||
mipsel-unknown-linux-muslsf \
|
||||
powerpc-unknown-linux-musl \
|
||||
riscv64-unknown-linux-musl \
|
||||
"
|
||||
|
||||
target_has_luajit()
|
||||
{
|
||||
case "$1" in
|
||||
aarch64-unknown-linux-musl| \
|
||||
armv6-unknown-linux-musleabi| \
|
||||
x86_64-unknown-linux-musl| \
|
||||
mips-unknown-linux-muslsf| \
|
||||
mips64-unknown-linux-musl| \
|
||||
mips64el-unknown-linux-musl| \
|
||||
mipsel-unknown-linux-muslsf| \
|
||||
powerpc-unknown-linux-musl) \
|
||||
return 0
|
||||
;;
|
||||
esac
|
||||
return 1
|
||||
}
|
||||
|
||||
REQD_H_FILES="/usr/include/sys/capability.h /usr/include/bits/libc-header-start.h"
|
||||
REQD_QUEUE_1="/usr/include/sys/queue.h"
|
||||
REQD_QUEUE_2="/usr/include/x86_64-linux-gnu/sys/queue.h"
|
||||
check_h_files()
|
||||
{
|
||||
[ ! -f "$REQD_QUEUE_1" -a ! -f "$REQD_QUEUE_2" ] && {
|
||||
echo "could not find $REQD_QUEUE_1 or $REQD_QUEUE_2"
|
||||
help_pkg
|
||||
exit 10
|
||||
}
|
||||
check_file $REQD_H_FILES
|
||||
}
|
||||
install_h_files()
|
||||
{
|
||||
if [ -f "$REQD_QUEUE_1" ]; then
|
||||
install -Dm644 -t $STAGING_DIR/include/sys $REQD_QUEUE_1
|
||||
elif [ -f "$REQD_QUEUE_2" ]; then
|
||||
install -Dm644 -t $STAGING_DIR/include/sys $REQD_QUEUE_2
|
||||
fi
|
||||
install -Dm644 -t $STAGING_DIR/include/sys $REQD_H_FILES
|
||||
}
|
||||
|
||||
buildenv()
|
||||
{
|
||||
# $1 = arch
|
||||
|
||||
export TARGET=$1
|
||||
export CC=$TARGET-gcc
|
||||
export LD=$TARGET-ld
|
||||
export AR=$TARGET-ar
|
||||
export NM=$TARGET-nm
|
||||
export STRIP=$TARGET-strip
|
||||
export STAGING_DIR="$EXEDIR/staging/$TARGET"
|
||||
[ -d "$STAGING_DIR" ] || {
|
||||
mkdir -p "$STAGING_DIR"
|
||||
mkdir -p "$STAGING_DIR/lib/pkgconfig"
|
||||
mkdir -p "$STAGING_DIR/bin"
|
||||
mkdir -p "$STAGING_DIR/include"
|
||||
}
|
||||
export PKG_CONFIG_PATH=$STAGING_DIR/lib/pkgconfig
|
||||
OLDPATH="$PATH"
|
||||
export PATH="$PATH:$TOOLCHAINS/$TARGET/bin"
|
||||
|
||||
CPU=
|
||||
CFLAGS_PIC=
|
||||
LDFLAGS_PIE=-static
|
||||
# not all archs support -static-pie. if does not support - it produces dynamic executable
|
||||
# "-static -static-pie" causes segfaults
|
||||
case $1 in
|
||||
armv6-*)
|
||||
CPU="-mthumb -msoft-float"
|
||||
CFLAGS="$CPU $CFLAGS"
|
||||
;;
|
||||
mips*)
|
||||
;;
|
||||
*)
|
||||
[ "$PIE" = 1 ] && {
|
||||
CFLAGS_PIC=-fPIC
|
||||
LDFLAGS_PIE="-static-pie"
|
||||
}
|
||||
esac
|
||||
}
|
||||
|
||||
buildenv_clear()
|
||||
{
|
||||
export PATH="$OLDPATH" TARGET= CC= LD= AR= NM= STRIP= STAGING_DIR= PKG_CONFIG_PATH=
|
||||
OLDPATH=
|
||||
}
|
||||
|
||||
which()
|
||||
{
|
||||
# on some systems 'which' command is considered deprecated and not installed by default
|
||||
# 'command -v' replacement does not work exactly the same way. it outputs shell aliases if present
|
||||
# $1 - executable name
|
||||
local IFS=:
|
||||
[ "$1" != "${1#/}" ] && [ -x "$1" ] && {
|
||||
echo "$1"
|
||||
return 0
|
||||
}
|
||||
for p in $PATH; do
|
||||
[ -x "$p/$1" ] && {
|
||||
echo "$p/$1"
|
||||
return 0
|
||||
}
|
||||
done
|
||||
return 1
|
||||
}
|
||||
exists()
|
||||
{
|
||||
which "$1" >/dev/null 2>/dev/null
|
||||
}
|
||||
exists_dir()
|
||||
{
|
||||
# use $1, ignore other args
|
||||
[ -d "$1" ]
|
||||
}
|
||||
|
||||
dir_is_not_empty()
|
||||
{
|
||||
# $1 - directory
|
||||
local n
|
||||
[ -d "$1" ] || return 1
|
||||
n=$(ls -A "$1" | wc -c | xargs)
|
||||
[ "$n" != 0 ]
|
||||
}
|
||||
|
||||
find_str_in_list()
|
||||
{
|
||||
# $1 - string
|
||||
# $2 - space separated values
|
||||
local v
|
||||
[ -n "$1" ] && {
|
||||
for v in $2; do
|
||||
[ "$v" = "$1" ] && return 0
|
||||
done
|
||||
}
|
||||
return 1
|
||||
}
|
||||
|
||||
ask_list()
|
||||
{
|
||||
# $1 - mode var
|
||||
# $2 - space separated value list
|
||||
# $3 - (optional) default value
|
||||
local M_DEFAULT
|
||||
eval M_DEFAULT="\$$1"
|
||||
local M_DEFAULT_VAR="$M_DEFAULT"
|
||||
local M="" m
|
||||
|
||||
[ -n "$3" ] && { find_str_in_list "$M_DEFAULT" "$2" || M_DEFAULT="$3" ;}
|
||||
|
||||
n=1
|
||||
for m in $2; do
|
||||
echo $n : $m
|
||||
n=$(($n+1))
|
||||
done
|
||||
printf "your choice (default : $M_DEFAULT) : "
|
||||
read m
|
||||
[ -n "$m" ] && M=$(echo $2 | cut -d ' ' -f$m 2>/dev/null)
|
||||
[ -z "$M" ] && M="$M_DEFAULT"
|
||||
echo selected : $M
|
||||
eval $1="\"$M\""
|
||||
|
||||
[ "$M" != "$M_DEFAULT_VAR" ]
|
||||
}
|
||||
|
||||
ask_target()
|
||||
{
|
||||
# $1 = 1 = ask all, otherwise ask only present toolchains
|
||||
|
||||
# already set ?
|
||||
[ -n "$TGT" ] && return
|
||||
|
||||
local d ALL_TARGETS
|
||||
[ "$1" = 1 ] || {
|
||||
if dir_is_not_empty "$TOOLCHAINS"; then
|
||||
for d in "$TOOLCHAINS"/*; do
|
||||
[ -d "$d" ] && {
|
||||
d="$(basename "$d")"
|
||||
ALL_TARGETS="$ALL_TARGETS $d"
|
||||
}
|
||||
done
|
||||
fi
|
||||
}
|
||||
[ -n "$ALL_TARGETS" ] || ALL_TARGETS="$TARGETS"
|
||||
|
||||
echo "select target :"
|
||||
ask_list TARGET "ALL $ALL_TARGETS" "ALL"
|
||||
echo
|
||||
echo selected TARGET : $TARGET
|
||||
echo
|
||||
|
||||
if [ $TARGET = ALL ]; then
|
||||
TGT="$ALL_TARGETS"
|
||||
else
|
||||
TGT="$TARGET"
|
||||
fi
|
||||
}
|
||||
|
||||
check_toolchains()
|
||||
{
|
||||
dir_is_not_empty "$TOOLCHAINS" || {
|
||||
echo DOWNLOAD TOOLCHAINS FIRST
|
||||
exit 1
|
||||
}
|
||||
}
|
||||
|
||||
help_pkg()
|
||||
{
|
||||
echo "debian/ubuntu: apt install curl xz-utils bzip2 unzip make gcc gcc-multilib libc6-dev libcap-dev pkg-config"
|
||||
echo "fedora: dnf install curl xz bzip2 unzip make gcc glibc-devel glibc-devel.i686 libcap-devel pkg-config"
|
||||
}
|
||||
|
||||
check_prog()
|
||||
{
|
||||
while [ -n "$1" ]; do
|
||||
exists $1 || {
|
||||
echo $1 is not available
|
||||
help_pkg
|
||||
exit 10
|
||||
}
|
||||
shift
|
||||
done
|
||||
}
|
||||
check_file()
|
||||
{
|
||||
while [ -n "$1" ]; do
|
||||
[ -f "$1" ] || {
|
||||
echo $1 is not available
|
||||
help_pkg
|
||||
exit 10
|
||||
}
|
||||
shift
|
||||
done
|
||||
}
|
||||
|
||||
translate_target()
|
||||
{
|
||||
case $1 in
|
||||
aarch64-unknown-linux-musl)
|
||||
ZBINTARGET=linux-arm64
|
||||
;;
|
||||
armv6-unknown-linux-musleabi)
|
||||
ZBINTARGET=linux-arm
|
||||
;;
|
||||
x86_64-unknown-linux-musl)
|
||||
ZBINTARGET=linux-x86_64
|
||||
;;
|
||||
i586-unknown-linux-musl)
|
||||
ZBINTARGET=linux-x86
|
||||
;;
|
||||
mips-unknown-linux-muslsf)
|
||||
ZBINTARGET=linux-mips
|
||||
;;
|
||||
mipsel-unknown-linux-muslsf)
|
||||
ZBINTARGET=linux-mipsel
|
||||
;;
|
||||
mips64-unknown-linux-musl)
|
||||
ZBINTARGET=linux-mips64
|
||||
;;
|
||||
mips64el-unknown-linux-musl)
|
||||
ZBINTARGET=linux-mipsel64
|
||||
;;
|
||||
powerpc-unknown-linux-musl)
|
||||
ZBINTARGET=linux-ppc
|
||||
;;
|
||||
riscv64-unknown-linux-musl)
|
||||
ZBINTARGET=linux-riscv64
|
||||
;;
|
||||
*)
|
||||
return 1
|
||||
esac
|
||||
return 0
|
||||
}
|
||||
22
docs/compile/builder-linux/get_toolchains.sh
Executable file
22
docs/compile/builder-linux/get_toolchains.sh
Executable file
@@ -0,0 +1,22 @@
|
||||
#!/bin/bash
|
||||
|
||||
EXEDIR="$(dirname "$0")"
|
||||
EXEDIR="$(cd "$EXEDIR"; pwd)"
|
||||
|
||||
. "$EXEDIR/common.inc"
|
||||
|
||||
BASEURL=https://github.com/bol-van/musl-cross/releases/download/latest
|
||||
|
||||
check_prog curl tar xz
|
||||
|
||||
[ -d "$TOOLCHAINS" ] || mkdir -p "$TOOLCHAINS"
|
||||
|
||||
ask_target 1
|
||||
|
||||
(
|
||||
cd "$TOOLCHAINS"
|
||||
for t in $TGT; do
|
||||
[ -d "$t" ] && rm -r "$t"
|
||||
curl -Lo - "${BASEURL}/${t}.tar.xz" | tar -Jx
|
||||
done
|
||||
)
|
||||
@@ -637,6 +637,7 @@ General parameters for all versions - nfqws2, dvtws2, winws2.
|
||||
--comment=any_text ; any text. ignored
|
||||
--intercept=0|1 ; allow interception. 0 - no, 1 - yes. If 0 lua-init scripts are executed then process exits. NFQUEUE is not initialized.
|
||||
--daemon ; detach from the console (daemonize)
|
||||
--chdir[=path] ; change current directory. if no path specified use the executable file directory - EXEDIR
|
||||
--pidfile=<filename> ; write PID to a file
|
||||
--ctrack-timeouts=S:E:F[:U] ; conntrack timeouts for tcp stages (SYN, ESTABLISHED, FIN) and for udp
|
||||
--ctrack-disable=[0|1] ; 1 disables conntrack
|
||||
@@ -3530,7 +3531,8 @@ Checks the [instance cutoff](#instance_cutoff) state for `desync.func_instance`
|
||||
function apply_arg_prefix(desync)
|
||||
```
|
||||
|
||||
Performs substitution of argument values from `desync.arg` that start with `%` and `#`.
|
||||
Performs substitution of argument values from `desync.arg` that start with `%`, `#`, `\`.
|
||||
Multiple calls are safe but do not update desync.arg if blobs were changed.
|
||||
|
||||
### apply_execution_plan
|
||||
|
||||
@@ -3539,6 +3541,8 @@ function apply_execution_plan(desync, instance)
|
||||
```
|
||||
|
||||
Copies the instance identification and its arguments from an [execution plan](#execution_plan) `instance` into the desync object, thereby recreating the desync state as if the `instance` were called directly by C code.
|
||||
With one exception : apply_arg_prefix is not applied because args can refer a blob created by previous conditionally executed instances.
|
||||
|
||||
The [execution plan](#execution_plan) is provided by the C function `execution_plan()` as an array of `instance` elements.
|
||||
|
||||
### verdict_aggregate
|
||||
@@ -3553,11 +3557,17 @@ Aggregates verdicts v1 and v2. VERDICT_MODIFY overrides VERDICT_PASS, while VERD
|
||||
|
||||
```
|
||||
function plan_instance_execute(desync, verdict, instance)
|
||||
function plan_instance_execute_preapplied(desync, verdict, instance)
|
||||
```
|
||||
|
||||
Executes an [execution plan](#execution_plan) `instance`, taking into account the [instance cutoff](#instance_cutoff) and standard [payload](#in-profile-filters) and [range](#in-profile-filters) filters.
|
||||
Calls apply_arg_prefix right before calling the instance.
|
||||
Returns the aggregation of the current verdict and the `instance` verdict.
|
||||
|
||||
The "preapplied" version does not apply execution plan, allowing the calling code to do so.
|
||||
Sometimes, to decide whether to call an instance, you need a desync table configured for the called instance.
|
||||
"preapplied" version allows to avoid double copying.
|
||||
|
||||
### plan_instance_pop
|
||||
|
||||
```
|
||||
@@ -4472,7 +4482,8 @@ Returns `true` if the dissect is tcp and has tcp timestamp option.
|
||||
function cond_lua(desync)
|
||||
```
|
||||
|
||||
Executes a Lua code from the "code" argument. The code returns condition value. Direct addressing of the desync table is possible within the code.
|
||||
Executes a Lua code from the "cond_code" argument. The code returns condition value. Direct addressing of the desync table is possible within the code.
|
||||
desync.arg is passed without called "apply_arg_prefix" : `%`, `#`, `\` remain as is without substitution because can refer blobs created by previous conditionally executed instances.
|
||||
|
||||
|
||||
# Auxiliary programs
|
||||
@@ -5203,6 +5214,15 @@ ipt_first_packets()
|
||||
|
||||
Outputs to stdout: `-m connbytes --connbytes-dir=original --connbytes-mode=packets --connbytes $RANGE`. `RANGE` is defined as "1:$1". If `$1` is "keepalive", nothing is output (no connbytes filter).
|
||||
|
||||
```
|
||||
ipt_port_ipset()
|
||||
# $1 - ipset name
|
||||
# $2 - comma separated port or port range list. ranges are port1-port2
|
||||
```
|
||||
|
||||
Creates "bitmap:port" ipset filled with the supplied port list. If the set already exists it's elements are replaced.
|
||||
|
||||
|
||||
##### Working with nftables
|
||||
|
||||
```
|
||||
|
||||
@@ -696,6 +696,7 @@ nfqws2 использует стандартный парсер getopt_long_only
|
||||
--comment=any_text ; любой текст. игнорируется
|
||||
--intercept=0|1 ; разрешить перехват. 0 - нет, 1 - да. при 0 выполняются lua-init скрипты и процесс завершается, перехват не включается, очередь NFQUEUE не инициализируется
|
||||
--daemon ; отключиться от консоли (демонизироваться)
|
||||
--chdir[=path] ; сменить текущую директорию. если нет path, выбирается путь исполняемого файла - EXEDIR
|
||||
--pidfile=<filename> ; запись PID в файл
|
||||
--ctrack-timeouts=S:E:F[:U] ; таймауты conntrack для стадий tcp SYN, ESTABLISHED, FIN и для udp
|
||||
--ctrack-disable=[0|1] ; 1 отключает conntrack
|
||||
@@ -3708,7 +3709,8 @@ function cutoff_shim_check(desync)
|
||||
function apply_arg_prefix(desync)
|
||||
```
|
||||
|
||||
Выполняет подстановку значений аргументов из desync.arg, начинающихся с `%` и `#`.
|
||||
Выполняет подстановку значений аргументов из desync.arg, начинающихся с `%` и `#`, `\`.
|
||||
Функция ставит специальную метку в desync.arg , чтобы избежать двойного разименования. Повторные вызовы безопасны, но не обновляют desync.arg при изменении блобов.
|
||||
|
||||
### apply_execution_plan
|
||||
|
||||
@@ -3718,6 +3720,8 @@ function apply_execution_plan(desync, instance)
|
||||
|
||||
Копирует в desync идентификацию инстанса и его аргументы из элемента [execution plan](#execution_plan) `instance`,
|
||||
тем самым воссоздает состояние desync, как если бы `instance` был вызван напрямую C кодом.
|
||||
За одним исключением : apply_arg_prefix не применяется, поскольку может содержать несуществующие блоб, существование которого зависит от условного выполнения предыдущих истансов.
|
||||
|
||||
[execution plan](#execution_plan) выдается C функцией `execution_plan()` как массив, элементами которого являются `instance`.
|
||||
|
||||
### verdict_aggregate
|
||||
@@ -3732,11 +3736,17 @@ function verdict_aggregate(v1, v2)
|
||||
|
||||
```
|
||||
function plan_instance_execute(desync, verdict, instance)
|
||||
function plan_instance_execute_preapplied(desync, verdict, instance)
|
||||
```
|
||||
|
||||
Выполняет элемент [execution plan](#execution_plan) `instance` с учетом [instance cutoff](#instance_cutoff) и стандартных фильтров [payload](#внутрипрофильные-фильтры) и [range](#внутрипрофильные-фильтры).
|
||||
При совпадении условий непосредственно перед вызовом выполняет apply_arg_prefix.
|
||||
Возвращает агрегацию verdict и вердикта `instance`.
|
||||
|
||||
Вариант "preapplied" не выполняет apply_execution_plan, позволяя это сделат вызывающему коду.
|
||||
Иногда для принятия решения вызывать ли instance требуется таблица desync, настроенная на вызываемый инстанс.
|
||||
Чтобы не делать apply дважды (там копирование desync.arg) и существует этот вариант.
|
||||
|
||||
### plan_instance_pop
|
||||
|
||||
```
|
||||
@@ -4651,7 +4661,8 @@ function cond_tcp_ts(desync)
|
||||
function cond_lua(desync)
|
||||
```
|
||||
|
||||
Выполняет Lua код из аргумента "code". Код возвращает значение условия через return. Возможна прямая адресация таблицы desync.
|
||||
Выполняет Lua код из аргумента "cond_code". Код возвращает значение условия через return. Возможна прямая адресация таблицы desync.
|
||||
desync.arg передаются с НЕ разименованными `%`, `#`, `\`, поскольку разименование может ссылаться на блобы, создаваемые предыдущими условно вызываемыми инстансами.
|
||||
|
||||
# Вспомогательные программы
|
||||
|
||||
@@ -5382,6 +5393,14 @@ ipt_first_packets()
|
||||
|
||||
Выдает в stdout "-m connbytes --connbytes-dir=original --connbytes-mode=packets --connbytes $RANGE". RANGE определяется как "1:$1". Если $1 = "keepalive", не выдается ничего (нет фильтра по connbytes).
|
||||
|
||||
```
|
||||
ipt_port_ipset()
|
||||
# $1 - имя ipset
|
||||
# $2 - список портов через запятую. диапазоны через "-"
|
||||
```
|
||||
|
||||
Создает ipset типа bitamp:port со списком портов. Если ipset уже существует, заменяет в нем элементы.
|
||||
|
||||
##### Работа с nftables
|
||||
|
||||
```
|
||||
|
||||
@@ -48,7 +48,7 @@ zapret2 является дальнейшим развитием проекта
|
||||
|
||||
Lua код получает от C кода структурированное представление приходящих пакетов в виде дерева (диссекты), подобного тем, что вы видите в wireshark.
|
||||
Туда же приходят результаты сборки или дешифровки частей некоторых протоколов (tls, quic).
|
||||
С код предоставляет функции-хелперы, позволяющие отсылать пакеты, работать с двоичными данными, разбирать TLS, искать маркер-позции и т.д.
|
||||
С код предоставляет функции-хелперы, позволяющие отсылать пакеты, работать с двоичными данными, разбирать TLS, искать маркер-позиции и т.д.
|
||||
Имеется библиотека хелперов, написанных на Lua, а так же готовая библиотека программ атаки на DPI (стратегий), реализующая функции *nfqws1* в расширенном варианте
|
||||
и с большей гибкостью.
|
||||
|
||||
@@ -414,8 +414,8 @@ nfqws2 \
|
||||
### Какие есть еще параметры
|
||||
|
||||
Как узнать какие есть еще функции и какие у них бывают параметры ? Смотрите `zapret-antidpi.lua`. Перед каждой функцией подробно описано какие параметры она берет.
|
||||
Описание стандартных блоков параметров есть в начале. Позже - по мере сил и возможностей - будет писаться талмуд - справочник с руководством по программированию
|
||||
*nfqws2* и описание стандартных библиотек.
|
||||
Описание стандартных блоков параметров есть в начале.
|
||||
Или сразу читайте [талмуд](manual.md) . Там все документировано.
|
||||
|
||||
### Очень важный совет
|
||||
|
||||
|
||||
BIN
files/fake/quic2_example_com.bin
Normal file
BIN
files/fake/quic2_example_com.bin
Normal file
Binary file not shown.
@@ -1,13 +0,0 @@
|
||||
REGISTER sip:192.168.1.1 SIP/2.0
|
||||
Via: SIP/2.0/UDP 192.168.1.2:42931;rport;branch=z9hG4bKPj3fd2e8713ffcd90c43f6ce69f6c98461
|
||||
Max-Forwards: 50
|
||||
From: <sip:703@192.168.1.1>;tag=ca565d7bd4e24a6d80c631d395ee117e
|
||||
To: <sip:703@192.168.1.1>
|
||||
Call-ID: dfec38302b8cea3d83c1452527c895c1
|
||||
CSeq: 26139 REGISTER
|
||||
User-Agent: MicroSIP/3.21.5
|
||||
Contact: <sip:703@192.168.1.2:42931;ob>
|
||||
Expires: 300
|
||||
Allow: PRACK, INVITE, ACK, BYE, CANCEL, UPDATE, INFO, SUBSCRIBE, NOTIFY, REFER, MESSAGE, OPTIONS
|
||||
Content-Length: 0
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
|
||||
WEBSERVER_DEFAULT_STRATEGY="
|
||||
--server
|
||||
--payload http_reply,tls_server_hello --lua-desync=fake:blob=0x00000000000000000000000000000000:badsum:repeats=2 --lua-desync=multisplit
|
||||
--payload empty --lua-desync=synack_split"
|
||||
--payload=http_reply,tls_server_hello --lua-desync=fake:blob=0x00000000000000000000000000000000:badsum:repeats=2 --lua-desync=multisplit
|
||||
--payload=empty --lua-desync=synack_split"
|
||||
|
||||
# can override in config :
|
||||
NFQWS_OPT_DESYNC_WEBSERVER="${NFQWS_OPT_DESYNC_WEBSERVER:-$WEBSERVER_DEFAULT_STRATEGY}"
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
# NOTE: @ih requires nft 1.0.1+ and updated kernel version. it's confirmed to work on 5.15 (openwrt 23) and not work on 5.10 (openwrt 22)
|
||||
|
||||
# can override in config :
|
||||
NFQWS_OPT_DESYNC_DHT="${NFQWS_OPT_DESYNC_DHT:---payload dht --lua-desync=dht_dn}"
|
||||
NFQWS_OPT_DESYNC_DHT="${NFQWS_OPT_DESYNC_DHT:---payload=dht --lua-desync=dht_dn}"
|
||||
# set it to "keepalive" to fool all packets, not just the first. or set number of packets to be fooled.
|
||||
NFQWS_OPT_DHT_PKT_OUT=${NFQWS_OPT_DHT_PKT_OUT:-20}
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
# NOTE: @ih requires nft 1.0.1+ and updated kernel version. it's confirmed to work on 5.15 (openwrt 23) and not work on 5.10 (openwrt 22)
|
||||
|
||||
# can override in config :
|
||||
NFQWS_OPT_DESYNC_DISCORD_MEDIA="${NFQWS_OPT_DESYNC_DISCORD_MEDIA:---payload discord_ip_discovery --lua-desync=fake:blob=0x00000000000000000000000000000000:repeats=2}"
|
||||
NFQWS_OPT_DESYNC_DISCORD_MEDIA="${NFQWS_OPT_DESYNC_DISCORD_MEDIA:---payload=discord_ip_discovery --lua-desync=fake:blob=0x00000000000000000000000000000000:repeats=2}"
|
||||
DISCORD_MEDIA_PORT_RANGE="${DISCORD_MEDIA_PORT_RANGE:-50000-50099}"
|
||||
|
||||
alloc_dnum DNUM_DISCORD_MEDIA
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# this custom script demonstrates how to launch extra nfqws instance limited by ipset
|
||||
|
||||
# can override in config :
|
||||
NFQWS2_MY1_OPT="${NFQWS2_MY1_OPT:---filter-udp=* --payload known,unknown --lua-desync=fake:blob=0x00000000000000000000000000000000:repeats=2:payload=all --new --filter-tcp=* --payload=known,unknown --lua-desync=multisplit}"
|
||||
NFQWS2_MY1_OPT="${NFQWS2_MY1_OPT:---filter-udp=* --payload=known,unknown --lua-desync=fake:blob=0x00000000000000000000000000000000:repeats=2:payload=all --new --filter-tcp=* --payload=known,unknown --lua-desync=multisplit}"
|
||||
NFQWS2_MY1_SUBNETS4="${NFQWS2_MY1_SUBNETS4:-173.194.0.0/16 108.177.0.0/17 74.125.0.0/16 64.233.160.0/19 172.217.0.0/16}"
|
||||
NFQWS2_MY1_SUBNETS6="${NFQWS2_MY1_SUBNETS6:-2a00:1450::/29}"
|
||||
NFQWS2_MY1_PORTS_TCP=${NFQWS2_MY1_PORTS_TCP:-$NFQWS2_PORTS_TCP}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
# NOTE: @ih requires nft 1.0.1+ and updated kernel version. it's confirmed to work on 5.15 (openwrt 23) and not work on 5.10 (openwrt 22)
|
||||
|
||||
# can override in config :
|
||||
NFQWS_OPT_DESYNC_QUIC="${NFQWS_OPT_DESYNC_QUIC:---payload quic_initial --lua-desync=fake:blob=fake_default_quic:repeats=2}"
|
||||
NFQWS_OPT_DESYNC_QUIC="${NFQWS_OPT_DESYNC_QUIC:---payload=quic_initial --lua-desync=fake:blob=fake_default_quic:repeats=2}"
|
||||
|
||||
alloc_dnum DNUM_QUIC4ALL
|
||||
alloc_qnum QNUM_QUIC4ALL
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
# NOTE: @ih requires nft 1.0.1+ and updated kernel version. it's confirmed to work on 5.15 (openwrt 23) and not work on 5.10 (openwrt 22)
|
||||
|
||||
# can override in config :
|
||||
NFQWS_OPT_DESYNC_STUN="${NFQWS_OPT_DESYNC_STUN:---payload stun --lua-desync=fake:blob=0x00000000000000000000000000000000:repeats=2}"
|
||||
NFQWS_OPT_DESYNC_STUN="${NFQWS_OPT_DESYNC_STUN:---payload=stun --lua-desync=fake:blob=0x00000000000000000000000000000000:repeats=2}"
|
||||
|
||||
alloc_dnum DNUM_STUN4ALL
|
||||
alloc_qnum QNUM_STUN4ALL
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
# NOTE: @ih requires nft 1.0.1+ and updated kernel version. it's confirmed to work on 5.15 (openwrt 23) and not work on 5.10 (openwrt 22)
|
||||
|
||||
# can override in config :
|
||||
NFQWS_OPT_DESYNC_WG="${NFQWS_OPT_DESYNC_WG:---payload wireguard_initiation,wireguard_response,wireguard_cookie --lua-desync=fake:blob=0x00000000000000000000000000000000:repeats=2}"
|
||||
NFQWS_OPT_DESYNC_WG="${NFQWS_OPT_DESYNC_WG:---payload=wireguard_initiation,wireguard_response,wireguard_cookie --lua-desync=fake:blob=0x00000000000000000000000000000000:repeats=2}"
|
||||
|
||||
alloc_dnum DNUM_WG4ALL
|
||||
alloc_qnum QNUM_WG4ALL
|
||||
|
||||
@@ -7,7 +7,6 @@ Type=forking
|
||||
Restart=no
|
||||
TimeoutSec=30sec
|
||||
IgnoreSIGPIPE=no
|
||||
KillMode=none
|
||||
GuessMainPID=no
|
||||
RemainAfterExit=no
|
||||
ExecStart=/opt/zapret2/init.d/sysv/zapret2 start
|
||||
|
||||
@@ -157,7 +157,7 @@ fi
|
||||
unset PKTWS
|
||||
case $UNAME in
|
||||
Linux)
|
||||
ARCHLIST="my linux-x86_64 linux-x86 linux-arm64 linux-arm linux-mips64 linux-mipsel linux-mips linux-lexra linux-ppc"
|
||||
ARCHLIST="my linux-x86_64 linux-x86 linux-arm64 linux-arm linux-mips64 linux-mipsel64 linux-mipsel linux-mips linux-lexra linux-ppc linux-riscv64"
|
||||
PKTWS=nfqws2
|
||||
;;
|
||||
FreeBSD)
|
||||
|
||||
@@ -1,8 +1,12 @@
|
||||
CC ?= cc
|
||||
OPTIMIZE ?= -Os
|
||||
CFLAGS += -std=gnu99 $(OPTIMIZE) -flto=auto
|
||||
CFLAGS_PIC = -fPIC
|
||||
CFLAGS += -std=gnu99 $(OPTIMIZE) -flto=auto $(CFLAGS_PIC)
|
||||
CFLAGS_BSD = -Wno-address-of-packed-member
|
||||
CFLAGS_WIN = -static
|
||||
LDFLAGS_PIE = -pie
|
||||
LDFLAGS += $(LDFLAGS_PIE)
|
||||
|
||||
LIBS =
|
||||
LIBS_WIN = -lws2_32
|
||||
SRC_FILES = ip2net.c qsort.c
|
||||
|
||||
@@ -125,7 +125,7 @@ function http_domcase(ctx, desync)
|
||||
local host_range = resolve_multi_pos(desync.dis.payload,desync.l7payload,"host,endhost")
|
||||
if #host_range == 2 then
|
||||
local host = string.sub(desync.dis.payload,host_range[1],host_range[2]-1)
|
||||
local newhost="", i
|
||||
local newhost=""
|
||||
for i = 1, #host do
|
||||
newhost=newhost..((i%2)==0 and string.lower(string.sub(host,i,i)) or string.upper(string.sub(host,i,i)))
|
||||
end
|
||||
@@ -221,7 +221,7 @@ function http_unixeol(ctx, desync)
|
||||
if #http < #desync.dis.payload then
|
||||
hdis.headers[idx_ua].value = hdis.headers[idx_ua].value .. string.rep(" ", #desync.dis.payload - #http)
|
||||
end
|
||||
local http = http_reconstruct_req(hdis, true)
|
||||
http = http_reconstruct_req(hdis, true)
|
||||
if #http==#desync.dis.payload then
|
||||
desync.dis.payload = http
|
||||
DLOG("http_unixeol: applied")
|
||||
@@ -389,7 +389,8 @@ function syndata(ctx, desync)
|
||||
dis.payload = blob(desync, desync.arg.blob, "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00")
|
||||
apply_fooling(desync, dis)
|
||||
if desync.arg.tls_mod then
|
||||
dis.payload = tls_mod_shim(desync, dis.payload, desync.arg.tls_mod, nil)
|
||||
local pl = tls_mod_shim(desync, dis.payload, desync.arg.tls_mod, nil)
|
||||
if pl then dis.payload = pl end
|
||||
end
|
||||
if b_debug then DLOG("syndata: "..hexdump_dlog(dis.payload)) end
|
||||
if rawsend_dissect_ipfrag(dis, desync_opts(desync)) then
|
||||
@@ -449,7 +450,8 @@ function fake(ctx, desync)
|
||||
end
|
||||
local fake_payload = blob(desync, desync.arg.blob)
|
||||
if desync.reasm_data and desync.arg.tls_mod then
|
||||
fake_payload = tls_mod_shim(desync, fake_payload, desync.arg.tls_mod, desync.reasm_data)
|
||||
local pl = tls_mod_shim(desync, fake_payload, desync.arg.tls_mod, desync.reasm_data)
|
||||
if pl then fake_payload = pl end
|
||||
end
|
||||
-- check debug to save CPU
|
||||
if b_debug then DLOG("fake: "..hexdump_dlog(fake_payload)) end
|
||||
@@ -729,14 +731,15 @@ function hostfakesplit(ctx, desync)
|
||||
local midhost
|
||||
if desync.arg.midhost then
|
||||
midhost = resolve_pos(data,desync.l7payload,desync.arg.midhost)
|
||||
if not midhost then
|
||||
if midhost then
|
||||
DLOG("hosfakesplit: midhost marker resolved to "..midhost)
|
||||
if midhost<=pos[1] or midhost>pos[2] then
|
||||
DLOG("hostfakesplit: midhost is not inside the host range")
|
||||
midhost = nil
|
||||
end
|
||||
else
|
||||
DLOG("hostfakesplit: cannot resolve midhost marker '"..desync.arg.midhost.."'")
|
||||
end
|
||||
DLOG("hosfakesplit: midhost marker resolved to "..midhost)
|
||||
if midhost<=pos[1] or midhost>pos[2] then
|
||||
DLOG("hostfakesplit: midhost is not inside the host range")
|
||||
midhost = nil
|
||||
end
|
||||
end
|
||||
-- if present apply ipfrag only to real host parts. fakes and parts outside of the host must be visible to DPI.
|
||||
if midhost then
|
||||
@@ -893,7 +896,7 @@ function fakedsplit(ctx, desync)
|
||||
return desync.arg.nodrop and VERDICT_PASS or VERDICT_DROP
|
||||
end
|
||||
else
|
||||
DLOG("fakedsplit: cannot resolve pos '"..desync.arg.pos.."'")
|
||||
DLOG("fakedsplit: cannot resolve pos '"..spos.."'")
|
||||
end
|
||||
else
|
||||
DLOG("fakedsplit: not acting on further replay pieces")
|
||||
@@ -938,11 +941,11 @@ function fakeddisorder(ctx, desync)
|
||||
if b_debug then DLOG("fakeddisorder: resolved split pos: "..tostring(pos-1)) end
|
||||
|
||||
-- do not apply fooling to original parts except tcp_ts_up but apply ip_id
|
||||
local fake, part, pat
|
||||
local fake, part
|
||||
local opts_orig = {rawsend = rawsend_opts_base(desync), reconstruct = {}, ipfrag = {}, ipid = desync.arg, fooling = {tcp_ts_up = desync.arg.tcp_ts_up}}
|
||||
local opts_fake = {rawsend = rawsend_opts(desync), reconstruct = reconstruct_opts(desync), ipfrag = {}, ipid = desync.arg, fooling = desync.arg}
|
||||
|
||||
fakepat = desync.arg.pattern and blob(desync,desync.arg.pattern) or "\x00"
|
||||
local fakepat = desync.arg.pattern and blob(desync,desync.arg.pattern) or "\x00"
|
||||
|
||||
-- second fake
|
||||
fake = pattern(fakepat,pos,#data-pos+1)
|
||||
@@ -1008,7 +1011,7 @@ function fakeddisorder(ctx, desync)
|
||||
return desync.arg.nodrop and VERDICT_PASS or VERDICT_DROP
|
||||
end
|
||||
else
|
||||
DLOG("fakeddisorder: cannot resolve pos '"..desync.arg.pos.."'")
|
||||
DLOG("fakeddisorder: cannot resolve pos '"..spos.."'")
|
||||
end
|
||||
else
|
||||
DLOG("fakeddisorder: not acting on further replay pieces")
|
||||
@@ -1209,8 +1212,8 @@ function udplen(ctx, desync)
|
||||
else
|
||||
desync.dis.payload = string.sub(desync.dis.payload,1,len+inc)
|
||||
DLOG("udplen: "..len.." => "..#desync.dis.payload)
|
||||
return VERDICT_MODIFY
|
||||
end
|
||||
return VERDICT_MODIFY
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -313,7 +313,7 @@ function circular(ctx, desync)
|
||||
local function count_strategies(hrec)
|
||||
if not hrec.ctstrategy then
|
||||
local uniq={}
|
||||
local n=0
|
||||
local n
|
||||
for i,instance in pairs(desync.plan) do
|
||||
if instance.arg.strategy then
|
||||
n = tonumber(instance.arg.strategy)
|
||||
@@ -411,19 +411,19 @@ function cond_tcp_has_ts(desync)
|
||||
end
|
||||
-- exec lua code in "code" arg and return it's result
|
||||
function cond_lua(desync)
|
||||
if not desync.arg.code then
|
||||
error("cond_lua: no 'code' parameter")
|
||||
if not desync.arg.cond_code then
|
||||
error("cond_lua: no 'cond_code' parameter")
|
||||
end
|
||||
local fname = desync.func_instance.."_cond_code"
|
||||
local fname = desync.func_instance.."_cond_cond_code"
|
||||
if not _G[fname] then
|
||||
local err
|
||||
_G[fname], err = load(desync.arg.code, fname)
|
||||
_G[fname], err = load(desync.arg.cond_code, fname)
|
||||
if not _G[fname] then
|
||||
error(err)
|
||||
return
|
||||
end
|
||||
end
|
||||
-- allow dynamic code to access desync
|
||||
-- allow dynamic cond_code to access desync
|
||||
_G.desync = desync
|
||||
local res, v = pcall(_G[fname])
|
||||
_G.desync = nil
|
||||
@@ -477,10 +477,12 @@ function per_instance_condition(ctx, desync)
|
||||
if not instance then break end
|
||||
if instance.arg.cond then
|
||||
if type(_G[instance.arg.cond])~="function" then
|
||||
error(name..": invalid 'iff' function '"..instance.arg.cond.."'")
|
||||
error("per_instance_condition: invalid 'iff' function '"..instance.arg.cond.."'")
|
||||
end
|
||||
-- preapply exec plan to feed cond function correct args
|
||||
apply_execution_plan(desync, instance)
|
||||
if logical_xor(_G[instance.arg.cond](desync), instance.arg.cond_neg) then
|
||||
verdict = plan_instance_execute(desync, verdict, instance)
|
||||
verdict = plan_instance_execute_preapplied(desync, verdict, instance)
|
||||
else
|
||||
DLOG("per_instance_condition: condition not satisfied. skipping '"..instance.func_instance.."'")
|
||||
end
|
||||
|
||||
@@ -96,12 +96,12 @@ function detect_payload_str(ctx, desync)
|
||||
error("detect_payload_str: missing 'pattern'")
|
||||
end
|
||||
local data = desync.reasm_data or desync.dis.payload
|
||||
local b = string.find(data,desync.arg.pattern,1,true)
|
||||
local b = data and string.find(data,desync.arg.pattern,1,true)
|
||||
if b then
|
||||
DLOG("detect_payload_str: detected '"..desync.arg.payload.."'")
|
||||
DLOG("detect_payload_str: detected '"..(desync.arg.payload or '?').."'")
|
||||
if desync.arg.payload then desync.l7payload = desync.arg.payload end
|
||||
else
|
||||
DLOG("detect_payload_str: not detected '"..desync.arg.payload.."'")
|
||||
DLOG("detect_payload_str: not detected '"..(desync.arg.payload or '?').."'")
|
||||
if desync.arg.undetected then desync.l7payload = desync.arg.undetected end
|
||||
end
|
||||
end
|
||||
@@ -149,11 +149,13 @@ end
|
||||
|
||||
-- applies # and $ prefixes. #var means var length, %var means var value
|
||||
function apply_arg_prefix(desync)
|
||||
-- prevent double apply
|
||||
if desync.arg.__prefix_applied then return end
|
||||
for a,v in pairs(desync.arg) do
|
||||
local c = string.sub(v,1,1)
|
||||
if c=='#' then
|
||||
local blb = blob(desync,string.sub(v,2))
|
||||
desync.arg[a] = (type(blb)=='string' or type(blb)=='table') and #blb or 0
|
||||
desync.arg[a] = tostring(type(blb)=='string' and #blb or 0)
|
||||
elseif c=='%' then
|
||||
desync.arg[a] = blob(desync,string.sub(v,2))
|
||||
elseif c=='\\' then
|
||||
@@ -163,6 +165,7 @@ function apply_arg_prefix(desync)
|
||||
end
|
||||
end
|
||||
end
|
||||
desync.arg.__prefix_applied = true
|
||||
end
|
||||
-- copy instance identification and args from execution plan to desync table
|
||||
-- NOTE : to not lose VERDICT_MODIFY dissect changes pass original desync table
|
||||
@@ -173,7 +176,7 @@ function apply_execution_plan(desync, instance)
|
||||
desync.func_n = instance.func_n
|
||||
desync.func_instance = instance.func_instance
|
||||
desync.arg = deepcopy(instance.arg)
|
||||
apply_arg_prefix(desync)
|
||||
-- no apply_arg_prefix here because it may refer non-existing blobs
|
||||
end
|
||||
-- produce resulting verdict from 2 verdicts
|
||||
function verdict_aggregate(v1, v2)
|
||||
@@ -192,8 +195,7 @@ function verdict_aggregate(v1, v2)
|
||||
end
|
||||
return bitor(v,vn)
|
||||
end
|
||||
function plan_instance_execute(desync, verdict, instance)
|
||||
apply_execution_plan(desync, instance)
|
||||
function plan_instance_execute_preapplied(desync, verdict, instance)
|
||||
if cutoff_shim_check(desync) then
|
||||
DLOG("plan_instance_execute: not calling '"..desync.func_instance.."' because of voluntary cutoff")
|
||||
elseif not payload_match_filter(desync.l7payload, instance.payload_filter) then
|
||||
@@ -201,11 +203,18 @@ function plan_instance_execute(desync, verdict, instance)
|
||||
elseif not pos_check_range(desync, instance.range) then
|
||||
DLOG("plan_instance_execute: not calling '"..desync.func_instance.."' because pos "..pos_str(desync,instance.range.from).." "..pos_str(desync,instance.range.to).." is out of range '"..pos_range_str(instance.range).."'")
|
||||
else
|
||||
-- condition is satisfied. here blobs must be referenced
|
||||
apply_arg_prefix(desync)
|
||||
desync.arg.__prefix_applied = nil
|
||||
DLOG("plan_instance_execute: calling '"..desync.func_instance.."'")
|
||||
verdict = verdict_aggregate(verdict,_G[instance.func](nil, desync))
|
||||
end
|
||||
return verdict
|
||||
end
|
||||
function plan_instance_execute(desync, verdict, instance)
|
||||
apply_execution_plan(desync, instance)
|
||||
return plan_instance_execute_preapplied(desync,verdict,instance)
|
||||
end
|
||||
function plan_instance_pop(desync)
|
||||
return (desync.plan and #desync.plan>0) and table.remove(desync.plan, 1) or nil
|
||||
end
|
||||
@@ -334,9 +343,8 @@ end
|
||||
|
||||
-- convert array a to packed string using 'packer' function. only numeric indexes starting from 1, order preserved
|
||||
function barray(a, packer)
|
||||
local sa={}
|
||||
if a then
|
||||
local s=""
|
||||
local sa={}
|
||||
for i=1,#a do
|
||||
sa[i] = packer(a[i])
|
||||
end
|
||||
@@ -345,16 +353,16 @@ function barray(a, packer)
|
||||
end
|
||||
-- convert table a to packed string using 'packer' function. any indexes, any order
|
||||
function btable(a, packer)
|
||||
local sa={}
|
||||
if a then
|
||||
local s=""
|
||||
local sa={}
|
||||
local i=1
|
||||
for k,v in pairs(a) do
|
||||
sa[k] = packer(v)
|
||||
sa[i] = packer(v)
|
||||
i=i+1
|
||||
end
|
||||
return table.concat(sa)
|
||||
end
|
||||
end
|
||||
|
||||
-- sequence comparision functions. they work only within 2G interval
|
||||
-- seq1>=seq2
|
||||
function seq_ge(seq1, seq2)
|
||||
@@ -434,7 +442,7 @@ function string2hex(s)
|
||||
return ss
|
||||
end
|
||||
function has_nonprintable(s)
|
||||
return s:match("[^ -\\r\\n\\t]")
|
||||
return s:match("[^ -\r\n\t]")
|
||||
end
|
||||
function make_readable(v)
|
||||
if type(v)=="string" then
|
||||
@@ -545,6 +553,7 @@ function blob(desync, name, def)
|
||||
error("blob '"..name.."' unavailable")
|
||||
end
|
||||
end
|
||||
blob = tostring(blob)
|
||||
end
|
||||
return blob
|
||||
end
|
||||
@@ -629,7 +638,7 @@ function tls_mod_shim(desync, blob, modlist, payload)
|
||||
if not val then
|
||||
error("tls_mod_shim: non-existent var '"..var.."'")
|
||||
end
|
||||
modlist = string.sub(modlist,1,p1+3)..val..string.sub(modlist,p2+1)
|
||||
modlist = string.sub(modlist,1,p1+3)..tostring(val)..string.sub(modlist,p2+1)
|
||||
end
|
||||
return tls_mod(blob,modlist,payload)
|
||||
end
|
||||
@@ -641,7 +650,7 @@ function parse_tcp_flags(s)
|
||||
local s_upper = string.upper(s)
|
||||
for flag in string.gmatch(s_upper, "[^,]+") do
|
||||
if flags[flag] then
|
||||
f = bitor(f,flags[flag])
|
||||
f = bitor(f,flags[flag])
|
||||
else
|
||||
error("tcp flag '"..flag.."' is invalid")
|
||||
end
|
||||
@@ -805,9 +814,9 @@ function autottl(incoming_ttl, attl)
|
||||
|
||||
if incoming_ttl>223 then
|
||||
orig=255
|
||||
elseif incoming_ttl<128 and incoming_ttl>96 then
|
||||
elseif incoming_ttl<=128 and incoming_ttl>96 then
|
||||
orig=128
|
||||
elseif incoming_ttl<64 and incoming_ttl>32 then
|
||||
elseif incoming_ttl<=64 and incoming_ttl>32 then
|
||||
orig=64
|
||||
else
|
||||
return nil
|
||||
@@ -872,7 +881,11 @@ function apply_fooling(desync, dis, fooling_options)
|
||||
if type(desync.track.lua_state.autottl_cache)~="table" then desync.track.lua_state.autottl_cache={} end
|
||||
if type(desync.track.lua_state.autottl_cache[desync.func_instance])~="table" then desync.track.lua_state.autottl_cache[desync.func_instance]={} end
|
||||
if not desync.track.lua_state.autottl_cache[desync.func_instance].autottl_found then
|
||||
desync.track.lua_state.autottl_cache[desync.func_instance].autottl = autottl(desync.track.incoming_ttl,parse_autottl(arg_autottl))
|
||||
local attl = parse_autottl(arg_autottl)
|
||||
if not attl then
|
||||
error("apply_fooling: invalid autottl value '"..arg_autottl.."'")
|
||||
end
|
||||
desync.track.lua_state.autottl_cache[desync.func_instance].autottl = autottl(desync.track.incoming_ttl,attl)
|
||||
if desync.track.lua_state.autottl_cache[desync.func_instance].autottl then
|
||||
desync.track.lua_state.autottl_cache[desync.func_instance].autottl_found = true
|
||||
DLOG("apply_fooling: discovered autottl "..desync.track.lua_state.autottl_cache[desync.func_instance].autottl)
|
||||
@@ -887,8 +900,11 @@ function apply_fooling(desync, dis, fooling_options)
|
||||
DLOG("apply_fooling: cannot apply autottl because incoming ttl unknown")
|
||||
end
|
||||
end
|
||||
if not ttl and tonumber(arg_ttl) then
|
||||
if not ttl and arg_ttl then
|
||||
ttl = tonumber(arg_ttl)
|
||||
if not ttl or ttl<0 or ttl>255 then
|
||||
error("apply_fooling: ip_ttl and ip6_ttl require valid value")
|
||||
end
|
||||
end
|
||||
--io.stderr:write("TTL "..tostring(ttl).."\n")
|
||||
return ttl
|
||||
@@ -905,11 +921,19 @@ function apply_fooling(desync, dis, fooling_options)
|
||||
-- use current packet if dissect not given
|
||||
if not dis then dis = desync.dis end
|
||||
if dis.tcp then
|
||||
if tonumber(fooling_options.tcp_seq) then
|
||||
dis.tcp.th_seq = u32add(dis.tcp.th_seq, fooling_options.tcp_seq)
|
||||
if fooling_options.tcp_seq then
|
||||
if tonumber(fooling_options.tcp_seq) then
|
||||
dis.tcp.th_seq = u32add(dis.tcp.th_seq, fooling_options.tcp_seq)
|
||||
else
|
||||
error("apply_fooling: tcp_seq requires increment parameter. there's no default value.")
|
||||
end
|
||||
end
|
||||
if tonumber(fooling_options.tcp_ack) then
|
||||
dis.tcp.th_ack = u32add(dis.tcp.th_ack, fooling_options.tcp_ack)
|
||||
if fooling_options.tcp_ack then
|
||||
if tonumber(fooling_options.tcp_ack) then
|
||||
dis.tcp.th_ack = u32add(dis.tcp.th_ack, fooling_options.tcp_ack)
|
||||
else
|
||||
error("apply_fooling: tcp_ack requires increment parameter. there's no default value.")
|
||||
end
|
||||
end
|
||||
if fooling_options.tcp_flags_unset then
|
||||
dis.tcp.th_flags = bitand(dis.tcp.th_flags, bitnot(parse_tcp_flags(fooling_options.tcp_flags_unset)))
|
||||
@@ -924,12 +948,16 @@ function apply_fooling(desync, dis, fooling_options)
|
||||
end
|
||||
end
|
||||
end
|
||||
if tonumber(fooling_options.tcp_ts) then
|
||||
local idx = find_tcp_option(dis.tcp.options,TCP_KIND_TS)
|
||||
if idx and (dis.tcp.options[idx].data and #dis.tcp.options[idx].data or 0)==8 then
|
||||
dis.tcp.options[idx].data = bu32(u32add(u32(dis.tcp.options[idx].data),fooling_options.tcp_ts))..string.sub(dis.tcp.options[idx].data,5)
|
||||
if fooling_options.tcp_ts then
|
||||
if tonumber(fooling_options.tcp_ts) then
|
||||
local idx = find_tcp_option(dis.tcp.options,TCP_KIND_TS)
|
||||
if idx and (dis.tcp.options[idx].data and #dis.tcp.options[idx].data or 0)==8 then
|
||||
dis.tcp.options[idx].data = bu32(u32add(u32(dis.tcp.options[idx].data),fooling_options.tcp_ts))..string.sub(dis.tcp.options[idx].data,5)
|
||||
else
|
||||
DLOG("apply_fooling: timestamp tcp option not present or invalid")
|
||||
end
|
||||
else
|
||||
DLOG("apply_fooling: timestamp tcp option not present or invalid")
|
||||
error("apply_fooling: tcp_ts requires increment parameter. there's no default value.")
|
||||
end
|
||||
end
|
||||
if fooling_options.tcp_md5 then
|
||||
@@ -940,7 +968,7 @@ function apply_fooling(desync, dis, fooling_options)
|
||||
end
|
||||
end
|
||||
if fooling_options.tcp_ts_up then
|
||||
move_ts_top(dis.tcp.options)
|
||||
move_ts_top()
|
||||
end
|
||||
end
|
||||
if dis.ip6 then
|
||||
@@ -1161,16 +1189,15 @@ function rawsend_dissect_segmented(desync, dis, mss, options)
|
||||
local pos=1
|
||||
local len
|
||||
local payload=discopy.payload
|
||||
|
||||
while pos <= #payload do
|
||||
len = #payload - pos + 1
|
||||
if len > max_data then len = max_data end
|
||||
if oob then
|
||||
if urp>=pos and urp<(pos+len)then
|
||||
discopy.tcp.th_flags = bitor(dis.tcp.th_flags, TH_URG)
|
||||
discopy.tcp.th_flags = bitor(discopy.tcp.th_flags, TH_URG)
|
||||
discopy.tcp.th_urp = urp-pos+1
|
||||
else
|
||||
discopy.tcp.th_flags = bitand(dis.tcp.th_flags, bitnot(TH_URG))
|
||||
discopy.tcp.th_flags = bitand(discopy.tcp.th_flags, bitnot(TH_URG))
|
||||
discopy.tcp.th_urp = 0
|
||||
end
|
||||
end
|
||||
@@ -1180,7 +1207,7 @@ function rawsend_dissect_segmented(desync, dis, mss, options)
|
||||
-- stop if failed
|
||||
return false
|
||||
end
|
||||
discopy.tcp.th_seq = discopy.tcp.th_seq + len
|
||||
discopy.tcp.th_seq = u32add(discopy.tcp.th_seq, len)
|
||||
pos = pos + len
|
||||
end
|
||||
return true
|
||||
@@ -1545,11 +1572,11 @@ function tls_client_hello_mod(tls, options)
|
||||
table.insert(tdis.handshake[TLS_HANDSHAKE_TYPE_CLIENT].dis.ext[idx_sni].dis.list, { name = options.sni_last, type = options.sni_snt_new } )
|
||||
end
|
||||
end
|
||||
local tls = tls_reconstruct(tdis)
|
||||
if not tls then
|
||||
local rtls = tls_reconstruct(tdis)
|
||||
if not rtls then
|
||||
DLOG_ERR("tls_client_hello_mod: reconstruct error")
|
||||
end
|
||||
return tls
|
||||
return rtls
|
||||
end
|
||||
|
||||
-- checks if filename is gzip compressed
|
||||
@@ -1616,9 +1643,9 @@ function gzip_file(filename, data, expected_ratio, level, memlevel, compress_blo
|
||||
if not gz then
|
||||
error("gzip_file: stream init error")
|
||||
end
|
||||
local off=1, block_size
|
||||
local off=1
|
||||
repeat
|
||||
block_size = #data-off+1
|
||||
local block_size = #data-off+1
|
||||
if block_size>compress_block_size then block_size=compress_block_size end
|
||||
local comp, eof = gzip_deflate(gz, string.sub(data,off,off+block_size-1), block_size / expected_ratio)
|
||||
if not comp then
|
||||
@@ -1638,7 +1665,7 @@ function readfile(filename)
|
||||
if not f then
|
||||
error("readfile: "..err)
|
||||
end
|
||||
local s,err = f:read("*a")
|
||||
local s, err = f:read("*a")
|
||||
f:close()
|
||||
if err then
|
||||
error("readfile: "..err)
|
||||
@@ -1656,7 +1683,7 @@ function writefile(filename, data)
|
||||
if not f then
|
||||
error("writefile: "..err)
|
||||
end
|
||||
local s,err = f:write(data)
|
||||
local s, err = f:write(data)
|
||||
f:close()
|
||||
if not s then
|
||||
error("writefile: "..err)
|
||||
@@ -1676,7 +1703,7 @@ function http_dissect_header(header)
|
||||
end
|
||||
-- make table with structured http header representation
|
||||
function http_dissect_headers(http, pos)
|
||||
local eol,pnext,header,value,idx,headers,pos_endheader,pos_startvalue,pos_headers_end
|
||||
local eol,pnext,header,value,headers,pos_endheader,pos_startvalue,pos_headers_end
|
||||
headers={}
|
||||
while pos do
|
||||
eol,pnext = find_next_line(http,pos)
|
||||
@@ -2125,7 +2152,7 @@ function is_tls_record(tls, offset, ctype, partialOK)
|
||||
if not tls then return false end
|
||||
if not offset then offset=1 end
|
||||
|
||||
if (#tls-offset+1)<6 or (ctype and ctype~=tls_record_type(tls, offset)) then return false end
|
||||
if (#tls-offset+1)<5 or (ctype and ctype~=tls_record_type(tls, offset)) then return false end
|
||||
local f2 = u16(tls, offset+1)
|
||||
return f2>=TLS_VER_SSL30 and f2<=TLS_VER_TLS12 and (partialOK or tls_record_full(tls, offset))
|
||||
|
||||
@@ -2164,12 +2191,12 @@ function is_tls_handshake(tls, offset, htype, partialOK)
|
||||
if not TLS_HANDSHAKE_TYPE_NAMES[typ] then return false end
|
||||
if typ==TLS_HANDSHAKE_TYPE_CLIENT or typ==TLS_HANDSHAKE_TYPE_SERVER then
|
||||
-- valid tls versions
|
||||
if (#tls-offset+1)<6 then return false end
|
||||
local f2 = u16(tls,offset+4)
|
||||
if f2<TLS_VER_SSL30 or f2>TLS_VER_TLS12 then return false end
|
||||
end
|
||||
-- length fits to data buffer
|
||||
return partialOK or tls_handshake_full(tls, offset)
|
||||
|
||||
end
|
||||
function is_tls_hello(tls, offset, partialOK)
|
||||
return is_tls_handshake(tls, offset, TLS_HANDSHAKE_TYPE_CLIENT, partialOK) or is_tls_handshake(tls, offset, TLS_HANDSHAKE_TYPE_SERVER, partialOK)
|
||||
@@ -2240,7 +2267,8 @@ function tls_dissect_ext(ext)
|
||||
return left, off
|
||||
end
|
||||
|
||||
local dis={}, off, len, left
|
||||
local dis={}
|
||||
local off, len, left
|
||||
|
||||
ext.dis = nil
|
||||
|
||||
@@ -2448,6 +2476,11 @@ function tls_dissect(tls, offset, partialOK)
|
||||
if typ==TLS_RECORD_TYPE_CHANGE_CIPHER_SPEC then
|
||||
encrypted = true
|
||||
elseif typ==TLS_RECORD_TYPE_HANDSHAKE and not encrypted then
|
||||
-- need 4 bytes for handshake type and 24-bit length
|
||||
if (#tls-off+1)<9 then
|
||||
if not partialOK then return end
|
||||
break
|
||||
end
|
||||
local htyp = tls_handshake_type(tls, off + 5)
|
||||
tdis.rec[#tdis.rec].htype = htyp
|
||||
if not tdis.handshake then tdis.handshake = {} end
|
||||
@@ -2463,7 +2496,7 @@ function tls_dissect(tls, offset, partialOK)
|
||||
-- next record
|
||||
if not is_tls_record(tls, off + 5 + len, nil, partialOK) or tls_record_type(tls, off + 5 + len) ~= typ then
|
||||
if not partialOK then return end
|
||||
break
|
||||
goto endrec
|
||||
end
|
||||
off = off + 5 + len
|
||||
len = tls_record_data_len(tls, off)
|
||||
@@ -2473,14 +2506,15 @@ function tls_dissect(tls, offset, partialOK)
|
||||
-- next record
|
||||
off = off + 5 + len
|
||||
end
|
||||
::endrec::
|
||||
|
||||
if tdis.handshake then
|
||||
for htyp, handshake in pairs(tdis.handshake) do
|
||||
if (handshake.type == TLS_HANDSHAKE_TYPE_CLIENT or handshake.type == TLS_HANDSHAKE_TYPE_SERVER) then
|
||||
tls_dissect_handshake(handshake, 1, partialOK)
|
||||
tls_dissect_handshake(handshake, partialOK)
|
||||
end
|
||||
end
|
||||
elseif is_tls_handshake(tls, offset, nil, partialOK) then
|
||||
elseif not tdis.rec and is_tls_handshake(tls, offset, nil, partialOK) then
|
||||
local htyp = tls_handshake_type(tls, offset)
|
||||
tdis.handshake = { [htyp] = { type = htyp, name = TLS_HANDSHAKE_TYPE_NAMES[htyp], data = string.sub(tls, offset, #tls) } }
|
||||
tls_dissect_handshake(tdis.handshake[htyp], partialOK)
|
||||
|
||||
@@ -175,7 +175,12 @@ end
|
||||
-- arg : server=[0|1] - override server mode. by default use "--server" nfqws2 parameter
|
||||
function udp2icmp(ctx, desync)
|
||||
local dataxor
|
||||
local bserver = desync.arg.server and (desync.arg.server~="0") or b_server
|
||||
local bserver
|
||||
if desync.arg.server then
|
||||
bserver = desync.arg.server~="0"
|
||||
else
|
||||
bserver = b_server
|
||||
end
|
||||
|
||||
local function one_byte_arg(name)
|
||||
if desync.arg[name] then
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
function pcap_write_header(file)
|
||||
-- big endian, nanoseconds in timestamps, ver 2.4, max packet size - 0x4000 (16384), 0x65 - l3 packets without l2
|
||||
file:write("\xA1\xB2\x3C\x4D\x00\x02\x00\x04\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x40\x00\x00\x00\x00\x65")
|
||||
-- big endian, nanoseconds in timestamps, ver 2.4, max packet size - 0xFFFF (65535), 0x65 - l3 packets without l2
|
||||
file:write("\xA1\xB2\x3C\x4D\x00\x02\x00\x04\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\x00\x00\x00\x65")
|
||||
end
|
||||
function pcap_write_packet(file, raw)
|
||||
local sec, nsec = clock_gettime();
|
||||
@@ -34,6 +34,7 @@ function pcap(ctx, desync)
|
||||
if not f then
|
||||
error("pcap: could not write to '".._G[fn_cache_name].."'")
|
||||
end
|
||||
pcap_write(f, raw_packet(ctx))
|
||||
local raw = ctx and raw_packet(ctx) or reconstruct_dissect(desync.dis)
|
||||
pcap_write(f, raw)
|
||||
f:close()
|
||||
end
|
||||
|
||||
@@ -90,10 +90,9 @@ function test_hkdf()
|
||||
local ikm = brandom(math.random(5,10))
|
||||
for ninfo=1,nblob do
|
||||
local info = brandom(math.random(5,10))
|
||||
local okm_prev
|
||||
for k,sha in pairs({"sha256","sha224"}) do
|
||||
for k,okml in pairs({8, 16, 50}) do
|
||||
local okm_prev
|
||||
for k,okml in pairs({8, 16, 50}) do
|
||||
local okm
|
||||
print("* hkdf "..sha)
|
||||
print("salt: "..string2hex(salt))
|
||||
@@ -107,7 +106,6 @@ function test_hkdf()
|
||||
print("duplicate okm !")
|
||||
end
|
||||
okms[okm] = true
|
||||
|
||||
test_assert(not okm_prev or okm_prev==string.sub(okm, 1, #okm_prev))
|
||||
okm_prev = okm
|
||||
end
|
||||
@@ -121,7 +119,7 @@ function test_aes()
|
||||
print("* aes")
|
||||
|
||||
local clear_text="test "..brandom_az09(11)
|
||||
local iv, key, encrypted, decrypted
|
||||
local encrypted, decrypted
|
||||
|
||||
for key_size=16,32,8 do
|
||||
local key = brandom(key_size)
|
||||
@@ -509,7 +507,7 @@ end
|
||||
function test_dissect()
|
||||
print("* dissect")
|
||||
|
||||
local dis, raw1, raw2
|
||||
local raw1, raw2
|
||||
|
||||
for i=1,20 do
|
||||
print("* dissect test "..tostring(i))
|
||||
@@ -613,7 +611,7 @@ function test_dissect()
|
||||
},
|
||||
payload = brandom(math.random(0, 20))
|
||||
}
|
||||
|
||||
|
||||
raw1 = reconstruct_dissect(ip6_udp)
|
||||
print("IP6+UDP : "..string2hex(raw1))
|
||||
dis1 = dissect(raw1)
|
||||
@@ -774,11 +772,6 @@ function test_csum()
|
||||
uh_ulen = UDP_BASE_LEN + #payload
|
||||
}
|
||||
|
||||
ip.ip_p = IPPROTO_UDP
|
||||
ip4b = reconstruct_iphdr(ip)
|
||||
ip6.ip6_plen = packet_len({ip6=ip6,udp=udp,payload=payload}) - IP6_BASE_LEN
|
||||
ip6b = reconstruct_ip6hdr(ip6, {ip6_last_proto=IPPROTO_UDP})
|
||||
|
||||
udpb = reconstruct_udphdr(udp)
|
||||
raw = bu16(udp.uh_sport) ..
|
||||
bu16(udp.uh_dport) ..
|
||||
@@ -787,8 +780,10 @@ function test_csum()
|
||||
print( raw==udpb and "UDP RECONSTRUCT OK" or "UDP RECONSTRUCT FAILED" )
|
||||
test_assert(raw==udpb)
|
||||
|
||||
ip.ip_p = IPPROTO_UDP
|
||||
raw = reconstruct_dissect({ip=ip, udp=udp, payload=payload})
|
||||
dis1 = dissect(raw)
|
||||
ip.ip_p = IPPROTO_UDP
|
||||
ip.ip_len = IP_BASE_LEN + #ip.options + #udpb + #payload
|
||||
ip4b = reconstruct_iphdr(ip)
|
||||
udpb = csum_udp_fix(ip4b,udpb,payload)
|
||||
@@ -796,6 +791,8 @@ function test_csum()
|
||||
print( dis1.udp.uh_sum==dis2.udp.uh_sum and "UDP+IP4 CSUM OK" or "UDP+IP4 CSUM FAILED" )
|
||||
test_assert(dis1.udp.uh_sum==dis2.udp.uh_sum)
|
||||
|
||||
ip6.ip6_plen = packet_len({ip6=ip6,udp=udp,payload=payload}) - IP6_BASE_LEN
|
||||
ip6b = reconstruct_ip6hdr(ip6, {ip6_last_proto=IPPROTO_UDP})
|
||||
raw = reconstruct_dissect({ip6=ip6, udp=udp, payload=payload})
|
||||
dis1 = dissect(raw)
|
||||
udpb = csum_udp_fix(ip6b,udpb,payload)
|
||||
@@ -951,7 +948,6 @@ function test_rawsend(opts)
|
||||
end
|
||||
local ip, ip6, udp, dis, ddis, raw_ip, raw_udp, raw
|
||||
local payload = brandom(math.random(100,1200))
|
||||
local b
|
||||
|
||||
local target
|
||||
for ifname,ifinfo in pairs(get_ifaddrs()) do
|
||||
@@ -999,7 +995,6 @@ function test_rawsend(opts)
|
||||
print("send ipv4 udp using pure rawsend without dissect")
|
||||
test_assert(rawsend_print(raw, {repeats=5}))
|
||||
|
||||
local target
|
||||
for ifname,ifinfo in pairs(get_ifaddrs()) do
|
||||
for k,v in pairs(ifinfo.addr) do
|
||||
if #v.addr==16 and (string.sub(v.addr,1,1)=="\xFC" or string.sub(v.addr,1,1)=="\xFD") then
|
||||
@@ -1085,7 +1080,7 @@ function test_rawsend(opts)
|
||||
print("send ipv6 icmp")
|
||||
test_assert(rawsend_dissect_print(dis, {fwmark = 0x8E10, repeats=3}))
|
||||
|
||||
local ip2 = {
|
||||
ip2 = {
|
||||
ip_tos = 0,
|
||||
ip_id = math.random(0,0xFFFF),
|
||||
ip_off = 0,
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
CC ?= cc
|
||||
OPTIMIZE ?= -Os
|
||||
CFLAGS += -std=gnu99 $(OPTIMIZE)
|
||||
CFLAGS_PIC = -fPIC
|
||||
CFLAGS += -std=gnu99 $(OPTIMIZE) $(CFLAGS_PIC)
|
||||
CFLAGS_BSD = -Wno-address-of-packed-member
|
||||
CFLAGS_WIN = -static
|
||||
LDFLAGS_PIE = -pie
|
||||
LDFLAGS += $(LDFLAGS_PIE)
|
||||
LIBS = -lpthread
|
||||
LIBS_ANDROID =
|
||||
LIBS_WIN = -lws2_32
|
||||
|
||||
@@ -1,7 +1,12 @@
|
||||
CC ?= cc
|
||||
PKG_CONFIG ?= pkg-config
|
||||
OPTIMIZE ?= -Os
|
||||
CFLAGS += -std=gnu99 -s $(OPTIMIZE) -flto=auto -Wno-address-of-packed-member
|
||||
OPTIMIZE ?= -Oz
|
||||
MINSIZE ?= -flto=auto -ffunction-sections -fdata-sections
|
||||
STRIPP = -s
|
||||
CFLAGS_PIC = -fPIC
|
||||
CFLAGS += -std=gnu99 $(OPTIMIZE) $(MINSIZE) $(CFLAGS_PIC) -Wno-address-of-packed-member
|
||||
LDFLAGS_PIE = -pie
|
||||
LDFLAGS += -flto=auto -Wl,--gc-sections $(LDFLAGS_PIE)
|
||||
LIBS = -lz -lm
|
||||
SRC_FILES = *.c crypto/*.c
|
||||
|
||||
@@ -37,7 +42,7 @@ LUA_CFLAGS+=-DLUAJIT
|
||||
all: dvtws2
|
||||
|
||||
dvtws2: $(SRC_FILES)
|
||||
$(CC) $(CFLAGS) $(LUA_CFLAGS) -o dvtws2 $(SRC_FILES) $(LIBS) $(LUA_LIB) $(LDFLAGS)
|
||||
$(CC) $(STRIPP) $(CFLAGS) $(LUA_CFLAGS) -o dvtws2 $(SRC_FILES) $(LIBS) $(LUA_LIB) $(LDFLAGS)
|
||||
|
||||
clean:
|
||||
rm -f dvtws2
|
||||
|
||||
@@ -1,13 +1,21 @@
|
||||
CC ?= cc
|
||||
PKG_CONFIG ?= pkg-config
|
||||
OPTIMIZE ?= -Os
|
||||
CFLAGS += -std=gnu99 $(OPTIMIZE) -flto=auto
|
||||
CFLAGS_LINUX = -Wno-alloc-size-larger-than
|
||||
MINSIZE ?= -flto=auto -ffunction-sections -fdata-sections
|
||||
CFLAGS += -std=gnu99 $(OPTIMIZE) $(MINSIZE)
|
||||
CFLAGS_PIC = -fPIC
|
||||
CFLAGS_LINUX = -Wno-alloc-size-larger-than $(CFLAGS_PIC)
|
||||
CFLAGS_SYSTEMD = -DUSE_SYSTEMD
|
||||
CFLAGS_BSD = -Wno-address-of-packed-member
|
||||
CFLAGS_CYGWIN = -Wno-address-of-packed-member -static
|
||||
CFLAGS_BSD = -Wno-address-of-packed-member $(CFLAGS_PIC)
|
||||
CFLAGS_CYGWIN = -Wno-address-of-packed-member -static -Wl,--nxcompat
|
||||
CFLAGS_CYGWIN32 =
|
||||
CFLAGS_CYGWIN64 = -Wl,--dynamicbase -Wl,--high-entropy-va
|
||||
CFLAGS_UBSAN = -fsanitize=undefined,alignment -fno-sanitize-recover=undefined,alignment
|
||||
LDFLAGS_PIE = -pie
|
||||
LDFLAGS += -flto=auto -Wl,--gc-sections $(LDFLAGS_PIE)
|
||||
LDFLAGS_ANDROID = -llog
|
||||
LDFLAGS_CYGWIN = -Wl,--build-id=none
|
||||
STRIPP=-s
|
||||
LIBS =
|
||||
LIBS_LINUX = -lz -lnetfilter_queue -lnfnetlink -lmnl -lm
|
||||
LIBS_SYSTEMD = -lsystemd
|
||||
@@ -27,6 +35,7 @@ ifeq ($(LUA_JIT),1)
|
||||
LUAJIT_VER?=2.1
|
||||
LUAJIT_LUA_VER?=5.1
|
||||
LUA_PKG:=luajit
|
||||
CFLAGS_CYGWIN32 = -msse2 -mfpmath=sse
|
||||
|
||||
$(info trying luajit $(LUAJIT_VER) lua $(LUAJIT_LUA_VER))
|
||||
|
||||
@@ -134,24 +143,24 @@ LUA_CFL += $(LUA_CFLAGS)
|
||||
all: nfqws2
|
||||
|
||||
nfqws2: $(SRC_FILES)
|
||||
$(CC) -s $(CFLAGS) $(LUA_CFL) $(CFLAGS_LINUX) -o nfqws2 $(SRC_FILES) $(LIBS) $(LUA_LIB) $(LIBS_LINUX) $(LDFLAGS)
|
||||
$(CC) $(STRIPP) $(CFLAGS) $(LUA_CFL) $(CFLAGS_LINUX) -o nfqws2 $(SRC_FILES) $(LIBS) $(LUA_LIB) $(LIBS_LINUX) $(LDFLAGS)
|
||||
|
||||
ubsan: $(SRC_FILES)
|
||||
$(CC) $(CFLAGS_UBSAN) $(CFLAGS) $(LUA_CFL) $(CFLAGS_LINUX) -o nfqws2 $(SRC_FILES) $(LIBS) $(LUA_LIB) $(LIBS_LINUX) $(LDFLAGS)
|
||||
|
||||
systemd: $(SRC_FILES)
|
||||
$(CC) -s $(CFLAGS) $(LUA_CFL) $(CFLAGS_LINUX) $(CFLAGS_SYSTEMD) -o nfqws2 $(SRC_FILES) $(LIBS) $(LUA_LIB) $(LIBS_LINUX) $(LIBS_SYSTEMD) $(LDFLAGS)
|
||||
$(CC) $(STRIPP) $(CFLAGS) $(LUA_CFL) $(CFLAGS_LINUX) $(CFLAGS_SYSTEMD) -o nfqws2 $(SRC_FILES) $(LIBS) $(LUA_LIB) $(LIBS_LINUX) $(LIBS_SYSTEMD) $(LDFLAGS)
|
||||
|
||||
android: $(SRC_FILES_ANDROID)
|
||||
$(CC) -s $(CFLAGS) $(LUA_CFL) -o nfqws2 $(SRC_FILES_ANDROID) $(LIBS) $(LUA_LIB) $(LIBS_LINUX) $(LDFLAGS) $(LDFLAGS_ANDROID)
|
||||
$(CC) $(STRIPP) $(CFLAGS) $(LUA_CFL) -o nfqws2 $(SRC_FILES_ANDROID) $(LIBS) $(LUA_LIB) $(LIBS_LINUX) $(LDFLAGS) $(LDFLAGS_ANDROID)
|
||||
|
||||
bsd: $(SRC_FILES)
|
||||
$(CC) -s $(CFLAGS) $(LUA_CFL) $(CFLAGS_BSD) -o dvtws2 $(SRC_FILES) $(LIBS) $(LUA_LIB) $(LIBS_BSD) $(LDFLAGS)
|
||||
$(CC) $(STRIPP) $(CFLAGS) $(LUA_CFL) $(CFLAGS_BSD) -o dvtws2 $(SRC_FILES) $(LIBS) $(LUA_LIB) $(LIBS_BSD) $(LDFLAGS)
|
||||
|
||||
cygwin64:
|
||||
$(CC) -s $(CFLAGS) $(LUA_CFL) $(CFLAGS_CYGWIN) -o winws2 $(SRC_FILES) $(LIBS) $(LUA_LIB) $(LIBS_CYGWIN) $(LIBS_CYGWIN64) $(RES_CYGWIN64) $(LDFLAGS)
|
||||
$(CC) $(STRIPP) $(CFLAGS) $(LUA_CFL) $(CFLAGS_CYGWIN) $(CFLAGS_CYGWIN64) -o winws2 $(SRC_FILES) $(RES_CYGWIN64) $(LIBS) $(LUA_LIB) $(LIBS_CYGWIN) $(LIBS_CYGWIN64) $(LDFLAGS) $(LDFLAGS_CYGWIN)
|
||||
cygwin32:
|
||||
$(CC) -s $(CFLAGS) $(LUA_CFL) $(CFLAGS_CYGWIN) -o winws2 $(SRC_FILES) $(LIBS) $(LUA_LIB) $(LIBS_CYGWIN) $(LIBS_CYGWIN32) $(RES_CYGWIN32) $(LDFLAGS)
|
||||
$(CC) $(STRIPP) $(CFLAGS) $(LUA_CFL) $(CFLAGS_CYGWIN) $(CFLAGS_CYGWIN32) -o winws2 $(SRC_FILES) $(RES_CYGWIN32) $(LIBS) $(LUA_LIB) $(LIBS_CYGWIN) $(LIBS_CYGWIN32) $(LDFLAGS) $(LDFLAGS_CYGWIN)
|
||||
cygwin: cygwin64
|
||||
|
||||
clean:
|
||||
|
||||
@@ -140,8 +140,17 @@ static void ConntrackApplyPos(t_ctrack *t, bool bReverse, const struct dissect *
|
||||
|
||||
if (dis->ip6) direct->ip6flow = ntohl(dis->ip6->ip6_ctlun.ip6_un1.ip6_un1_flow);
|
||||
|
||||
scale = tcp_find_scale_factor(dis->tcp);
|
||||
mss = tcp_find_mss(dis->tcp);
|
||||
direct->winsize_calc = direct->winsize = ntohs(dis->tcp->th_win);
|
||||
if (t->pos.state == SYN)
|
||||
{
|
||||
// scale and mss only valid in syn packets
|
||||
scale = tcp_find_scale_factor(dis->tcp);
|
||||
if (scale != SCALE_NONE) direct->scale = scale;
|
||||
direct->mss = tcp_find_mss(dis->tcp);
|
||||
}
|
||||
else
|
||||
// apply scale only outside of the SYN stage
|
||||
direct->winsize_calc <<= direct->scale;
|
||||
|
||||
direct->seq_last = ntohl(dis->tcp->th_seq);
|
||||
direct->pos = direct->seq_last + dis->len_payload;
|
||||
@@ -154,10 +163,6 @@ static void ConntrackApplyPos(t_ctrack *t, bool bReverse, const struct dissect *
|
||||
if (!((direct->pos - direct->uppos) & 0x80000000))
|
||||
direct->uppos = direct->pos;
|
||||
}
|
||||
direct->winsize_calc = direct->winsize = ntohs(dis->tcp->th_win);
|
||||
if (scale != SCALE_NONE) direct->scale = scale;
|
||||
if (direct->scale != SCALE_NONE) direct->winsize_calc <<= direct->scale;
|
||||
if (mss && !direct->mss) direct->mss = mss;
|
||||
|
||||
if (!direct->rseq_over_2G && ((direct->seq_last - direct->seq0) & 0x80000000))
|
||||
direct->rseq_over_2G = true;
|
||||
@@ -167,9 +172,6 @@ static void ConntrackApplyPos(t_ctrack *t, bool bReverse, const struct dissect *
|
||||
|
||||
static void ConntrackFeedPacket(t_ctrack *t, bool bReverse, const struct dissect *dis)
|
||||
{
|
||||
uint8_t scale;
|
||||
uint16_t mss;
|
||||
|
||||
if (bReverse)
|
||||
{
|
||||
t->pos.server.pcounter++;
|
||||
@@ -283,7 +285,7 @@ static bool ConntrackPoolFeedPool(t_conntrack_pool **pp, const struct dissect *d
|
||||
}
|
||||
return false;
|
||||
ok:
|
||||
ctr->track.ipproto = proto;
|
||||
ctr->track.pos.ipproto = proto;
|
||||
if (ctrack) *ctrack = &ctr->track;
|
||||
if (bReverse) *bReverse = b_rev;
|
||||
return true;
|
||||
@@ -347,7 +349,7 @@ void ConntrackPoolDump(const t_conntrack *p)
|
||||
{
|
||||
t_conntrack_pool *t, *tmp;
|
||||
time_t tnow;
|
||||
char sa1[40], sa2[40];
|
||||
char sa1[INET6_ADDRSTRLEN], sa2[INET6_ADDRSTRLEN];
|
||||
|
||||
if (!(tnow=boottime())) return;
|
||||
HASH_ITER(hh, p->pool, t, tmp) {
|
||||
@@ -365,8 +367,8 @@ void ConntrackPoolDump(const t_conntrack *p)
|
||||
t->track.pos.client.seq0, t->track.pos.client.seq_last - t->track.pos.client.seq0, t->track.pos.client.pos - t->track.pos.client.seq0,
|
||||
t->track.pos.server.seq0, t->track.pos.server.seq_last - t->track.pos.server.seq0, t->track.pos.server.pos - t->track.pos.server.seq0,
|
||||
t->track.pos.client.mss, t->track.pos.server.mss,
|
||||
t->track.pos.client.winsize, t->track.pos.client.scale == SCALE_NONE ? -1 : t->track.pos.client.scale,
|
||||
t->track.pos.server.winsize, t->track.pos.server.scale == SCALE_NONE ? -1 : t->track.pos.server.scale);
|
||||
t->track.pos.client.winsize, t->track.pos.client.scale,
|
||||
t->track.pos.server.winsize, t->track.pos.server.scale);
|
||||
else
|
||||
printf("rseq=%u client.pos=%u rack=%u server.pos=%u",
|
||||
t->track.pos.client.seq_last, t->track.pos.client.pos,
|
||||
|
||||
@@ -53,7 +53,6 @@ typedef struct {
|
||||
typedef struct
|
||||
{
|
||||
bool bCheckDone, bCheckResult, bCheckExcluded; // hostlist check result cache
|
||||
uint8_t ipproto;
|
||||
|
||||
struct timespec t_start;
|
||||
|
||||
|
||||
@@ -21,15 +21,15 @@ typedef struct
|
||||
uint32_t ip6flow;
|
||||
|
||||
// tcp only state, not used in udp
|
||||
uint32_t pos; // TCP: seq_last+payload, ack_last+payload UDP: sum of all seen payload lenghts including current
|
||||
uint32_t pos; // seq_last+payload, ack_last+payload
|
||||
uint32_t uppos; // max seen position. useful to detect retransmissions
|
||||
uint32_t uppos_prev; // previous max seen position. useful to detect retransmissions
|
||||
uint32_t seq_last; // TCP: last seen seq and ack UDP: sum of all seen payload lenghts NOT including current
|
||||
uint32_t seq_last; // last seen seq and ack
|
||||
uint32_t seq0; // starting seq and ack
|
||||
uint16_t winsize; // last seen window size
|
||||
uint16_t mss;
|
||||
uint32_t winsize_calc; // calculated window size
|
||||
uint8_t scale; // last seen window scale factor. SCALE_NONE if none
|
||||
uint8_t scale; // last seen window scale factor
|
||||
bool rseq_over_2G;
|
||||
} t_ctrack_position;
|
||||
|
||||
@@ -38,5 +38,6 @@ typedef struct
|
||||
struct timespec t_last;
|
||||
t_connstate state;
|
||||
t_ctrack_position client, server;
|
||||
uint8_t ipproto;
|
||||
}
|
||||
t_ctrack_positions;
|
||||
|
||||
@@ -258,8 +258,6 @@ int gcm_start(gcm_context *ctx, // pointer to user-provided GCM context
|
||||
size_t use_len; // byte count to process, up to 16 bytes
|
||||
size_t i; // local loop iterator
|
||||
|
||||
if (iv_len!=12) return -1;
|
||||
|
||||
// since the context might be reused under the same key
|
||||
// we zero the working buffers for this next new process
|
||||
memset(ctx->y, 0x00, sizeof(ctx->y));
|
||||
@@ -447,7 +445,7 @@ int gcm_crypt_and_tag(
|
||||
prepare the gcm context with the keying material, we simply
|
||||
invoke each of the three GCM sub-functions in turn...
|
||||
*/
|
||||
if (iv_len!=12 || tag_len>16) return -1;
|
||||
if (tag_len>16) return -1;
|
||||
|
||||
int ret;
|
||||
if ((ret=gcm_start(ctx, mode, iv, iv_len, add, add_len))) return ret;
|
||||
@@ -483,26 +481,28 @@ int gcm_auth_decrypt(
|
||||
uchar check_tag[16]; // the tag generated and returned by decryption
|
||||
int diff; // an ORed flag to detect authentication errors
|
||||
size_t i; // our local iterator
|
||||
int ret;
|
||||
|
||||
if (iv_len!=12 || tag_len>16) return -1;
|
||||
if (tag_len>16) return -1;
|
||||
|
||||
/*
|
||||
we use GCM_DECRYPT_AND_TAG (above) to perform our decryption
|
||||
(which is an identical XORing to reverse the previous one)
|
||||
and also to re-generate the matching authentication tag
|
||||
*/
|
||||
gcm_crypt_and_tag(ctx, AES_DECRYPT, iv, iv_len, add, add_len,
|
||||
input, output, length, check_tag, tag_len);
|
||||
if ((ret = gcm_crypt_and_tag(ctx, AES_DECRYPT, iv, iv_len, add, add_len, input, output, length, check_tag, tag_len))) return ret;
|
||||
|
||||
// now we verify the authentication tag in 'constant time'
|
||||
for (diff = 0, i = 0; i < tag_len; i++)
|
||||
diff |= tag[i] ^ check_tag[i];
|
||||
|
||||
if (diff != 0) { // see whether any bits differed?
|
||||
if (diff)
|
||||
{
|
||||
// see whether any bits differed?
|
||||
memset(output, 0, length); // if so... wipe the output data
|
||||
return(GCM_AUTH_FAILURE); // return GCM_AUTH_FAILURE
|
||||
}
|
||||
return(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
|
||||
@@ -29,7 +29,6 @@
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#include <basetsd.h>
|
||||
typedef unsigned int size_t;// use the right type for length declarations
|
||||
typedef UINT32 uint32_t;
|
||||
typedef UINT64 uint64_t;
|
||||
#else
|
||||
|
||||
@@ -60,9 +60,9 @@ int hkdf(SHAversion whichSha,
|
||||
uint8_t okm[], size_t okm_len)
|
||||
{
|
||||
uint8_t prk[USHAMaxHashSize];
|
||||
return hkdfExtract(whichSha, salt, salt_len, ikm, ikm_len, prk) ||
|
||||
hkdfExpand(whichSha, prk, USHAHashSize(whichSha), info,
|
||||
info_len, okm, okm_len);
|
||||
int ret;
|
||||
if ((ret=hkdfExtract(whichSha, salt, salt_len, ikm, ikm_len, prk))) return ret;
|
||||
return hkdfExpand(whichSha, prk, USHAHashSize(whichSha), info, info_len, okm, okm_len);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -146,6 +146,7 @@ int hkdfExpand(SHAversion whichSha, const uint8_t prk[], size_t prk_len,
|
||||
size_t hash_len, N;
|
||||
unsigned char T[USHAMaxHashSize];
|
||||
size_t Tlen, where, i;
|
||||
int ret;
|
||||
|
||||
if (info == 0) {
|
||||
info = (const unsigned char *)"";
|
||||
@@ -164,12 +165,11 @@ int hkdfExpand(SHAversion whichSha, const uint8_t prk[], size_t prk_len,
|
||||
for (i = 1; i <= N; i++) {
|
||||
HMACContext context;
|
||||
unsigned char c = i;
|
||||
int ret = hmacReset(&context, whichSha, prk, prk_len) ||
|
||||
hmacInput(&context, T, Tlen) ||
|
||||
hmacInput(&context, info, info_len) ||
|
||||
hmacInput(&context, &c, 1) ||
|
||||
hmacResult(&context, T);
|
||||
if (ret != shaSuccess) return ret;
|
||||
if ((ret=hmacReset(&context, whichSha, prk, prk_len))) return ret;
|
||||
if ((ret=hmacInput(&context, T, Tlen))) return ret;
|
||||
if ((ret=hmacInput(&context, info, info_len))) return ret;
|
||||
if ((ret=hmacInput(&context, &c, 1))) return ret;
|
||||
if ((ret=hmacResult(&context, T))) return ret;
|
||||
memcpy(okm + where, T,
|
||||
(i != N) ? hash_len : (okm_len - where));
|
||||
where += hash_len;
|
||||
@@ -321,9 +321,8 @@ int hkdfResult(HKDFContext *context,
|
||||
if (!okm) return context->Corrupted = shaBadParam;
|
||||
if (!prk) prk = prkbuf;
|
||||
|
||||
ret = hmacResult(&context->hmacContext, prk) ||
|
||||
hkdfExpand(context->whichSha, prk, context->hashSize, info,
|
||||
info_len, okm, okm_len);
|
||||
if (!(ret = hmacResult(&context->hmacContext, prk)))
|
||||
ret = hkdfExpand(context->whichSha, prk, context->hashSize, info, info_len, okm, okm_len);
|
||||
context->Computed = 1;
|
||||
return context->Corrupted = ret;
|
||||
}
|
||||
|
||||
@@ -49,9 +49,10 @@ int hmac(SHAversion whichSha,
|
||||
uint8_t digest[USHAMaxHashSize])
|
||||
{
|
||||
HMACContext context;
|
||||
return hmacReset(&context, whichSha, key, key_len) ||
|
||||
hmacInput(&context, message_array, length) ||
|
||||
hmacResult(&context, digest);
|
||||
int ret;
|
||||
if ((ret=hmacReset(&context, whichSha, key, key_len))) return ret;
|
||||
if ((ret=hmacInput(&context, message_array, length))) return ret;
|
||||
return hmacResult(&context, digest);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -101,10 +102,8 @@ int hmacReset(HMACContext *context, enum SHAversion whichSha,
|
||||
*/
|
||||
if (key_len > blocksize) {
|
||||
USHAContext tcontext;
|
||||
int err = USHAReset(&tcontext, whichSha) ||
|
||||
USHAInput(&tcontext, key, key_len) ||
|
||||
USHAResult(&tcontext, tempkey);
|
||||
if (err != shaSuccess) return err;
|
||||
if ((ret=USHAReset(&tcontext, whichSha)) || (ret=USHAInput(&tcontext, key, key_len)) || (ret=USHAResult(&tcontext, tempkey)))
|
||||
return ret;
|
||||
|
||||
key = tempkey;
|
||||
key_len = hashsize;
|
||||
@@ -134,9 +133,9 @@ int hmacReset(HMACContext *context, enum SHAversion whichSha,
|
||||
|
||||
/* perform inner hash */
|
||||
/* init context for 1st pass */
|
||||
ret = USHAReset(&context->shaContext, whichSha) ||
|
||||
if (!(ret = USHAReset(&context->shaContext, whichSha)))
|
||||
/* and start with inner pad */
|
||||
USHAInput(&context->shaContext, k_ipad, blocksize);
|
||||
ret = USHAInput(&context->shaContext, k_ipad, blocksize);
|
||||
return context->Corrupted = ret;
|
||||
}
|
||||
|
||||
@@ -197,8 +196,7 @@ int hmacFinalBits(HMACContext *context,
|
||||
if (context->Corrupted) return context->Corrupted;
|
||||
if (context->Computed) return context->Corrupted = shaStateError;
|
||||
/* then final bits of datagram */
|
||||
return context->Corrupted =
|
||||
USHAFinalBits(&context->shaContext, bits, bit_count);
|
||||
return context->Corrupted = USHAFinalBits(&context->shaContext, bits, bit_count);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -229,21 +227,16 @@ int hmacResult(HMACContext *context, uint8_t *digest)
|
||||
|
||||
/* finish up 1st pass */
|
||||
/* (Use digest here as a temporary buffer.) */
|
||||
ret =
|
||||
USHAResult(&context->shaContext, digest) ||
|
||||
|
||||
if (!(ret=USHAResult(&context->shaContext, digest)) &&
|
||||
/* perform outer SHA */
|
||||
/* init context for 2nd pass */
|
||||
USHAReset(&context->shaContext, context->whichSha) ||
|
||||
|
||||
!(ret=USHAReset(&context->shaContext, context->whichSha)) &&
|
||||
/* start with outer pad */
|
||||
USHAInput(&context->shaContext, context->k_opad,
|
||||
context->blockSize) ||
|
||||
|
||||
!(ret=USHAInput(&context->shaContext, context->k_opad, context->blockSize)) &&
|
||||
/* then results of 1st hash */
|
||||
USHAInput(&context->shaContext, digest, context->hashSize) ||
|
||||
!(ret=USHAInput(&context->shaContext, digest, context->hashSize)))
|
||||
/* finish up 2nd pass */
|
||||
USHAResult(&context->shaContext, digest);
|
||||
ret=USHAResult(&context->shaContext, digest);
|
||||
|
||||
context->Computed = 1;
|
||||
return context->Corrupted = ret;
|
||||
|
||||
185
nfq2/darkmagic.c
185
nfq2/darkmagic.c
@@ -48,7 +48,7 @@ uint32_t net32_add(uint32_t netorder_value, uint32_t cpuorder_increment)
|
||||
{
|
||||
return htonl(ntohl(netorder_value)+cpuorder_increment);
|
||||
}
|
||||
uint32_t net16_add(uint16_t netorder_value, uint16_t cpuorder_increment)
|
||||
uint16_t net16_add(uint16_t netorder_value, uint16_t cpuorder_increment)
|
||||
{
|
||||
return htons(ntohs(netorder_value)+cpuorder_increment);
|
||||
}
|
||||
@@ -229,7 +229,7 @@ uint16_t family_from_proto(uint8_t l3proto)
|
||||
{
|
||||
case IPPROTO_IP: return AF_INET;
|
||||
case IPPROTO_IPV6: return AF_INET6;
|
||||
default: return -1;
|
||||
default: return AF_UNSPEC;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -285,7 +285,7 @@ void str_icmp_type_name(char *s, size_t s_len, bool v6, uint8_t type)
|
||||
|
||||
static void str_srcdst_ip(char *s, size_t s_len, const void *saddr,const void *daddr)
|
||||
{
|
||||
char s_ip[16],d_ip[16];
|
||||
char s_ip[INET_ADDRSTRLEN],d_ip[INET_ADDRSTRLEN];
|
||||
*s_ip=*d_ip=0;
|
||||
inet_ntop(AF_INET, saddr, s_ip, sizeof(s_ip));
|
||||
inet_ntop(AF_INET, daddr, d_ip, sizeof(d_ip));
|
||||
@@ -306,7 +306,7 @@ void print_ip(const struct ip *ip)
|
||||
}
|
||||
void str_srcdst_ip6(char *s, size_t s_len, const void *saddr,const void *daddr)
|
||||
{
|
||||
char s_ip[40],d_ip[40];
|
||||
char s_ip[INET6_ADDRSTRLEN],d_ip[INET6_ADDRSTRLEN];
|
||||
*s_ip=*d_ip=0;
|
||||
inet_ntop(AF_INET6, saddr, s_ip, sizeof(s_ip));
|
||||
inet_ntop(AF_INET6, daddr, d_ip, sizeof(d_ip));
|
||||
@@ -314,14 +314,14 @@ void str_srcdst_ip6(char *s, size_t s_len, const void *saddr,const void *daddr)
|
||||
}
|
||||
void str_ip6hdr(char *s, size_t s_len, const struct ip6_hdr *ip6hdr, uint8_t proto)
|
||||
{
|
||||
char ss[83],s_proto[16];
|
||||
char ss[100],s_proto[16];
|
||||
str_srcdst_ip6(ss,sizeof(ss),&ip6hdr->ip6_src,&ip6hdr->ip6_dst);
|
||||
str_proto_name(s_proto,sizeof(s_proto),proto);
|
||||
snprintf(s,s_len,"%s proto=%s ttl=%u",ss,s_proto,ip6hdr->ip6_hlim);
|
||||
}
|
||||
void print_ip6hdr(const struct ip6_hdr *ip6hdr, uint8_t proto)
|
||||
{
|
||||
char s[128];
|
||||
char s[132];
|
||||
str_ip6hdr(s,sizeof(s),ip6hdr,proto);
|
||||
printf("%s",s);
|
||||
}
|
||||
@@ -335,7 +335,7 @@ void str_tcphdr(char *s, size_t s_len, const struct tcphdr *tcphdr)
|
||||
if (tcphdr->th_flags & TH_PUSH) *f++='P';
|
||||
if (tcphdr->th_flags & TH_URG) *f++='U';
|
||||
*f=0;
|
||||
snprintf(s,s_len,"sport=%u dport=%u flags=%s seq=%u ack_seq=%u",htons(tcphdr->th_sport),htons(tcphdr->th_dport),flags,htonl(tcphdr->th_seq),htonl(tcphdr->th_ack));
|
||||
snprintf(s,s_len,"sport=%u dport=%u flags=%s seq=%u ack_seq=%u",ntohs(tcphdr->th_sport),ntohs(tcphdr->th_dport),flags,ntohl(tcphdr->th_seq),ntohl(tcphdr->th_ack));
|
||||
}
|
||||
void print_tcphdr(const struct tcphdr *tcphdr)
|
||||
{
|
||||
@@ -345,7 +345,7 @@ void print_tcphdr(const struct tcphdr *tcphdr)
|
||||
}
|
||||
void str_udphdr(char *s, size_t s_len, const struct udphdr *udphdr)
|
||||
{
|
||||
snprintf(s,s_len,"sport=%u dport=%u",htons(udphdr->uh_sport),htons(udphdr->uh_dport));
|
||||
snprintf(s,s_len,"sport=%u dport=%u",ntohs(udphdr->uh_sport),ntohs(udphdr->uh_dport));
|
||||
}
|
||||
void print_udphdr(const struct udphdr *udphdr)
|
||||
{
|
||||
@@ -504,7 +504,7 @@ uint8_t *proto_find_ip6_exthdr(struct ip6_hdr *ip6, size_t len, uint8_t proto)
|
||||
bool fr=false;
|
||||
uint16_t fr_off=0;
|
||||
|
||||
if (len<sizeof(struct ip6_hdr)) return false;
|
||||
if (len<sizeof(struct ip6_hdr)) return NULL;
|
||||
plen = ntohs(ip6->ip6_ctlun.ip6_un1.ip6_un1_plen);
|
||||
last_proto = ip6->ip6_ctlun.ip6_un1.ip6_un1_nxt;
|
||||
data = (uint8_t*)(ip6+1);
|
||||
@@ -521,18 +521,18 @@ uint8_t *proto_find_ip6_exthdr(struct ip6_hdr *ip6, size_t len, uint8_t proto)
|
||||
case IPPROTO_MH: // mobility header
|
||||
case IPPROTO_HIP: // Host Identity Protocol Version v2
|
||||
case IPPROTO_SHIM6:
|
||||
if (len < 2) return false; // error
|
||||
if (len < 2) return NULL; // error
|
||||
hdrlen = 8 + (data[1] << 3);
|
||||
break;
|
||||
case IPPROTO_FRAGMENT: // fragment. length fixed to 8, hdrlen field defined as reserved
|
||||
hdrlen = 8;
|
||||
if (len < hdrlen) return false; // error
|
||||
if (len < hdrlen) return NULL; // error
|
||||
fr_off = ntohs(((struct ip6_frag*)data)->ip6f_offlg & IP6F_OFF_MASK);
|
||||
fr = ((struct ip6_frag*)data)->ip6f_offlg & (IP6F_OFF_MASK|IP6F_MORE_FRAG);
|
||||
break;
|
||||
case IPPROTO_AH:
|
||||
// special case. length in ah header is in 32-bit words minus 2
|
||||
if (len < 2) return false; // error
|
||||
if (len < 2) return NULL; // error
|
||||
hdrlen = 8 + (data[1] << 2);
|
||||
break;
|
||||
default:
|
||||
@@ -540,7 +540,7 @@ uint8_t *proto_find_ip6_exthdr(struct ip6_hdr *ip6, size_t len, uint8_t proto)
|
||||
// exthdr was not found
|
||||
return NULL;
|
||||
}
|
||||
if (len < hdrlen) return false; // error
|
||||
if (len < hdrlen) return NULL; // error
|
||||
last_proto = *data;
|
||||
len -= hdrlen; data += hdrlen;
|
||||
}
|
||||
@@ -557,11 +557,15 @@ void proto_dissect_l3l4(const uint8_t *data, size_t len, struct dissect *dis, bo
|
||||
dis->data_pkt = data;
|
||||
dis->len_pkt = len;
|
||||
|
||||
uint16_t iplen;
|
||||
|
||||
if (proto_check_ipv4(data, len) && (no_payload_check || proto_check_ipv4_payload(data, len)))
|
||||
{
|
||||
dis->ip = (const struct ip *) data;
|
||||
dis->proto = dis->ip->ip_p;
|
||||
p = data;
|
||||
iplen = ntohs(((struct ip*)data)->ip_len);
|
||||
if (iplen<len) dis->len_pkt = len = iplen;
|
||||
proto_skip_ipv4(&data, &len, &dis->frag, &dis->frag_off);
|
||||
dis->len_l3 = data-p;
|
||||
}
|
||||
@@ -569,6 +573,8 @@ void proto_dissect_l3l4(const uint8_t *data, size_t len, struct dissect *dis, bo
|
||||
{
|
||||
dis->ip6 = (const struct ip6_hdr *) data;
|
||||
p = data;
|
||||
iplen = ntohs(((struct ip6_hdr*)data)->ip6_ctlun.ip6_un1.ip6_un1_plen) + sizeof(struct ip6_hdr);
|
||||
if (iplen<len) dis->len_pkt = len = iplen;
|
||||
proto_skip_ipv6(&data, &len, &dis->proto, &dis->frag, &dis->frag_off);
|
||||
dis->len_l3 = data-p;
|
||||
}
|
||||
@@ -797,8 +803,8 @@ static BOOL RemoveTokenPrivs(void)
|
||||
if (memcmp(&privs->Privileges[k].Luid, &luid_SeChangeNotifyPrivilege, sizeof(LUID)))
|
||||
privs->Privileges[k].Attributes = SE_PRIVILEGE_REMOVED;
|
||||
}
|
||||
bRes = AdjustTokenPrivileges(hToken, FALSE, privs, dwSize, NULL, NULL);
|
||||
}
|
||||
bRes = AdjustTokenPrivileges(hToken, FALSE, privs, dwSize, NULL, NULL);
|
||||
free(privs);
|
||||
}
|
||||
}
|
||||
@@ -922,11 +928,29 @@ BOOL SetMandatoryLabelObject(HANDLE h, SE_OBJECT_TYPE ObjType, DWORD dwMandatory
|
||||
|
||||
bool ensure_file_access(const char *filename)
|
||||
{
|
||||
return SetMandatoryLabelFile(filename, SECURITY_MANDATORY_LOW_RID, 0);
|
||||
bool b=false;
|
||||
size_t l = cygwin_conv_path(CCP_POSIX_TO_WIN_W | CCP_ABSOLUTE, filename, NULL, 0);
|
||||
WCHAR *wfilename = (WCHAR*)malloc(l);
|
||||
if (wfilename)
|
||||
{
|
||||
if (!cygwin_conv_path(CCP_POSIX_TO_WIN_W | CCP_ABSOLUTE, filename, wfilename, l))
|
||||
b = SetMandatoryLabelFileW(wfilename, SECURITY_MANDATORY_LOW_RID, 0);
|
||||
free(wfilename);
|
||||
}
|
||||
return b;
|
||||
}
|
||||
bool ensure_dir_access(const char *dir)
|
||||
{
|
||||
return SetMandatoryLabelFile(dir, SECURITY_MANDATORY_LOW_RID, OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE);
|
||||
bool b=false;
|
||||
size_t l = cygwin_conv_path(CCP_POSIX_TO_WIN_W | CCP_ABSOLUTE, dir, NULL, 0);
|
||||
WCHAR *wdir = (WCHAR*)malloc(l);
|
||||
if (wdir)
|
||||
{
|
||||
if (!cygwin_conv_path(CCP_POSIX_TO_WIN_W | CCP_ABSOLUTE, dir, wdir, l))
|
||||
b=SetMandatoryLabelFileW(wdir, SECURITY_MANDATORY_LOW_RID, OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE);
|
||||
free(wdir);
|
||||
}
|
||||
return b;
|
||||
}
|
||||
|
||||
bool prepare_low_appdata()
|
||||
@@ -1557,7 +1581,6 @@ void rawsend_cleanup(void)
|
||||
{
|
||||
if (w_filter)
|
||||
{
|
||||
CancelIoEx(w_filter,&ovl);
|
||||
WinDivertClose(w_filter);
|
||||
w_filter=NULL;
|
||||
}
|
||||
@@ -1585,71 +1608,71 @@ bool windivert_init(const char *filter)
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool windivert_recv_filter(HANDLE hFilter, uint8_t *packet, size_t *len, WINDIVERT_ADDRESS *wa, unsigned int *wa_count)
|
||||
static bool windivert_recv_exit(void)
|
||||
{
|
||||
UINT recv_len;
|
||||
DWORD err;
|
||||
DWORD rd;
|
||||
char c;
|
||||
sigset_t pending;
|
||||
|
||||
// make signals working
|
||||
usleep(0);
|
||||
|
||||
if (bQuit)
|
||||
{
|
||||
errno=EINTR;
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
if (!logical_net_filter_match_rate_limited())
|
||||
{
|
||||
errno=ENODEV;
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
usleep(0);
|
||||
return false;
|
||||
}
|
||||
static bool windivert_recv_filter(HANDLE hFilter, uint8_t *packet, size_t *len, WINDIVERT_ADDRESS *wa, unsigned int *wa_count)
|
||||
{
|
||||
UINT recv_len;
|
||||
DWORD rd;
|
||||
unsigned int wac;
|
||||
|
||||
*wa_count *= sizeof(WINDIVERT_ADDRESS);
|
||||
if (WinDivertRecvEx(hFilter, packet, *len, &recv_len, 0, wa, wa_count, &ovl))
|
||||
if (windivert_recv_exit()) return false;
|
||||
|
||||
wac = *wa_count * sizeof(WINDIVERT_ADDRESS);
|
||||
if (WinDivertRecvEx(hFilter, packet, *len, &recv_len, 0, wa, &wac, &ovl))
|
||||
{
|
||||
*wa_count /= sizeof(WINDIVERT_ADDRESS);
|
||||
*wa_count = wac/sizeof(WINDIVERT_ADDRESS);
|
||||
*len = recv_len;
|
||||
return true;
|
||||
}
|
||||
|
||||
for(;;)
|
||||
w_win32_error = GetLastError();
|
||||
switch(w_win32_error)
|
||||
{
|
||||
w_win32_error = GetLastError();
|
||||
|
||||
switch(w_win32_error)
|
||||
{
|
||||
case ERROR_IO_PENDING:
|
||||
// make signals working
|
||||
while (WaitForSingleObject(ovl.hEvent,50)==WAIT_TIMEOUT)
|
||||
{
|
||||
if (bQuit)
|
||||
{
|
||||
errno=EINTR;
|
||||
return false;
|
||||
}
|
||||
if (!logical_net_filter_match_rate_limited())
|
||||
{
|
||||
errno=ENODEV;
|
||||
return false;
|
||||
}
|
||||
usleep(0);
|
||||
}
|
||||
if (!GetOverlappedResult(hFilter,&ovl,&rd,TRUE))
|
||||
continue;
|
||||
*wa_count /= sizeof(WINDIVERT_ADDRESS);
|
||||
*len = rd;
|
||||
return true;
|
||||
case ERROR_INSUFFICIENT_BUFFER:
|
||||
errno = ENOBUFS;
|
||||
break;
|
||||
case ERROR_NO_DATA:
|
||||
errno = ESHUTDOWN;
|
||||
break;
|
||||
default:
|
||||
errno = EIO;
|
||||
}
|
||||
break;
|
||||
case ERROR_IO_PENDING:
|
||||
// make signals working
|
||||
while (WaitForSingleObject(ovl.hEvent,50)==WAIT_TIMEOUT)
|
||||
{
|
||||
if (windivert_recv_exit()) return false;
|
||||
}
|
||||
if (!GetOverlappedResult(hFilter,&ovl,&rd,FALSE))
|
||||
{
|
||||
errno=EIO;
|
||||
goto cancel;
|
||||
}
|
||||
*wa_count = wac/sizeof(WINDIVERT_ADDRESS);
|
||||
*len = rd;
|
||||
return true;
|
||||
case ERROR_INSUFFICIENT_BUFFER:
|
||||
errno = ENOBUFS;
|
||||
break;
|
||||
case ERROR_NO_DATA:
|
||||
errno = ESHUTDOWN;
|
||||
break;
|
||||
default:
|
||||
errno = EIO;
|
||||
}
|
||||
cancel:
|
||||
// make sure no pending operations
|
||||
CancelIoEx(w_filter,&ovl);
|
||||
GetOverlappedResult(hFilter, &ovl, &rd, TRUE);
|
||||
return false;
|
||||
}
|
||||
bool windivert_recv(uint8_t *packet, size_t *len, WINDIVERT_ADDRESS *wa, unsigned int *wa_count)
|
||||
@@ -1797,7 +1820,7 @@ static int rawsend_sendto_divert(sa_family_t family, int sock, const void *buf,
|
||||
char s[64];
|
||||
snprintf(s,sizeof(s),"rawsend_sendto_divert: sendto (%zu)",len);
|
||||
DLOG_PERROR(s);
|
||||
return false;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return wr;
|
||||
@@ -1881,8 +1904,9 @@ static int rawsend_socket(sa_family_t family)
|
||||
}
|
||||
if (family==AF_INET && setsockopt(*sock, IPPROTO_IP, IP_NODEFRAG, &yes, sizeof(yes)) == -1)
|
||||
{
|
||||
// since 2.6.36
|
||||
DLOG_PERROR("rawsend: setsockopt(IP_NODEFRAG)");
|
||||
goto exiterr;
|
||||
//goto exiterr;
|
||||
}
|
||||
if (family==AF_INET && setsockopt(*sock, IPPROTO_IP, IP_FREEBIND, &yes, sizeof(yes)) == -1)
|
||||
{
|
||||
@@ -2075,6 +2099,7 @@ static uint16_t wlan_get_family_id(struct mnl_socket* nl)
|
||||
static int wlan_info_attr_cb(const struct nlattr *attr, void *data)
|
||||
{
|
||||
struct wlan_interface *wlan = (struct wlan_interface *)data;
|
||||
size_t len;
|
||||
switch(mnl_attr_get_type(attr))
|
||||
{
|
||||
case NL80211_ATTR_IFINDEX:
|
||||
@@ -2086,12 +2111,10 @@ static int wlan_info_attr_cb(const struct nlattr *attr, void *data)
|
||||
wlan->ifindex = mnl_attr_get_u32(attr);
|
||||
break;
|
||||
case NL80211_ATTR_SSID:
|
||||
if (mnl_attr_validate(attr, MNL_TYPE_STRING) < 0)
|
||||
{
|
||||
DLOG_PERROR("mnl_attr_validate(ssid)");
|
||||
return MNL_CB_ERROR;
|
||||
}
|
||||
snprintf(wlan->ssid,sizeof(wlan->ssid),"%s",mnl_attr_get_str(attr));
|
||||
len = mnl_attr_get_payload_len(attr);
|
||||
if (len>=sizeof(wlan->ssid)) len=sizeof(wlan->ssid)-1;
|
||||
memcpy(wlan->ssid, mnl_attr_get_payload(attr), len);
|
||||
wlan->ssid[len]=0;
|
||||
break;
|
||||
case NL80211_ATTR_IFNAME:
|
||||
if (mnl_attr_validate(attr, MNL_TYPE_STRING) < 0)
|
||||
@@ -2137,8 +2160,8 @@ static uint8_t *find_ie(uint8_t *buf, size_t len, uint8_t ie)
|
||||
{
|
||||
if (len<(2+buf[1])) break;
|
||||
if (buf[0]==ie) return buf;
|
||||
buf+=buf[1]+2;
|
||||
len-=buf[1]+2;
|
||||
buf+=buf[1]+2;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
@@ -2221,6 +2244,7 @@ static bool scan_info(struct mnl_socket* nl, uint16_t wlan_family_id, struct wla
|
||||
// wlan_info does not return ssid since kernel 5.19
|
||||
// it's used to enumerate all wifi interfaces then call scan_info on each
|
||||
if (!wlan_info(nl, wlan_family_id, &wc_all, false)) return false;
|
||||
w->count=0;
|
||||
for(int i=0;i<wc_all.count;i++)
|
||||
if (!netlink_genl_simple_transact(nl, wlan_family_id, NLM_F_REQUEST | NLM_F_ACK | NLM_F_DUMP, NL80211_CMD_GET_SCAN, 0, scan_prepare, (void*)&wc_all.wlan[i].ifindex, scan_info_cb, w))
|
||||
return false;
|
||||
@@ -2434,20 +2458,11 @@ bool make_writeable_dir()
|
||||
if (mkdir(wrdir,0755) && errno!=EEXIST)
|
||||
return false;
|
||||
|
||||
bool b = false;
|
||||
bool b;
|
||||
#ifdef __CYGWIN__
|
||||
size_t l = cygwin_conv_path(CCP_POSIX_TO_WIN_W | CCP_ABSOLUTE, wrdir, NULL, 0);
|
||||
WCHAR *wwrdir = (WCHAR*)malloc(l);
|
||||
if (wwrdir)
|
||||
{
|
||||
if (!cygwin_conv_path(CCP_POSIX_TO_WIN_W | CCP_ABSOLUTE, wrdir, wwrdir, l))
|
||||
b = SetMandatoryLabelFileW(wwrdir, SECURITY_MANDATORY_LOW_RID, OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE);
|
||||
free(wwrdir);
|
||||
}
|
||||
b = ensure_dir_access(wrdir);
|
||||
#else
|
||||
if (ensure_dir_access(wrdir))
|
||||
b = true;
|
||||
else
|
||||
if (!(b=ensure_dir_access(wrdir)))
|
||||
{
|
||||
// could not chown. may be still accessible ?
|
||||
char testfile[PATH_MAX];
|
||||
|
||||
@@ -94,7 +94,7 @@
|
||||
|
||||
// returns netorder value
|
||||
uint32_t net32_add(uint32_t netorder_value, uint32_t cpuorder_increment);
|
||||
uint32_t net16_add(uint16_t netorder_value, uint16_t cpuorder_increment);
|
||||
uint16_t net16_add(uint16_t netorder_value, uint16_t cpuorder_increment);
|
||||
|
||||
#define SCALE_NONE ((uint8_t)-1)
|
||||
|
||||
|
||||
169
nfq2/desync.c
169
nfq2/desync.c
@@ -289,11 +289,11 @@ static struct desync_profile *dp_find(
|
||||
struct desync_profile_list *dpl;
|
||||
if (params.debug)
|
||||
{
|
||||
char s[40];
|
||||
char s[INET6_ADDRSTRLEN];
|
||||
ntopa46(ip, ip6, s, sizeof(s));
|
||||
if (ipr || ipr6)
|
||||
{
|
||||
char sr[40];
|
||||
char sr[INET6_ADDRSTRLEN];
|
||||
ntopa46(ipr, ipr6, sr, sizeof(sr));
|
||||
DLOG("desync profile search for %s ip1=%s ip2=%s port=%u icmp=%u:%u l7proto=%s ssid='%s' hostname='%s'\n",
|
||||
proto_name(l3proto), s, sr, port, icmp_type, icmp_code, l7proto_str(l7proto), ssid ? ssid : "", hostname ? hostname : "");
|
||||
@@ -556,7 +556,7 @@ static bool reasm_client_start(t_ctrack *ctrack, uint8_t proto, size_t sz, size_
|
||||
// server gave us too small tcp window
|
||||
// client will not send all pieces of reasm
|
||||
// if we drop packets and wait for next pieces we will see nothing but retransmissions
|
||||
DLOG("reasm cancelled because server window size %u is smaller than expected reasm size %u\n", ctrack->pos.server.winsize_calc, sz);
|
||||
DLOG("reasm cancelled because server window size %u is smaller than expected reasm size %zu\n", ctrack->pos.server.winsize_calc, sz);
|
||||
return false;
|
||||
}
|
||||
return reasm_start(ctrack, &ctrack->reasm_client, proto, (proto == IPPROTO_TCP) ? ctrack->pos.client.seq_last : 0, sz, szMax, data_payload, len_payload);
|
||||
@@ -737,7 +737,7 @@ static bool ipcache_get_hostname(const struct in_addr *a4, const struct in6_addr
|
||||
}
|
||||
if (params.debug)
|
||||
{
|
||||
char s[40];
|
||||
char s[INET6_ADDRSTRLEN];
|
||||
ntopa46(a4, a6, s, sizeof(s));
|
||||
DLOG("ipcache hostname search for %s\n", s);
|
||||
}
|
||||
@@ -746,7 +746,7 @@ static bool ipcache_get_hostname(const struct in_addr *a4, const struct in6_addr
|
||||
{
|
||||
if (params.debug)
|
||||
{
|
||||
char s[40];
|
||||
char s[INET6_ADDRSTRLEN];
|
||||
ntopa46(a4, a6, s, sizeof(s));
|
||||
DLOG("got cached hostname for %s : %s (is_ip=%u)\n", s, ipc->hostname, ipc->hostname_is_ip);
|
||||
}
|
||||
@@ -1137,7 +1137,7 @@ static void setup_direction(
|
||||
|
||||
if (params.debug)
|
||||
{
|
||||
char ip[40];
|
||||
char ip[INET6_ADDRSTRLEN];
|
||||
ntopa46(*sdip4, *sdip6, ip, sizeof(ip));
|
||||
DLOG("%s mode desync profile/ipcache search target ip=%s port=%u\n", params.server ? "server" : "client", ip, *sdport);
|
||||
}
|
||||
@@ -1574,20 +1574,21 @@ static uint8_t dpi_desync_tcp_packet_play(
|
||||
if (!bReqFull && ReasmIsEmpty(&ps.ctrack->reasm_client) && !is_retransmission(&ps.ctrack->pos.client))
|
||||
{
|
||||
// do not reconstruct unexpected large payload (they are feeding garbage ?)
|
||||
// also do not reconstruct if server window size is low
|
||||
if (!reasm_client_start(ps.ctrack, IPPROTO_TCP, TLSRecordLen(dis->data_payload), TCP_MAX_REASM, dis->data_payload, dis->len_payload))
|
||||
goto pass_reasm_cancel;
|
||||
goto rediscover;
|
||||
}
|
||||
|
||||
if (!ReasmIsEmpty(&ps.ctrack->reasm_client))
|
||||
{
|
||||
if (rawpacket_queue(&ps.ctrack->delayed, &ps.dst, fwmark, desync_fwmark, ifin, ifout, dis->data_pkt, dis->len_pkt, dis->len_payload, &ps.ctrack->pos))
|
||||
if (rawpacket_queue(&ps.ctrack->delayed, &ps.dst, fwmark, desync_fwmark, ifin, ifout, dis->data_pkt, dis->len_pkt, dis->len_payload, &ps.ctrack->pos, false))
|
||||
{
|
||||
DLOG("DELAY desync until reasm is complete (#%u)\n", rawpacket_queue_count(&ps.ctrack->delayed));
|
||||
}
|
||||
else
|
||||
{
|
||||
DLOG_ERR("rawpacket_queue failed !\n");
|
||||
goto pass_reasm_cancel;
|
||||
goto rediscover;
|
||||
}
|
||||
if (ReasmIsFull(&ps.ctrack->reasm_client))
|
||||
{
|
||||
@@ -1601,6 +1602,8 @@ static uint8_t dpi_desync_tcp_packet_play(
|
||||
}
|
||||
}
|
||||
|
||||
// UNSOLVED: if reasm is cancelled all packets except the last are passed as is without lua desync
|
||||
rediscover:
|
||||
if (!dp_rediscovery(&ps))
|
||||
goto pass_reasm_cancel;
|
||||
|
||||
@@ -1645,8 +1648,12 @@ static const uint8_t *dns_extract_name(const uint8_t *a, const uint8_t *b, const
|
||||
{
|
||||
size_t nl, off;
|
||||
const uint8_t *p;
|
||||
bool bptr = (*a & 0xC0)==0xC0;
|
||||
bool bptr;
|
||||
uint8_t x,y;
|
||||
|
||||
if (!name_size) return NULL;
|
||||
|
||||
bptr = (*a & 0xC0)==0xC0;
|
||||
if (bptr)
|
||||
{
|
||||
if (a+1>=e) return NULL;
|
||||
@@ -1661,66 +1668,115 @@ static const uint8_t *dns_extract_name(const uint8_t *a, const uint8_t *b, const
|
||||
if (p>=e) return NULL;
|
||||
for (nl=0; *p ;)
|
||||
{
|
||||
if ((p+*p+1)>=e || (*p+1)>=(name_size-nl)) return NULL;
|
||||
if (nl) name[nl++] = '.';
|
||||
memcpy(name + nl, p + 1, *p);
|
||||
nl += *p;
|
||||
p += *p + 1;
|
||||
if (nl)
|
||||
{
|
||||
if (nl>=name_size) return NULL;
|
||||
name[nl++] = '.';
|
||||
}
|
||||
// do not support mixed ptr+real
|
||||
if ((*p & 0xC0) || (p+*p+1)>=e || (*p+1)>=(name_size-nl)) return NULL;
|
||||
for(y=*p++,x=0 ; x<y ; x++,p++) name[nl+x] = tolower(*p);
|
||||
nl += y;
|
||||
}
|
||||
if (nl>=name_size) return NULL;
|
||||
name[nl] = 0;
|
||||
return bptr ? a+2 : p+1;
|
||||
}
|
||||
static bool dns_skip_name(const uint8_t **a, size_t *len)
|
||||
{
|
||||
// 11 higher bits indicate pointer
|
||||
// lazy skip name. mixed compressed/uncompressed names are supported
|
||||
for(;;)
|
||||
{
|
||||
if (*len<2) return false;
|
||||
if ((**a & 0xC0)==0xC0)
|
||||
{
|
||||
// pointer is the end
|
||||
(*a)+=2; (*len)-=2;
|
||||
break;
|
||||
}
|
||||
if (!**a)
|
||||
{
|
||||
// zero length is the end
|
||||
(*a)++; (*len)--;
|
||||
break;
|
||||
}
|
||||
if (*len<(**a+1)) return false;
|
||||
*len-=**a+1;
|
||||
*a+=**a+1;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool feed_dns_response(const uint8_t *a, size_t len)
|
||||
{
|
||||
if (!params.cache_hostname) return true;
|
||||
|
||||
// check of minimum header length and response flag
|
||||
uint16_t k, off, dlen, qcount = a[4]<<8 | a[5], acount = a[6]<<8 | a[7];
|
||||
char s_ip[40];
|
||||
uint16_t k, typ, off, dlen, qcount = a[4]<<8 | a[5], acount = a[6]<<8 | a[7];
|
||||
char s_ip[INET6_ADDRSTRLEN];
|
||||
const uint8_t *b = a, *p;
|
||||
const uint8_t *e = b + len;
|
||||
size_t nl;
|
||||
char name[256] = "";
|
||||
|
||||
if (len<12 || !(a[2]&0x80)) return false;
|
||||
a+=12; len-=12;
|
||||
for(k=0;k<qcount;k++)
|
||||
if (!qcount || len<12 || !(a[2]&0x80)) return false;
|
||||
if (!acount)
|
||||
{
|
||||
DLOG("skipping DNS response without answer\n");
|
||||
return false;
|
||||
}
|
||||
a+=12; len-=12;
|
||||
for(k=0,*name = 0 ; k<qcount ; k++)
|
||||
{
|
||||
if (*name) return false; // we do not support multiple queries with names
|
||||
// remember original query name
|
||||
if (!(p = dns_extract_name(a, b, e, name, sizeof(name)))) return false;
|
||||
len -= p-a;
|
||||
if ((len<4) || p[2] || p[3]!=1) return false;
|
||||
typ = pntoh16(p);
|
||||
// must be A or AAAA query. others are not interesting
|
||||
if ((len<4) || p[0] || p[1]!=1 && p[1]!=28 || p[2] || p[3]!=1) return false;
|
||||
if (typ!=1 && typ!=28)
|
||||
{
|
||||
DLOG("skipping DNS query type %u for '%s'\n", typ, name);
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
DLOG("DNS query type %u for '%s'\n", typ, name);
|
||||
}
|
||||
// skip type, class
|
||||
a=p+4; len-=4;
|
||||
}
|
||||
if (!*name) return false;
|
||||
for(k=0;k<acount;k++)
|
||||
{
|
||||
// 11 higher bits indicate pointer
|
||||
if (len<12 || (*a & 0xC0)!=0xC0) return false;
|
||||
|
||||
dlen = a[10]<<8 | a[11];
|
||||
if (len<(dlen+12)) return false;
|
||||
if (a[4]==0 && a[5]==1 && a[2]==0) // IN class and higher byte of type = 0
|
||||
if (!dns_skip_name(&a,&len)) return false;
|
||||
if (len<10) return false;
|
||||
dlen = a[8]<<8 | a[9];
|
||||
if (len<(dlen+10)) return false;
|
||||
if (a[2]==0 && a[3]==1) // IN class
|
||||
{
|
||||
switch(a[3])
|
||||
typ = pntoh16(a);
|
||||
switch(typ)
|
||||
{
|
||||
case 1: // A
|
||||
if (dlen!=4) break;
|
||||
if (params.debug && inet_ntop(AF_INET, a+12, s_ip, sizeof(s_ip)))
|
||||
DLOG("DNS response : %s\n", s_ip);
|
||||
ipcache_put_hostname((struct in_addr *)(a+12), NULL, name, false);
|
||||
if (params.debug && inet_ntop(AF_INET, a+10, s_ip, sizeof(s_ip)))
|
||||
DLOG("DNS response type %u : %s\n", typ, s_ip);
|
||||
ipcache_put_hostname((struct in_addr *)(a+10), NULL, name, false);
|
||||
break;
|
||||
case 28: // AAAA
|
||||
if (dlen!=16) break;
|
||||
if (params.debug && inet_ntop(AF_INET6, a+12, s_ip, sizeof(s_ip)))
|
||||
DLOG("DNS response : %s\n", s_ip);
|
||||
ipcache_put_hostname(NULL, (struct in6_addr *)(a+12), name, false);
|
||||
if (params.debug && inet_ntop(AF_INET6, a+10, s_ip, sizeof(s_ip)))
|
||||
DLOG("DNS response type %u : %s\n", typ, s_ip);
|
||||
ipcache_put_hostname(NULL, (struct in6_addr *)(a+10), name, false);
|
||||
break;
|
||||
default:
|
||||
DLOG("skipping DNS response type %u\n", typ);
|
||||
}
|
||||
}
|
||||
len -= 12+dlen; a += 12+dlen;
|
||||
len -= 10+dlen; a += 10+dlen;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -1778,7 +1834,7 @@ static uint8_t dpi_desync_udp_packet_play(
|
||||
else
|
||||
{
|
||||
DLOG("QUIC reasm is too long. cancelling.\n");
|
||||
goto pass_reasm_cancel;
|
||||
goto rediscover_cancel;
|
||||
}
|
||||
}
|
||||
size_t hello_offset, hello_len, defrag_len = sizeof(defrag);
|
||||
@@ -1802,18 +1858,18 @@ static uint8_t dpi_desync_udp_packet_play(
|
||||
{
|
||||
// preallocate max buffer to avoid reallocs that cause memory copy
|
||||
if (!reasm_client_start(ps.ctrack, IPPROTO_UDP, UDP_MAX_REASM, UDP_MAX_REASM, clean, clean_len))
|
||||
goto pass_reasm_cancel;
|
||||
goto rediscover_cancel;
|
||||
}
|
||||
if (!ReasmIsEmpty(&ps.ctrack->reasm_client))
|
||||
{
|
||||
if (rawpacket_queue(&ps.ctrack->delayed, &ps.dst, fwmark, desync_fwmark, ifin, ifout, dis->data_pkt, dis->len_pkt, dis->len_payload, &ps.ctrack->pos))
|
||||
if (rawpacket_queue(&ps.ctrack->delayed, &ps.dst, fwmark, desync_fwmark, ifin, ifout, dis->data_pkt, dis->len_pkt, dis->len_payload, &ps.ctrack->pos, false))
|
||||
{
|
||||
DLOG("DELAY desync until reasm is complete (#%u)\n", rawpacket_queue_count(&ps.ctrack->delayed));
|
||||
}
|
||||
else
|
||||
{
|
||||
DLOG_ERR("rawpacket_queue failed !\n");
|
||||
goto pass_reasm_cancel;
|
||||
goto rediscover_cancel;
|
||||
}
|
||||
if (bReqFull)
|
||||
{
|
||||
@@ -1844,16 +1900,16 @@ static uint8_t dpi_desync_udp_packet_play(
|
||||
{
|
||||
// preallocate max buffer to avoid reallocs that cause memory copy
|
||||
if (!reasm_client_start(ps.ctrack, IPPROTO_UDP, UDP_MAX_REASM, UDP_MAX_REASM, clean, clean_len))
|
||||
goto pass_reasm_cancel;
|
||||
goto rediscover_cancel;
|
||||
}
|
||||
if (rawpacket_queue(&ps.ctrack->delayed, &ps.dst, fwmark, desync_fwmark, ifin, ifout, dis->data_pkt, dis->len_pkt, dis->len_payload, &ps.ctrack->pos))
|
||||
if (rawpacket_queue(&ps.ctrack->delayed, &ps.dst, fwmark, desync_fwmark, ifin, ifout, dis->data_pkt, dis->len_pkt, dis->len_payload, &ps.ctrack->pos, false))
|
||||
{
|
||||
DLOG("DELAY desync until reasm is complete (#%u)\n", rawpacket_queue_count(&ps.ctrack->delayed));
|
||||
}
|
||||
else
|
||||
{
|
||||
DLOG_ERR("rawpacket_queue failed !\n");
|
||||
goto pass_reasm_cancel;
|
||||
goto rediscover_cancel;
|
||||
}
|
||||
return ct_new_postnat_fix(ps.ctrack, dis, mod_pkt, len_mod_pkt);
|
||||
}
|
||||
@@ -1878,18 +1934,16 @@ static uint8_t dpi_desync_udp_packet_play(
|
||||
feed_dns_response(dis->data_payload, dis->len_payload);
|
||||
} // len_payload
|
||||
|
||||
// UNSOLVED: if reasm is cancelled all packets except the last are passed as is without lua desync
|
||||
rediscover_cancel:
|
||||
reasm_client_cancel(ps.ctrack);
|
||||
|
||||
if (!dp_rediscovery(&ps))
|
||||
goto pass;
|
||||
|
||||
ps.verdict = desync(ps.dp, fwmark, ifin, ifout, ps.bReverseFixed, ps.ctrack_replay, tpos, ps.l7payload, ps.l7proto, dis, ps.sdip4, ps.sdip6, ps.sdport, mod_pkt, len_mod_pkt, replay_piece, replay_piece_count, reasm_offset, NULL, 0, data_decrypt, len_decrypt);
|
||||
|
||||
pass:
|
||||
return (!ps.bReverse && (ps.verdict & VERDICT_MASK) == VERDICT_DROP) ? ct_new_postnat_fix(ps.ctrack, dis, mod_pkt, len_mod_pkt) : ps.verdict;
|
||||
pass_reasm_cancel:
|
||||
reasm_client_cancel(ps.ctrack);
|
||||
goto pass;
|
||||
return (!ps.bReverseFixed && (ps.verdict & VERDICT_MASK) == VERDICT_DROP) ? ct_new_postnat_fix(ps.ctrack, dis, mod_pkt, len_mod_pkt) : ps.verdict;
|
||||
}
|
||||
|
||||
// conntrack is supported only for RELATED icmp
|
||||
@@ -1949,7 +2003,7 @@ static uint8_t dpi_desync_icmp_packet(
|
||||
// invert direction. they are answering to this packet
|
||||
bReverse = !bReverse;
|
||||
DLOG("found conntrack entry. inverted reverse=%u\n",bReverse);
|
||||
if (ctrack->dp_search_complete)
|
||||
if (ctrack->dp_search_complete && ctrack->dp)
|
||||
{
|
||||
// RELATED icmp processed within base connection profile
|
||||
dp = ctrack->dp;
|
||||
@@ -2143,12 +2197,24 @@ static bool replay_queue(struct rawpacket_tailhead *q)
|
||||
struct rawpacket *rp;
|
||||
size_t offset;
|
||||
unsigned int i, count;
|
||||
bool b = true;
|
||||
uint8_t mod[RECONSTRUCT_MAX_SIZE];
|
||||
size_t modlen;
|
||||
uint32_t seq0;
|
||||
t_ctrack_position *pos;
|
||||
bool b = true, bseq;
|
||||
|
||||
for (i = 0, offset = 0, count = rawpacket_queue_count(q); (rp = rawpacket_dequeue(q)); offset += rp->len_payload, rawpacket_free(rp), i++)
|
||||
for (i = 0, offset = 0, count = rawpacket_queue_count(q); (rp = rawpacket_dequeue(q)); rawpacket_free(rp), i++)
|
||||
{
|
||||
// TCP: track reasm_offset using sequence numbers
|
||||
if ((bseq = rp->tpos_present && rp->tpos.ipproto==IPPROTO_TCP))
|
||||
{
|
||||
pos = rp->server_side ? &rp->tpos.server : &rp->tpos.client;
|
||||
if (i)
|
||||
offset = pos->seq_last - seq0;
|
||||
else
|
||||
seq0 = pos->seq_last;
|
||||
}
|
||||
|
||||
DLOG("REPLAYING delayed packet #%u offset %zu\n", i+1, offset);
|
||||
modlen = sizeof(mod);
|
||||
uint8_t verdict = dpi_desync_packet_play(i, count, offset, rp->fwmark_orig, rp->ifin, rp->ifout, rp->tpos_present ? &rp->tpos : NULL, rp->packet, rp->len, mod, &modlen);
|
||||
@@ -2166,6 +2232,9 @@ static bool replay_queue(struct rawpacket_tailhead *q)
|
||||
DLOG("DROPPING delayed packet #%u\n", i+1);
|
||||
break;
|
||||
}
|
||||
|
||||
if (!bseq)
|
||||
offset += rp->len_payload;
|
||||
}
|
||||
return b;
|
||||
}
|
||||
|
||||
@@ -173,27 +173,27 @@ bool packet_range_parse(const char *s, struct packet_range *range)
|
||||
|
||||
void str_cidr4(char *s, size_t s_len, const struct cidr4 *cidr)
|
||||
{
|
||||
char s_ip[16];
|
||||
char s_ip[INET_ADDRSTRLEN];
|
||||
*s_ip=0;
|
||||
inet_ntop(AF_INET, &cidr->addr, s_ip, sizeof(s_ip));
|
||||
snprintf(s,s_len,cidr->preflen<32 ? "%s/%u" : "%s", s_ip, cidr->preflen);
|
||||
}
|
||||
void print_cidr4(const struct cidr4 *cidr)
|
||||
{
|
||||
char s[19];
|
||||
char s[INET_ADDRSTRLEN+4];
|
||||
str_cidr4(s,sizeof(s),cidr);
|
||||
printf("%s",s);
|
||||
}
|
||||
void str_cidr6(char *s, size_t s_len, const struct cidr6 *cidr)
|
||||
{
|
||||
char s_ip[40];
|
||||
char s_ip[INET6_ADDRSTRLEN];
|
||||
*s_ip=0;
|
||||
inet_ntop(AF_INET6, &cidr->addr, s_ip, sizeof(s_ip));
|
||||
snprintf(s,s_len,cidr->preflen<128 ? "%s/%u" : "%s", s_ip, cidr->preflen);
|
||||
}
|
||||
void print_cidr6(const struct cidr6 *cidr)
|
||||
{
|
||||
char s[44];
|
||||
char s[INET6_ADDRSTRLEN+4];
|
||||
str_cidr6(s,sizeof(s),cidr);
|
||||
printf("%s",s);
|
||||
}
|
||||
|
||||
42
nfq2/gzip.c
42
nfq2/gzip.c
@@ -2,6 +2,7 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "helpers.h"
|
||||
|
||||
#define ZCHUNK 16384
|
||||
#define BUFMIN 128
|
||||
@@ -14,6 +15,7 @@ int z_readfile(FILE *F, char **buf, size_t *size, size_t extra_alloc)
|
||||
unsigned char in[ZCHUNK];
|
||||
size_t bufsize;
|
||||
void *newbuf;
|
||||
size_t rd;
|
||||
|
||||
memset(&zs, 0, sizeof(zs));
|
||||
|
||||
@@ -25,20 +27,21 @@ int z_readfile(FILE *F, char **buf, size_t *size, size_t extra_alloc)
|
||||
|
||||
do
|
||||
{
|
||||
zs.avail_in = fread(in, 1, sizeof(in), F);
|
||||
if (ferror(F))
|
||||
if (!fread_safe(in, 1, sizeof(in), F, &rd))
|
||||
{
|
||||
r = Z_ERRNO;
|
||||
goto zerr;
|
||||
}
|
||||
if (!zs.avail_in)
|
||||
if (!rd)
|
||||
{
|
||||
// file is not full
|
||||
r = Z_DATA_ERROR;
|
||||
goto zerr;
|
||||
}
|
||||
zs.avail_in = rd;
|
||||
zs.next_in = in;
|
||||
do
|
||||
|
||||
for(;;)
|
||||
{
|
||||
if ((bufsize - *size) < BUFMIN)
|
||||
{
|
||||
@@ -53,20 +56,41 @@ int z_readfile(FILE *F, char **buf, size_t *size, size_t extra_alloc)
|
||||
}
|
||||
zs.avail_out = bufsize - *size;
|
||||
zs.next_out = (unsigned char*)(*buf + *size);
|
||||
|
||||
r = inflate(&zs, Z_NO_FLUSH);
|
||||
if (r != Z_OK && r != Z_STREAM_END) goto zerr;
|
||||
|
||||
*size = bufsize - zs.avail_out;
|
||||
} while (r == Z_OK && zs.avail_in);
|
||||
if (r==Z_STREAM_END) break;
|
||||
if (r==Z_BUF_ERROR)
|
||||
{
|
||||
if (zs.avail_in)
|
||||
goto zerr;
|
||||
else
|
||||
{
|
||||
r = Z_OK;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (r!=Z_OK) goto zerr;
|
||||
}
|
||||
} while (r == Z_OK);
|
||||
|
||||
if (*size < bufsize)
|
||||
{
|
||||
// free extra space
|
||||
if ((newbuf = realloc(*buf, *size + extra_alloc))) *buf = newbuf;
|
||||
if (*size + extra_alloc)
|
||||
{
|
||||
// free extra space
|
||||
if ((newbuf = realloc(*buf, *size + extra_alloc))) *buf = newbuf;
|
||||
}
|
||||
else
|
||||
{
|
||||
free(*buf);
|
||||
*buf = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
inflateEnd(&zs);
|
||||
return Z_OK;
|
||||
return r;
|
||||
|
||||
zerr:
|
||||
inflateEnd(&zs);
|
||||
|
||||
445
nfq2/helpers.c
445
nfq2/helpers.c
@@ -9,9 +9,15 @@
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
#include <libgen.h>
|
||||
#include <limits.h>
|
||||
#include <errno.h>
|
||||
#include <sys/param.h>
|
||||
|
||||
#ifdef __CYGWIN__
|
||||
#include <sys/cygwin.h>
|
||||
#endif
|
||||
|
||||
|
||||
#define UNIQ_SORT \
|
||||
{ \
|
||||
size_t i, j, u; \
|
||||
@@ -33,7 +39,7 @@ static int cmp_size_t(const void * a, const void * b)
|
||||
}
|
||||
void qsort_size_t(size_t *array, int ct)
|
||||
{
|
||||
qsort(array,ct,sizeof(*array),cmp_size_t);
|
||||
qsort(array, ct, sizeof(*array), cmp_size_t);
|
||||
}
|
||||
static int cmp_ssize_t(const void * a, const void * b)
|
||||
{
|
||||
@@ -41,14 +47,13 @@ static int cmp_ssize_t(const void * a, const void * b)
|
||||
}
|
||||
void qsort_ssize_t(ssize_t *array, int ct)
|
||||
{
|
||||
qsort(array,ct,sizeof(*array),cmp_ssize_t);
|
||||
qsort(array, ct, sizeof(*array), cmp_ssize_t);
|
||||
}
|
||||
|
||||
|
||||
int str_index(const char **strs, int count, const char *str)
|
||||
{
|
||||
for(int i=0;i<count;i++)
|
||||
if (!strcmp(strs[i],str)) return i;
|
||||
for (int i = 0; i < count; i++)
|
||||
if (!strcmp(strs[i], str)) return i;
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -60,7 +65,7 @@ void rtrim(char *s)
|
||||
|
||||
void replace_char(char *s, char from, char to)
|
||||
{
|
||||
for(;*s;s++) if (*s==from) *s=to;
|
||||
for (; *s; s++) if (*s == from) *s = to;
|
||||
}
|
||||
|
||||
const char *strncasestr(const char *s, const char *find, size_t slen)
|
||||
@@ -88,18 +93,18 @@ const char *strncasestr(const char *s, const char *find, size_t slen)
|
||||
|
||||
static inline bool is_letter(char c)
|
||||
{
|
||||
return (c>='a' && c<='z') || (c>='A' && c<='Z');
|
||||
return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z');
|
||||
}
|
||||
static inline bool is_digit(char c)
|
||||
{
|
||||
return c>='0' && c<='9';
|
||||
return c >= '0' && c <= '9';
|
||||
}
|
||||
bool is_identifier(const char *p)
|
||||
{
|
||||
if (*p!='_' && !is_letter(*p))
|
||||
if (*p != '_' && !is_letter(*p))
|
||||
return false;
|
||||
for(++p;*p;p++)
|
||||
if (!is_letter(*p) && !is_digit(*p) && *p!='_')
|
||||
for (++p; *p; p++)
|
||||
if (!is_letter(*p) && !is_digit(*p) && *p != '_')
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
@@ -120,8 +125,7 @@ bool load_file(const char *filename, off_t offset, void *buffer, size_t *buffer_
|
||||
}
|
||||
}
|
||||
|
||||
*buffer_size = fread(buffer, 1, *buffer_size, F);
|
||||
if (ferror(F))
|
||||
if (!fread_safe(buffer, 1, *buffer_size, F, buffer_size))
|
||||
{
|
||||
fclose(F);
|
||||
return false;
|
||||
@@ -143,7 +147,7 @@ bool save_file(const char *filename, const void *buffer, size_t buffer_size)
|
||||
return false;
|
||||
}
|
||||
fclose(F);
|
||||
if (wr!=buffer_size)
|
||||
if (wr != buffer_size)
|
||||
{
|
||||
errno = EIO;
|
||||
return false;
|
||||
@@ -152,22 +156,22 @@ bool save_file(const char *filename, const void *buffer, size_t buffer_size)
|
||||
}
|
||||
bool append_to_list_file(const char *filename, const char *s)
|
||||
{
|
||||
FILE *F = fopen(filename,"at");
|
||||
FILE *F = fopen(filename, "at");
|
||||
if (!F) return false;
|
||||
bool bOK = fprintf(F,"%s\n",s)>0;
|
||||
bool bOK = fprintf(F, "%s\n", s) > 0;
|
||||
fclose(F);
|
||||
return bOK;
|
||||
}
|
||||
|
||||
void expand_bits(void *target, const void *source, unsigned int source_bitlen, unsigned int target_bytelen)
|
||||
{
|
||||
unsigned int target_bitlen = target_bytelen<<3;
|
||||
unsigned int bitlen = target_bitlen<source_bitlen ? target_bitlen : source_bitlen;
|
||||
unsigned int bytelen = bitlen>>3;
|
||||
unsigned int target_bitlen = target_bytelen << 3;
|
||||
unsigned int bitlen = target_bitlen < source_bitlen ? target_bitlen : source_bitlen;
|
||||
unsigned int bytelen = bitlen >> 3;
|
||||
|
||||
if ((target_bytelen-bytelen)>=1) memset((uint8_t*)target+bytelen,0,target_bytelen-bytelen);
|
||||
memcpy(target,source,bytelen);
|
||||
if ((bitlen &= 7)) ((uint8_t*)target)[bytelen] = ((uint8_t*)source)[bytelen] & (~((1 << (8-bitlen)) - 1));
|
||||
if ((target_bytelen - bytelen) >= 1) memset((uint8_t*)target + bytelen, 0, target_bytelen - bytelen);
|
||||
memcpy(target, source, bytelen);
|
||||
if ((bitlen &= 7)) ((uint8_t*)target)[bytelen] = ((uint8_t*)source)[bytelen] & (~((1 << (8 - bitlen)) - 1));
|
||||
}
|
||||
|
||||
// " [fd00::1]" => "fd00::1"
|
||||
@@ -179,53 +183,53 @@ void expand_bits(void *target, const void *source, unsigned int source_bitlen, u
|
||||
bool strip_host_to_ip(char *host)
|
||||
{
|
||||
size_t l;
|
||||
char *h,*p;
|
||||
char *h, *p;
|
||||
uint8_t addr[16];
|
||||
|
||||
for (h = host ; *h==' ' || *h=='\t' ; h++);
|
||||
for (h = host; *h == ' ' || *h == '\t'; h++);
|
||||
l = strlen(h);
|
||||
if (l>=2)
|
||||
if (l >= 2)
|
||||
{
|
||||
if (*h=='[')
|
||||
if (*h == '[')
|
||||
{
|
||||
// ipv6 ?
|
||||
for (p=++h ; *p && *p!=']' ; p++);
|
||||
if (*p==']')
|
||||
for (p = ++h; *p && *p != ']'; p++);
|
||||
if (*p == ']')
|
||||
{
|
||||
l = p-h;
|
||||
memmove(host,h,l);
|
||||
host[l]=0;
|
||||
return inet_pton(AF_INET6, host, addr)>0;
|
||||
l = p - h;
|
||||
memmove(host, h, l);
|
||||
host[l] = 0;
|
||||
return inet_pton(AF_INET6, host, addr) > 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (inet_pton(AF_INET6, h, addr)>0)
|
||||
if (inet_pton(AF_INET6, h, addr) > 0)
|
||||
{
|
||||
// ipv6 ?
|
||||
if (host!=h)
|
||||
if (host != h)
|
||||
{
|
||||
l = strlen(h);
|
||||
memmove(host,h,l);
|
||||
host[l]=0;
|
||||
memmove(host, h, l);
|
||||
host[l] = 0;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// ipv4 ?
|
||||
for (p=h ; *p && *p!=':' ; p++);
|
||||
l = p-h;
|
||||
if (host!=h) memmove(host,h,l);
|
||||
host[l]=0;
|
||||
return inet_pton(AF_INET, host, addr)>0;
|
||||
for (p = h; *p && *p != ':'; p++);
|
||||
l = p - h;
|
||||
if (host != h) memmove(host, h, l);
|
||||
host[l] = 0;
|
||||
return inet_pton(AF_INET, host, addr) > 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void ntopa46(const struct in_addr *ip, const struct in6_addr *ip6,char *str, size_t len)
|
||||
void ntopa46(const struct in_addr *ip, const struct in6_addr *ip6, char *str, size_t len)
|
||||
{
|
||||
if (!len) return;
|
||||
*str = 0;
|
||||
@@ -235,13 +239,13 @@ void ntopa46(const struct in_addr *ip, const struct in6_addr *ip6,char *str, siz
|
||||
}
|
||||
void ntop46(const struct sockaddr *sa, char *str, size_t len)
|
||||
{
|
||||
ntopa46(sa->sa_family==AF_INET ? &((struct sockaddr_in*)sa)->sin_addr : NULL,
|
||||
sa->sa_family==AF_INET6 ? &((struct sockaddr_in6*)sa)->sin6_addr : NULL,
|
||||
ntopa46(sa->sa_family == AF_INET ? &((struct sockaddr_in*)sa)->sin_addr : NULL,
|
||||
sa->sa_family == AF_INET6 ? &((struct sockaddr_in6*)sa)->sin6_addr : NULL,
|
||||
str, len);
|
||||
}
|
||||
void ntop46_port(const struct sockaddr *sa, char *str, size_t len)
|
||||
{
|
||||
char ip[40];
|
||||
char ip[INET6_ADDRSTRLEN];
|
||||
ntop46(sa, ip, sizeof(ip));
|
||||
switch (sa->sa_family)
|
||||
{
|
||||
@@ -265,32 +269,32 @@ void print_sockaddr(const struct sockaddr *sa)
|
||||
|
||||
uint16_t saport(const struct sockaddr *sa)
|
||||
{
|
||||
return ntohs(sa->sa_family==AF_INET ? ((struct sockaddr_in*)sa)->sin_port :
|
||||
sa->sa_family==AF_INET6 ? ((struct sockaddr_in6*)sa)->sin6_port : 0);
|
||||
return ntohs(sa->sa_family == AF_INET ? ((struct sockaddr_in*)sa)->sin_port :
|
||||
sa->sa_family == AF_INET6 ? ((struct sockaddr_in6*)sa)->sin6_port : 0);
|
||||
}
|
||||
|
||||
bool sa_has_addr(const struct sockaddr *sa)
|
||||
{
|
||||
switch(sa->sa_family)
|
||||
switch (sa->sa_family)
|
||||
{
|
||||
case AF_INET:
|
||||
return ((struct sockaddr_in*)sa)->sin_addr.s_addr!=INADDR_ANY;
|
||||
case AF_INET6:
|
||||
return memcmp(((struct sockaddr_in6*)sa)->sin6_addr.s6_addr, "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 16);
|
||||
default:
|
||||
return false;
|
||||
case AF_INET:
|
||||
return ((struct sockaddr_in*)sa)->sin_addr.s_addr != INADDR_ANY;
|
||||
case AF_INET6:
|
||||
return memcmp(((struct sockaddr_in6*)sa)->sin6_addr.s6_addr, "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 16);
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool seq_within(uint32_t s, uint32_t s1, uint32_t s2)
|
||||
{
|
||||
return (s2>=s1 && s>=s1 && s<=s2) || (s2<s1 && (s<=s2 || s>=s1));
|
||||
return (s2 >= s1 && s >= s1 && s <= s2) || (s2 < s1 && (s <= s2 || s >= s1));
|
||||
}
|
||||
|
||||
bool ipv6_addr_is_zero(const struct in6_addr *a)
|
||||
{
|
||||
return !memcmp(a,"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",16);
|
||||
return !memcmp(a, "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 16);
|
||||
}
|
||||
|
||||
|
||||
@@ -309,8 +313,8 @@ uint32_t pntoh24(const uint8_t *p)
|
||||
}
|
||||
void phton24(uint8_t *p, uint32_t v)
|
||||
{
|
||||
p[0] = (uint8_t)(v>>16);
|
||||
p[1] = (uint8_t)(v>>8);
|
||||
p[0] = (uint8_t)(v >> 16);
|
||||
p[1] = (uint8_t)(v >> 8);
|
||||
p[2] = (uint8_t)v;
|
||||
}
|
||||
uint32_t pntoh32(const uint8_t *p)
|
||||
@@ -319,9 +323,9 @@ uint32_t pntoh32(const uint8_t *p)
|
||||
}
|
||||
void phton32(uint8_t *p, uint32_t v)
|
||||
{
|
||||
p[0] = (uint8_t)(v>>24);
|
||||
p[1] = (uint8_t)(v>>16);
|
||||
p[2] = (uint8_t)(v>>8);
|
||||
p[0] = (uint8_t)(v >> 24);
|
||||
p[1] = (uint8_t)(v >> 16);
|
||||
p[2] = (uint8_t)(v >> 8);
|
||||
p[3] = (uint8_t)v;
|
||||
}
|
||||
uint64_t pntoh48(const uint8_t *p)
|
||||
@@ -330,11 +334,11 @@ uint64_t pntoh48(const uint8_t *p)
|
||||
}
|
||||
void phton48(uint8_t *p, uint64_t v)
|
||||
{
|
||||
p[0] = (uint8_t)(v>>40);
|
||||
p[1] = (uint8_t)(v>>32);
|
||||
p[2] = (uint8_t)(v>>24);
|
||||
p[3] = (uint8_t)(v>>16);
|
||||
p[4] = (uint8_t)(v>>8);
|
||||
p[0] = (uint8_t)(v >> 40);
|
||||
p[1] = (uint8_t)(v >> 32);
|
||||
p[2] = (uint8_t)(v >> 24);
|
||||
p[3] = (uint8_t)(v >> 16);
|
||||
p[4] = (uint8_t)(v >> 8);
|
||||
p[5] = (uint8_t)v;
|
||||
}
|
||||
uint64_t pntoh64(const uint8_t *p)
|
||||
@@ -343,24 +347,24 @@ uint64_t pntoh64(const uint8_t *p)
|
||||
}
|
||||
void phton64(uint8_t *p, uint64_t v)
|
||||
{
|
||||
p[0] = (uint8_t)(v>>56);
|
||||
p[1] = (uint8_t)(v>>48);
|
||||
p[2] = (uint8_t)(v>>40);
|
||||
p[3] = (uint8_t)(v>>32);
|
||||
p[4] = (uint8_t)(v>>24);
|
||||
p[5] = (uint8_t)(v>>16);
|
||||
p[6] = (uint8_t)(v>>8);
|
||||
p[0] = (uint8_t)(v >> 56);
|
||||
p[1] = (uint8_t)(v >> 48);
|
||||
p[2] = (uint8_t)(v >> 40);
|
||||
p[3] = (uint8_t)(v >> 32);
|
||||
p[4] = (uint8_t)(v >> 24);
|
||||
p[5] = (uint8_t)(v >> 16);
|
||||
p[6] = (uint8_t)(v >> 8);
|
||||
p[7] = (uint8_t)v;
|
||||
}
|
||||
|
||||
uint16_t bswap16(uint16_t u)
|
||||
{
|
||||
// __builtin_bswap16 is absent in ancient lexra gcc 4.6
|
||||
return (u>>8) | ((u&0xFF)<<8);
|
||||
return (u >> 8) | ((u & 0xFF) << 8);
|
||||
}
|
||||
uint32_t bswap24(uint32_t u)
|
||||
{
|
||||
return (u>>16) & 0xFF | u & 0xFF00 | (u<<16) & 0xFF0000;
|
||||
return (u >> 16) & 0xFF | u & 0xFF00 | (u << 16) & 0xFF0000;
|
||||
}
|
||||
uint64_t bswap48(uint64_t u)
|
||||
{
|
||||
@@ -371,39 +375,39 @@ uint64_t bswap48(uint64_t u)
|
||||
#define INVALID_HEX_DIGIT ((uint8_t)-1)
|
||||
static inline uint8_t parse_hex_digit(char c)
|
||||
{
|
||||
return (c>='0' && c<='9') ? c-'0' : (c>='a' && c<='f') ? c-'a'+0xA : (c>='A' && c<='F') ? c-'A'+0xA : INVALID_HEX_DIGIT;
|
||||
return (c >= '0' && c <= '9') ? c - '0' : (c >= 'a' && c <= 'f') ? c - 'a' + 0xA : (c >= 'A' && c <= 'F') ? c - 'A' + 0xA : INVALID_HEX_DIGIT;
|
||||
}
|
||||
static inline bool parse_hex_byte(const char *s, uint8_t *pbyte)
|
||||
{
|
||||
uint8_t u,l;
|
||||
uint8_t u, l;
|
||||
u = parse_hex_digit(s[0]);
|
||||
l = parse_hex_digit(s[1]);
|
||||
if (u==INVALID_HEX_DIGIT || l==INVALID_HEX_DIGIT)
|
||||
if (u == INVALID_HEX_DIGIT || l == INVALID_HEX_DIGIT)
|
||||
{
|
||||
*pbyte=0;
|
||||
*pbyte = 0;
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
*pbyte=(u<<4) | l;
|
||||
*pbyte = (u << 4) | l;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
bool parse_hex_str(const char *s, uint8_t *pbuf, size_t *size)
|
||||
{
|
||||
uint8_t *pe = pbuf+*size;
|
||||
*size=0;
|
||||
while(pbuf<pe && *s)
|
||||
uint8_t *pe = pbuf + *size;
|
||||
*size = 0;
|
||||
while (pbuf < pe && *s)
|
||||
{
|
||||
if (!parse_hex_byte(s,pbuf))
|
||||
if (!parse_hex_byte(s, pbuf))
|
||||
return false;
|
||||
pbuf++; s+=2; (*size)++;
|
||||
pbuf++; s += 2; (*size)++;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
char hex_digit(uint8_t v)
|
||||
{
|
||||
return v<=9 ? '0'+v : (v<=0xF) ? v+'A'-0xA : '?';
|
||||
return v <= 9 ? '0' + v : (v <= 0xF) ? v + 'A' - 0xA : '?';
|
||||
}
|
||||
|
||||
int fprint_localtime(FILE *F)
|
||||
@@ -412,39 +416,39 @@ int fprint_localtime(FILE *F)
|
||||
time_t now;
|
||||
|
||||
time(&now);
|
||||
localtime_r(&now,&t);
|
||||
localtime_r(&now, &t);
|
||||
return fprintf(F, "%02d.%02d.%04d %02d:%02d:%02d", t.tm_mday, t.tm_mon + 1, t.tm_year + 1900, t.tm_hour, t.tm_min, t.tm_sec);
|
||||
}
|
||||
|
||||
bool file_size(const char *filename, off_t *size)
|
||||
{
|
||||
struct stat st;
|
||||
if (stat(filename,&st)==-1) return false;
|
||||
if (stat(filename, &st) == -1) return false;
|
||||
*size = st.st_size;
|
||||
return true;
|
||||
}
|
||||
time_t file_mod_time(const char *filename)
|
||||
{
|
||||
struct stat st;
|
||||
return stat(filename,&st)==-1 ? 0 : st.st_mtime;
|
||||
return stat(filename, &st) == -1 ? 0 : st.st_mtime;
|
||||
}
|
||||
bool file_mod_signature(const char *filename, file_mod_sig *ms)
|
||||
{
|
||||
struct stat st;
|
||||
if (stat(filename,&st)==-1)
|
||||
if (stat(filename, &st) == -1)
|
||||
{
|
||||
FILE_MOD_RESET(ms);
|
||||
return false;
|
||||
}
|
||||
ms->mod_time=st.st_mtime;
|
||||
ms->size=st.st_size;
|
||||
ms->mod_time = st.st_mtime;
|
||||
ms->size = st.st_size;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool file_open_test(const char *filename, int flags)
|
||||
{
|
||||
int fd = open(filename,flags);
|
||||
if (fd>=0)
|
||||
int fd = open(filename, flags);
|
||||
if (fd >= 0)
|
||||
{
|
||||
close(fd);
|
||||
return true;
|
||||
@@ -453,54 +457,54 @@ bool file_open_test(const char *filename, int flags)
|
||||
}
|
||||
|
||||
|
||||
void fill_random_bytes(uint8_t *p,size_t sz)
|
||||
void fill_random_bytes(uint8_t *p, size_t sz)
|
||||
{
|
||||
size_t k;
|
||||
if (sz)
|
||||
{
|
||||
// alignment
|
||||
if ((size_t)p & 1) { *p=(uint8_t)random(); sz--; p++; }
|
||||
if ((size_t)p & 1) { *p = (uint8_t)random(); sz--; p++; }
|
||||
// random has only 31 bits of entropy. not 32 bits
|
||||
for (k=0 ; (k+1)<sz ; k+=2) *(uint16_t*)(p+k) = (uint16_t)random();
|
||||
if (sz & 1) p[sz-1]=(uint8_t)random();
|
||||
for (k = 0; (k + 1) < sz; k += 2) *(uint16_t*)(p + k) = (uint16_t)random();
|
||||
if (sz & 1) p[sz - 1] = (uint8_t)random();
|
||||
}
|
||||
}
|
||||
void fill_random_az(uint8_t *p,size_t sz)
|
||||
void fill_random_az(uint8_t *p, size_t sz)
|
||||
{
|
||||
size_t k;
|
||||
for(k=0;k<sz;k++) p[k] = 'a'+(random() % ('z'-'a'+1));
|
||||
for (k = 0; k < sz; k++) p[k] = 'a' + (random() % ('z' - 'a' + 1));
|
||||
}
|
||||
void fill_random_az09(uint8_t *p,size_t sz)
|
||||
void fill_random_az09(uint8_t *p, size_t sz)
|
||||
{
|
||||
size_t k;
|
||||
uint8_t rnd;
|
||||
for(k=0;k<sz;k++)
|
||||
for (k = 0; k < sz; k++)
|
||||
{
|
||||
rnd = random() % (10 + 'z'-'a'+1);
|
||||
p[k] = rnd<10 ? rnd+'0' : 'a'+rnd-10;
|
||||
rnd = random() % (10 + 'z' - 'a' + 1);
|
||||
p[k] = rnd < 10 ? rnd + '0' : 'a' + rnd - 10;
|
||||
}
|
||||
}
|
||||
#if defined(__FreeBSD__) && __FreeBSD_version <= 1200000
|
||||
#include <sys/sysctl.h>
|
||||
int getentropy(void *buf, size_t len)
|
||||
{
|
||||
int mib[2];
|
||||
size_t size = len;
|
||||
int mib[2];
|
||||
size_t size = len;
|
||||
|
||||
// Check for reasonable length (getentropy limits to 256)
|
||||
if (len > 256) {
|
||||
errno = EIO;
|
||||
return -1;
|
||||
}
|
||||
// Check for reasonable length (getentropy limits to 256)
|
||||
if (len > 256) {
|
||||
errno = EIO;
|
||||
return -1;
|
||||
}
|
||||
|
||||
mib[0] = CTL_KERN;
|
||||
mib[1] = KERN_ARND;
|
||||
mib[0] = CTL_KERN;
|
||||
mib[1] = KERN_ARND;
|
||||
|
||||
if (sysctl(mib, 2, buf, &size, NULL, 0) == -1) {
|
||||
return -1;
|
||||
}
|
||||
if (sysctl(mib, 2, buf, &size, NULL, 0) == -1) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return (size == len) ? 0 : -1;
|
||||
return (size == len) ? 0 : -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -508,48 +512,95 @@ int getentropy(void *buf, size_t len)
|
||||
ssize_t read_intr(int fd, void *buf, size_t count)
|
||||
{
|
||||
ssize_t rd;
|
||||
while ((rd=read(fd,buf,count))<0 && errno==EINTR);
|
||||
while ((rd = read(fd, buf, count)) < 0 && errno == EINTR);
|
||||
return rd;
|
||||
}
|
||||
|
||||
bool fill_crypto_random_bytes(uint8_t *p,size_t sz)
|
||||
bool fread_safe(void *ptr, size_t size, size_t nmemb, FILE *F, size_t *rd)
|
||||
{
|
||||
size_t result, to_read, total_read = 0;
|
||||
while (total_read < nmemb)
|
||||
{
|
||||
to_read = nmemb - total_read;
|
||||
errno = 0;
|
||||
total_read += (result = fread((uint8_t*)ptr + (total_read * size), size, to_read, F));
|
||||
if (result < to_read)
|
||||
{
|
||||
if (ferror(F))
|
||||
{
|
||||
if (errno == EINTR)
|
||||
{
|
||||
clearerr(F);
|
||||
continue;
|
||||
}
|
||||
*rd = total_read;
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
*rd = total_read;
|
||||
return true;
|
||||
}
|
||||
char* fgets_safe(char *s, int size, FILE *stream)
|
||||
{
|
||||
char *result;
|
||||
|
||||
while (true)
|
||||
{
|
||||
errno = 0;
|
||||
if ((result = fgets(s, size, stream))) return result;
|
||||
if (ferror(stream))
|
||||
{
|
||||
if (errno == EINTR)
|
||||
{
|
||||
clearerr(stream);
|
||||
continue;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
if (feof(stream)) return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
bool fill_crypto_random_bytes(uint8_t *p, size_t sz)
|
||||
{
|
||||
ssize_t rd;
|
||||
int fd;
|
||||
|
||||
#if defined(__linux__) || defined(__CYGWIN__)
|
||||
for(; sz && (rd=getrandom(p,sz,GRND_NONBLOCK))>0 ; p+=rd, sz-=rd);
|
||||
for (; sz && (rd = getrandom(p, sz, GRND_NONBLOCK)) > 0; p += rd, sz -= rd);
|
||||
if (sz)
|
||||
#elif defined(BSD)
|
||||
while(sz)
|
||||
while (sz)
|
||||
{
|
||||
rd = sz<256 ? sz : 256; // BSD limitation
|
||||
if (getentropy(p,rd)) break;
|
||||
p+=rd; sz-=rd;
|
||||
rd = sz < 256 ? sz : 256; // BSD limitation
|
||||
if (getentropy(p, rd)) break;
|
||||
p += rd; sz -= rd;
|
||||
}
|
||||
if (sz)
|
||||
#endif
|
||||
{
|
||||
if ((fd = open("/dev/random",O_NONBLOCK))>=0)
|
||||
if ((fd = open("/dev/random", O_NONBLOCK)) >= 0)
|
||||
{
|
||||
do
|
||||
{
|
||||
if ((rd=read_intr(fd,p,sz))>0)
|
||||
if ((rd = read_intr(fd, p, sz)) > 0)
|
||||
{
|
||||
p+=rd; sz-=rd;
|
||||
p += rd; sz -= rd;
|
||||
}
|
||||
} while(sz && rd>0);
|
||||
} while (sz && rd > 0);
|
||||
close(fd);
|
||||
}
|
||||
if (sz && (fd = open("/dev/urandom",0))>=0)
|
||||
if (sz && (fd = open("/dev/urandom", 0)) >= 0)
|
||||
{
|
||||
do
|
||||
{
|
||||
if ((rd=read_intr(fd,p,sz))>0)
|
||||
if ((rd = read_intr(fd, p, sz)) > 0)
|
||||
{
|
||||
p+=rd; sz-=rd;
|
||||
p += rd; sz -= rd;
|
||||
}
|
||||
} while(sz && rd>0);
|
||||
} while (sz && rd > 0);
|
||||
close(fd);
|
||||
}
|
||||
}
|
||||
@@ -557,33 +608,33 @@ bool fill_crypto_random_bytes(uint8_t *p,size_t sz)
|
||||
}
|
||||
|
||||
#if defined(__GNUC__) && !defined(__llvm__)
|
||||
__attribute__((optimize ("no-strict-aliasing")))
|
||||
__attribute__((optimize("no-strict-aliasing")))
|
||||
#endif
|
||||
void bxor(const uint8_t *x1, const uint8_t *x2, uint8_t *result, size_t sz)
|
||||
{
|
||||
for (; sz>=8 ; x1+=8, x2+=8, result+=8, sz-=8)
|
||||
for (; sz >= 8; x1 += 8, x2 += 8, result += 8, sz -= 8)
|
||||
*(uint64_t*)result = *(uint64_t*)x1 ^ *(uint64_t*)x2;
|
||||
for (; sz ; x1++, x2++, result++, sz--)
|
||||
for (; sz; x1++, x2++, result++, sz--)
|
||||
*result = *x1 ^ *x2;
|
||||
}
|
||||
#if defined(__GNUC__) && !defined(__llvm__)
|
||||
__attribute__((optimize ("no-strict-aliasing")))
|
||||
__attribute__((optimize("no-strict-aliasing")))
|
||||
#endif
|
||||
void bor(const uint8_t *x1, const uint8_t *x2, uint8_t *result, size_t sz)
|
||||
{
|
||||
for (; sz>=8 ; x1+=8, x2+=8, result+=8, sz-=8)
|
||||
for (; sz >= 8; x1 += 8, x2 += 8, result += 8, sz -= 8)
|
||||
*(uint64_t*)result = *(uint64_t*)x1 | *(uint64_t*)x2;
|
||||
for (; sz ; x1++, x2++, result++, sz--)
|
||||
for (; sz; x1++, x2++, result++, sz--)
|
||||
*result = *x1 | *x2;
|
||||
}
|
||||
#if defined(__GNUC__) && !defined(__llvm__)
|
||||
__attribute__((optimize ("no-strict-aliasing")))
|
||||
__attribute__((optimize("no-strict-aliasing")))
|
||||
#endif
|
||||
void band(const uint8_t *x1, const uint8_t *x2, uint8_t *result, size_t sz)
|
||||
{
|
||||
for (; sz>=8 ; x1+=8, x2+=8, result+=8, sz-=8)
|
||||
for (; sz >= 8; x1 += 8, x2 += 8, result += 8, sz -= 8)
|
||||
*(uint64_t*)result = *(uint64_t*)x1 & *(uint64_t*)x2;
|
||||
for (; sz ; x1++, x2++, result++, sz--)
|
||||
for (; sz; x1++, x2++, result++, sz--)
|
||||
*result = *x1 & *x2;
|
||||
}
|
||||
|
||||
@@ -608,17 +659,69 @@ void close_std_and_exit(int code)
|
||||
|
||||
bool set_env_exedir(const char *argv0)
|
||||
{
|
||||
char *s,*d;
|
||||
bool bOK=false;
|
||||
char *s, *d;
|
||||
bool bOK = false;
|
||||
if ((s = strdup(argv0)))
|
||||
{
|
||||
if ((d = dirname(s)))
|
||||
bOK = !setenv("EXEDIR",d,1);
|
||||
{
|
||||
char d_abs[PATH_MAX];
|
||||
if (realpath(d, d_abs))
|
||||
d=d_abs;
|
||||
bOK = !setenv("EXEDIR", d, 1);
|
||||
}
|
||||
free(s);
|
||||
}
|
||||
return bOK;
|
||||
}
|
||||
|
||||
// works for existing and new files
|
||||
bool realpath_any(const char *file, char *pabs)
|
||||
{
|
||||
bool b = true;
|
||||
char *s1=NULL, *s2=NULL;
|
||||
int res;
|
||||
size_t l;
|
||||
|
||||
#ifdef __CYGWIN__
|
||||
l = cygwin_conv_path(CCP_WIN_A_TO_POSIX | CCP_ABSOLUTE, file, NULL, 0);
|
||||
char *rp_file = (char*)malloc(l);
|
||||
if (cygwin_conv_path(CCP_WIN_A_TO_POSIX | CCP_ABSOLUTE, file, rp_file, l))
|
||||
goto err;
|
||||
#else
|
||||
#define rp_file file
|
||||
#endif
|
||||
|
||||
if (!realpath(rp_file,pabs))
|
||||
{
|
||||
char pa[PATH_MAX], *dir, *base;
|
||||
if (!(s1 = strdup(rp_file))) goto err;
|
||||
dir = dirname(s1);
|
||||
if (!realpath(dir,pa))
|
||||
goto err;
|
||||
if (!(s2 = strdup(rp_file))) goto err;
|
||||
base = basename(s2);
|
||||
l = strlen(pa);
|
||||
if (l && pa[l-1]=='/')
|
||||
res=snprintf(pabs,PATH_MAX,"%s%s",pa, base);
|
||||
else
|
||||
res=snprintf(pabs,PATH_MAX,"%s/%s",pa,base);
|
||||
b = res>0 && res<PATH_MAX;
|
||||
}
|
||||
ex:
|
||||
#ifdef __CYGWIN__
|
||||
free(rp_file);
|
||||
#else
|
||||
#undef rp_file
|
||||
#endif
|
||||
free(s1);
|
||||
free(s2);
|
||||
return b;
|
||||
err:
|
||||
b = false;
|
||||
goto ex;
|
||||
}
|
||||
|
||||
bool parse_int16(const char *p, int16_t *v)
|
||||
{
|
||||
if (*p == '+' || *p == '-' || *p >= '0' && *p <= '9')
|
||||
@@ -630,34 +733,38 @@ bool parse_int16(const char *p, int16_t *v)
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32_t mask_from_bitcount(uint32_t zct)
|
||||
{
|
||||
return zct<32 ? ~((1u << zct) - 1) : 0;
|
||||
}
|
||||
static void mask_from_bitcount6_make(uint32_t zct, struct in6_addr *a)
|
||||
{
|
||||
if (zct >= 128)
|
||||
memset(a->s6_addr,0x00,16);
|
||||
else
|
||||
{
|
||||
int32_t n = (127 - zct) >> 3;
|
||||
memset(a->s6_addr,0xFF,n);
|
||||
memset(a->s6_addr+n,0x00,16-n);
|
||||
a->s6_addr[n] = ~((1u << (zct & 7)) - 1);
|
||||
}
|
||||
}
|
||||
static struct in6_addr ip6_mask[129];
|
||||
void mask_from_bitcount6_prepare(void)
|
||||
{
|
||||
for (int zct=0;zct<=128;zct++) mask_from_bitcount6_make(zct, ip6_mask+zct);
|
||||
}
|
||||
const struct in6_addr *mask_from_bitcount6(uint32_t zct)
|
||||
{
|
||||
return ip6_mask+zct;
|
||||
}
|
||||
|
||||
time_t boottime(void)
|
||||
{
|
||||
struct timespec ts;
|
||||
return clock_gettime(CLOCK_BOOT_OR_UPTIME, &ts) ? 0 : ts.tv_sec;
|
||||
}
|
||||
|
||||
|
||||
#ifdef __CYGWIN__
|
||||
uint32_t mask_from_bitcount(uint32_t zct)
|
||||
{
|
||||
return zct < 32 ? ~((1u << zct) - 1) : 0;
|
||||
}
|
||||
static void mask_from_bitcount6_make(uint32_t zct, struct in6_addr *a)
|
||||
{
|
||||
if (zct >= 128)
|
||||
memset(a->s6_addr, 0x00, 16);
|
||||
else
|
||||
{
|
||||
int32_t n = (127 - zct) >> 3;
|
||||
memset(a->s6_addr, 0xFF, n);
|
||||
memset(a->s6_addr + n, 0x00, 16 - n);
|
||||
a->s6_addr[n] = ~((1u << (zct & 7)) - 1);
|
||||
}
|
||||
}
|
||||
static struct in6_addr ip6_mask[129];
|
||||
void mask_from_bitcount6_prepare(void)
|
||||
{
|
||||
for (int zct = 0; zct <= 128; zct++) mask_from_bitcount6_make(zct, ip6_mask + zct);
|
||||
}
|
||||
const struct in6_addr *mask_from_bitcount6(uint32_t zct)
|
||||
{
|
||||
return ip6_mask + zct;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -12,6 +12,9 @@
|
||||
#include <fcntl.h>
|
||||
|
||||
#define UNARY_PLUS(v) (v>0 ? "+" : "")
|
||||
//#define MIN(v1,v2) ((v1)<(v2) ? (v1) : (v2))
|
||||
//#define MAX(v1,v2) ((v1)<(v2) ? (v2) : (v1))
|
||||
|
||||
|
||||
// this saves memory. sockaddr_storage is larger than required. it can be 128 bytes. sockaddr_in6 is 28 bytes.
|
||||
typedef union
|
||||
@@ -34,6 +37,8 @@ const char *strncasestr(const char *s,const char *find, size_t slen);
|
||||
bool is_identifier(const char *p);
|
||||
|
||||
ssize_t read_intr(int fd, void *buf, size_t count);
|
||||
bool fread_safe(void *ptr, size_t size, size_t nmemb, FILE *F, size_t *rd);
|
||||
char* fgets_safe(char *s, int size, FILE *stream);
|
||||
|
||||
bool load_file(const char *filename, off_t offset, void *buffer, size_t *buffer_size);
|
||||
bool save_file(const char *filename, const void *buffer, size_t buffer_size);
|
||||
@@ -104,13 +109,10 @@ void set_console_io_buffering(void);
|
||||
void close_std(void);
|
||||
void close_std_and_exit(int code);
|
||||
bool set_env_exedir(const char *argv0);
|
||||
bool realpath_any(const char *file, char *pabs);
|
||||
|
||||
bool parse_int16(const char *p, int16_t *v);
|
||||
|
||||
uint32_t mask_from_bitcount(uint32_t zct);
|
||||
void mask_from_bitcount6_prepare(void);
|
||||
const struct in6_addr *mask_from_bitcount6(uint32_t zct);
|
||||
|
||||
#ifdef CLOCK_BOOTTIME
|
||||
#define CLOCK_BOOT_OR_UPTIME CLOCK_BOOTTIME
|
||||
#elif defined(CLOCK_UPTIME)
|
||||
@@ -120,3 +122,9 @@ const struct in6_addr *mask_from_bitcount6(uint32_t zct);
|
||||
#endif
|
||||
|
||||
time_t boottime(void);
|
||||
|
||||
#ifdef __CYGWIN__
|
||||
uint32_t mask_from_bitcount(uint32_t zct);
|
||||
void mask_from_bitcount6_prepare(void);
|
||||
const struct in6_addr *mask_from_bitcount6(uint32_t zct);
|
||||
#endif
|
||||
|
||||
@@ -8,8 +8,10 @@ static bool addpool(hostlist_pool **hostlist, char **s, const char *end, int *ct
|
||||
{
|
||||
char *p=*s;
|
||||
|
||||
for (; p<end && (*p==' ' || *p=='\t') ; p++);
|
||||
*s = p;
|
||||
// comment line ?
|
||||
if ( *p != '#' && *p != ';' && *p != '/' && *p != '\r' && *p != '\n')
|
||||
if (p<end && *p != '#' && *p != ';' && *p != '/' && *p != '\r' && *p != '\n')
|
||||
{
|
||||
// advance until eol lowering all chars
|
||||
uint32_t flags = 0;
|
||||
@@ -60,22 +62,25 @@ bool AppendHostList(hostlist_pool **hostlist, const char *filename)
|
||||
{
|
||||
r = z_readfile(F,&zbuf,&zsize,0);
|
||||
fclose(F);
|
||||
if (r==Z_OK)
|
||||
if (r==Z_STREAM_END)
|
||||
{
|
||||
DLOG_CONDUP("zlib compression detected. uncompressed size : %zu\n", zsize);
|
||||
|
||||
p = zbuf;
|
||||
e = zbuf + zsize;
|
||||
while(p<e)
|
||||
if (zbuf)
|
||||
{
|
||||
if (!addpool(hostlist,&p,e,&ct))
|
||||
p = zbuf;
|
||||
e = zbuf + zsize;
|
||||
while(p<e)
|
||||
{
|
||||
DLOG_ERR("Not enough memory to store host list : %s\n", filename);
|
||||
free(zbuf);
|
||||
return false;
|
||||
if (!addpool(hostlist,&p,e,&ct))
|
||||
{
|
||||
DLOG_ERR("Not enough memory to store host list : %s\n", filename);
|
||||
free(zbuf);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
free(zbuf);
|
||||
}
|
||||
free(zbuf);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -87,7 +92,7 @@ bool AppendHostList(hostlist_pool **hostlist, const char *filename)
|
||||
{
|
||||
DLOG_CONDUP("loading plain text list\n");
|
||||
|
||||
while (fgets(s, sizeof(s), F))
|
||||
while (fgets_safe(s, sizeof(s), F))
|
||||
{
|
||||
p = s;
|
||||
if (!addpool(hostlist,&p,p+strlen(p),&ct))
|
||||
@@ -97,6 +102,12 @@ bool AppendHostList(hostlist_pool **hostlist, const char *filename)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (ferror(F))
|
||||
{
|
||||
DLOG_PERROR("AppendHostList");
|
||||
fclose(F);
|
||||
return false;
|
||||
}
|
||||
fclose(F);
|
||||
}
|
||||
|
||||
@@ -274,13 +285,15 @@ bool HostlistCheck(const struct desync_profile *dp, const char *host, bool no_ma
|
||||
static struct hostlist_file *RegisterHostlist_(struct hostlist_files_head *hostlists, struct hostlist_collection_head *hl_collection, const char *filename)
|
||||
{
|
||||
struct hostlist_file *hfile;
|
||||
char pabs[PATH_MAX];
|
||||
|
||||
if (filename)
|
||||
{
|
||||
if (!(hfile=hostlist_files_search(hostlists, filename)))
|
||||
if (!(hfile=hostlist_files_add(hostlists, filename)))
|
||||
if (!realpath(filename,pabs)) return NULL;
|
||||
if (!(hfile=hostlist_files_search(hostlists, pabs)))
|
||||
if (!(hfile=hostlist_files_add(hostlists, pabs)))
|
||||
return NULL;
|
||||
if (!hostlist_collection_search(hl_collection, filename))
|
||||
if (!hostlist_collection_search(hl_collection, pabs))
|
||||
if (!hostlist_collection_add(hl_collection, hfile))
|
||||
return NULL;
|
||||
}
|
||||
@@ -296,13 +309,11 @@ static struct hostlist_file *RegisterHostlist_(struct hostlist_files_head *hostl
|
||||
}
|
||||
struct hostlist_file *RegisterHostlist(struct desync_profile *dp, bool bExclude, const char *filename)
|
||||
{
|
||||
/*
|
||||
if (filename && !file_mod_time(filename))
|
||||
{
|
||||
DLOG_ERR("cannot access hostlist file '%s'\n",filename);
|
||||
return NULL;
|
||||
}
|
||||
*/
|
||||
return RegisterHostlist_(
|
||||
¶ms.hostlists,
|
||||
bExclude ? &dp->hl_collection_exclude : &dp->hl_collection,
|
||||
|
||||
92
nfq2/ipset.c
92
nfq2/ipset.c
@@ -11,36 +11,42 @@ static bool addpool(ipset *ips, char **s, const char *end, int *ct)
|
||||
struct cidr4 c4;
|
||||
struct cidr6 c6;
|
||||
|
||||
for (p=*s; p<end && *p && *p!=' ' && *p!='\t' && *p!='\r' && *p != '\n'; p++);
|
||||
|
||||
// comment line
|
||||
if (!(**s == '#' || **s == ';' || **s == '/' || **s == '\r' || **s == '\n' ))
|
||||
for (p=*s; p<end && (*p==' ' || *p=='\t') ; p++);
|
||||
if (p<end)
|
||||
{
|
||||
l = p-*s;
|
||||
if (l>=sizeof(cidr)) l=sizeof(cidr)-1;
|
||||
memcpy(cidr,*s,l);
|
||||
cidr[l]=0;
|
||||
// comment line
|
||||
if (!(*p == '#' || *p == ';' || *p == '/' || *p == '\r' || *p == '\n' ))
|
||||
{
|
||||
*s=p;
|
||||
// advance to the token's end
|
||||
for (; p<end && *p && *p!=' ' && *p!='\t' && *p!='\r' && *p != '\n'; p++);
|
||||
|
||||
if (parse_cidr4(cidr,&c4))
|
||||
{
|
||||
if (!ipset4AddCidr(&ips->ips4, &c4))
|
||||
l = p-*s;
|
||||
if (l>=sizeof(cidr)) l=sizeof(cidr)-1;
|
||||
memcpy(cidr,*s,l);
|
||||
cidr[l]=0;
|
||||
|
||||
if (parse_cidr4(cidr,&c4))
|
||||
{
|
||||
ipsetDestroy(ips);
|
||||
return false;
|
||||
if (!ipset4AddCidr(&ips->ips4, &c4))
|
||||
{
|
||||
ipsetDestroy(ips);
|
||||
return false;
|
||||
}
|
||||
if (ct) (*ct)++;
|
||||
}
|
||||
if (ct) (*ct)++;
|
||||
}
|
||||
else if (parse_cidr6(cidr,&c6))
|
||||
{
|
||||
if (!ipset6AddCidr(&ips->ips6, &c6))
|
||||
else if (parse_cidr6(cidr,&c6))
|
||||
{
|
||||
ipsetDestroy(ips);
|
||||
return false;
|
||||
if (!ipset6AddCidr(&ips->ips6, &c6))
|
||||
{
|
||||
ipsetDestroy(ips);
|
||||
return false;
|
||||
}
|
||||
if (ct) (*ct)++;
|
||||
}
|
||||
if (ct) (*ct)++;
|
||||
else
|
||||
DLOG_ERR("bad ip or subnet : %s\n",cidr);
|
||||
}
|
||||
else
|
||||
DLOG_ERR("bad ip or subnet : %s\n",cidr);
|
||||
}
|
||||
|
||||
// skip remaining non-eol chars
|
||||
@@ -77,22 +83,25 @@ static bool AppendIpset(ipset *ips, const char *filename)
|
||||
{
|
||||
r = z_readfile(F,&zbuf,&zsize,0);
|
||||
fclose(F);
|
||||
if (r==Z_OK)
|
||||
if (r==Z_STREAM_END)
|
||||
{
|
||||
DLOG_CONDUP("zlib compression detected. uncompressed size : %zu\n", zsize);
|
||||
|
||||
p = zbuf;
|
||||
e = zbuf + zsize;
|
||||
while(p<e)
|
||||
if (zbuf)
|
||||
{
|
||||
if (!addpool(ips,&p,e,&ct))
|
||||
p = zbuf;
|
||||
e = zbuf + zsize;
|
||||
while(p<e)
|
||||
{
|
||||
DLOG_ERR("Not enough memory to store ipset : %s\n", filename);
|
||||
free(zbuf);
|
||||
return false;
|
||||
if (!addpool(ips,&p,e,&ct))
|
||||
{
|
||||
DLOG_ERR("Not enough memory to store ipset : %s\n", filename);
|
||||
free(zbuf);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
free(zbuf);
|
||||
}
|
||||
free(zbuf);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -104,7 +113,7 @@ static bool AppendIpset(ipset *ips, const char *filename)
|
||||
{
|
||||
DLOG_CONDUP("loading plain text list\n");
|
||||
|
||||
while (fgets(s, sizeof(s)-1, F))
|
||||
while (fgets_safe(s, sizeof(s)-1, F))
|
||||
{
|
||||
p = s;
|
||||
if (!addpool(ips,&p,p+strlen(p),&ct))
|
||||
@@ -114,6 +123,12 @@ static bool AppendIpset(ipset *ips, const char *filename)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (ferror(F))
|
||||
{
|
||||
DLOG_PERROR("AppendIpset");
|
||||
fclose(F);
|
||||
return false;
|
||||
}
|
||||
fclose(F);
|
||||
}
|
||||
|
||||
@@ -176,7 +191,7 @@ bool LoadAllIpsets()
|
||||
|
||||
static bool SearchIpset(const ipset *ips, const struct in_addr *ipv4, const struct in6_addr *ipv6)
|
||||
{
|
||||
char s_ip[40];
|
||||
char s_ip[INET6_ADDRSTRLEN];
|
||||
bool bInSet=false;
|
||||
|
||||
if (!!ipv4 != !!ipv6)
|
||||
@@ -272,12 +287,15 @@ bool IpsetCheck(
|
||||
static struct ipset_file *RegisterIpset_(struct ipset_files_head *ipsets, struct ipset_collection_head *ips_collection, const char *filename)
|
||||
{
|
||||
struct ipset_file *hfile;
|
||||
char pabs[PATH_MAX];
|
||||
|
||||
if (filename)
|
||||
{
|
||||
if (!(hfile=ipset_files_search(ipsets, filename)))
|
||||
if (!(hfile=ipset_files_add(ipsets, filename)))
|
||||
if (!realpath(filename,pabs)) return NULL;
|
||||
if (!(hfile=ipset_files_search(ipsets, pabs)))
|
||||
if (!(hfile=ipset_files_add(ipsets, pabs)))
|
||||
return NULL;
|
||||
if (!ipset_collection_search(ips_collection, filename))
|
||||
if (!ipset_collection_search(ips_collection, pabs))
|
||||
if (!ipset_collection_add(ips_collection, hfile))
|
||||
return NULL;
|
||||
}
|
||||
|
||||
52
nfq2/kavl.h
52
nfq2/kavl.h
@@ -92,6 +92,19 @@ int main(void) {
|
||||
} \
|
||||
if (cnt_) *cnt_ = cnt; \
|
||||
return (__type*)p; \
|
||||
} \
|
||||
__scope __type *kavl_interval_##suf(const __type *root, const __type *x, __type **lower, __type **upper) { \
|
||||
const __type *p = root, *l = 0, *u = 0; \
|
||||
while (p != 0) { \
|
||||
int cmp; \
|
||||
cmp = __cmp(x, p); \
|
||||
if (cmp < 0) u = p, p = p->__head.p[0]; \
|
||||
else if (cmp > 0) l = p, p = p->__head.p[1]; \
|
||||
else { l = u = p; break; } \
|
||||
} \
|
||||
if (lower) *lower = (__type*)l; \
|
||||
if (upper) *upper = (__type*)u; \
|
||||
return (__type*)p; \
|
||||
}
|
||||
|
||||
#define __KAVL_ROTATE(suf, __type, __head) \
|
||||
@@ -271,43 +284,42 @@ int main(void) {
|
||||
|
||||
#define __KAVL_ITR(suf, __scope, __type, __head, __cmp) \
|
||||
struct kavl_itr_##suf { \
|
||||
const __type *stack[KAVL_MAX_DEPTH], **top, *right; /* _right_ points to the right child of *top */ \
|
||||
const __type *stack[KAVL_MAX_DEPTH], **top; \
|
||||
}; \
|
||||
__scope void kavl_itr_first_##suf(const __type *root, struct kavl_itr_##suf *itr) { \
|
||||
const __type *p; \
|
||||
for (itr->top = itr->stack - 1, p = root; p; p = p->__head.p[0]) \
|
||||
*++itr->top = p; \
|
||||
itr->right = (*itr->top)->__head.p[1]; \
|
||||
} \
|
||||
__scope int kavl_itr_find_##suf(const __type *root, const __type *x, struct kavl_itr_##suf *itr) { \
|
||||
const __type *p = root; \
|
||||
itr->top = itr->stack - 1; \
|
||||
while (p != 0) { \
|
||||
int cmp; \
|
||||
*++itr->top = p; \
|
||||
cmp = __cmp(x, p); \
|
||||
if (cmp < 0) *++itr->top = p, p = p->__head.p[0]; \
|
||||
if (cmp < 0) p = p->__head.p[0]; \
|
||||
else if (cmp > 0) p = p->__head.p[1]; \
|
||||
else break; \
|
||||
} \
|
||||
if (p) { \
|
||||
*++itr->top = p; \
|
||||
itr->right = p->__head.p[1]; \
|
||||
return 1; \
|
||||
} else if (itr->top >= itr->stack) { \
|
||||
itr->right = (*itr->top)->__head.p[1]; \
|
||||
return 0; \
|
||||
} else return 0; \
|
||||
return p? 1 : 0; \
|
||||
} \
|
||||
__scope int kavl_itr_next_##suf(struct kavl_itr_##suf *itr) { \
|
||||
for (;;) { \
|
||||
const __type *p; \
|
||||
for (p = itr->right, --itr->top; p; p = p->__head.p[0]) \
|
||||
__scope int kavl_itr_next_bidir_##suf(struct kavl_itr_##suf *itr, int dir) { \
|
||||
const __type *p; \
|
||||
if (itr->top < itr->stack) return 0; \
|
||||
dir = !!dir; \
|
||||
p = (*itr->top)->__head.p[dir]; \
|
||||
if (p) { /* go down */ \
|
||||
for (; p; p = p->__head.p[!dir]) \
|
||||
*++itr->top = p; \
|
||||
if (itr->top < itr->stack) return 0; \
|
||||
itr->right = (*itr->top)->__head.p[1]; \
|
||||
return 1; \
|
||||
} else { /* go up */ \
|
||||
do { \
|
||||
p = *itr->top--; \
|
||||
} while (itr->top >= itr->stack && p == (*itr->top)->__head.p[dir]); \
|
||||
return itr->top < itr->stack? 0 : 1; \
|
||||
} \
|
||||
}
|
||||
} \
|
||||
|
||||
/**
|
||||
* Insert a node to the tree
|
||||
@@ -332,6 +344,7 @@ int main(void) {
|
||||
* @return node equal to _x_ if present, or NULL if absent
|
||||
*/
|
||||
#define kavl_find(suf, root, x, cnt) kavl_find_##suf(root, x, cnt)
|
||||
#define kavl_interval(suf, root, x, lower, upper) kavl_interval_##suf(root, x, lower, upper)
|
||||
|
||||
/**
|
||||
* Delete a node from the tree
|
||||
@@ -376,7 +389,8 @@ int main(void) {
|
||||
*
|
||||
* @return 1 if there is a next object; 0 otherwise
|
||||
*/
|
||||
#define kavl_itr_next(suf, itr) kavl_itr_next_##suf(itr)
|
||||
#define kavl_itr_next(suf, itr) kavl_itr_next_bidir_##suf(itr, 1)
|
||||
#define kavl_itr_prev(suf, itr) kavl_itr_next_bidir_##suf(itr, 0)
|
||||
|
||||
/**
|
||||
* Return the pointer at the iterator
|
||||
|
||||
124
nfq2/lua.c
124
nfq2/lua.c
@@ -42,6 +42,7 @@ typedef struct _SOCKET_ADDRESS {
|
||||
#include "params.h"
|
||||
#include "gzip.h"
|
||||
#include "helpers.h"
|
||||
#include "nfqws.h"
|
||||
#include "conntrack.h"
|
||||
#include "crypto/sha.h"
|
||||
#include "crypto/aes-gcm.h"
|
||||
@@ -685,8 +686,8 @@ static int luacall_aes_gcm(lua_State *L)
|
||||
luaL_error(L, "aes_gcm: wrong key length %u. should be 16,24,32.", (unsigned)key_len);
|
||||
size_t iv_len;
|
||||
const uint8_t *iv = (uint8_t*)lua_reqlstring(L,3,&iv_len);
|
||||
if (iv_len!=12)
|
||||
luaL_error(L, "aes_gcm: wrong iv length %u. should be 12.", (unsigned)iv_len);
|
||||
if (!iv_len)
|
||||
luaL_error(L, "aes_gcm: zero iv length");
|
||||
size_t input_len;
|
||||
const uint8_t *input = (uint8_t*)lua_reqlstring(L,4,&input_len);
|
||||
size_t add_len=0;
|
||||
@@ -1247,6 +1248,7 @@ void lua_push_blob(lua_State *L, int idx_desync, const char *blob)
|
||||
lua_pop(L,1);
|
||||
lua_getglobal(L, blob);
|
||||
}
|
||||
lua_tostring(L,-1);
|
||||
}
|
||||
void lua_pushf_blob(lua_State *L, int idx_desync, const char *field, const char *blob)
|
||||
{
|
||||
@@ -1656,7 +1658,7 @@ void lua_pushf_ctrack_pos(lua_State *L, const t_ctrack *ctrack, const t_ctrack_p
|
||||
lua_pushf_lint(L,"pdcounter", pos->pdcounter);
|
||||
lua_pushf_lint(L,"pbcounter", pos->pbcounter);
|
||||
if (pos->ip6flow) lua_pushf_int(L,"ip6_flow", pos->ip6flow);
|
||||
if (ctrack->ipproto == IPPROTO_TCP)
|
||||
if (ctrack->pos.ipproto == IPPROTO_TCP)
|
||||
{
|
||||
lua_pushliteral(L, "tcp");
|
||||
lua_createtable(L, 0, 11);
|
||||
@@ -1778,7 +1780,10 @@ void lua_pushf_args(lua_State *L, const struct str2_list_head *args, int idx_des
|
||||
lua_push_blob(L, idx_desync, val+1);
|
||||
lua_Integer len = lua_rawlen(L, -1);
|
||||
lua_pop(L,1);
|
||||
lua_pushf_int(L, var, len);
|
||||
lua_pushstring(L, var);
|
||||
lua_pushinteger(L, len);
|
||||
lua_tostring(L,-1); // force string type in arg
|
||||
lua_rawset(L,-3);
|
||||
}
|
||||
else
|
||||
lua_pushf_str(L, var, val);
|
||||
@@ -1863,7 +1868,7 @@ static bool lua_reconstruct_ip6exthdr(lua_State *L, int idx, struct ip6_hdr *ip6
|
||||
{
|
||||
LUA_STACK_GUARD_ENTER(L)
|
||||
// proto = last header type
|
||||
if (*len<sizeof(struct tcphdr)) return false;
|
||||
if (*len<sizeof(struct ip6_hdr)) return false;
|
||||
|
||||
uint8_t *last_proto = &ip6->ip6_ctlun.ip6_un1.ip6_un1_nxt;
|
||||
size_t filled = sizeof(struct ip6_hdr);
|
||||
@@ -1900,11 +1905,24 @@ static bool lua_reconstruct_ip6exthdr(lua_State *L, int idx, struct ip6_hdr *ip6
|
||||
lua_getfield(L,-1, "data");
|
||||
if (lua_type(L,-1)!=LUA_TSTRING) goto err;
|
||||
if (!(p=(uint8_t*)lua_tolstring(L,-1,&l))) l=0;
|
||||
if (!l || (l+2)>left || ((type==IPPROTO_AH) ? (l<6 || ((l+2) & 3)) : ((l+2) & 7))) goto err;
|
||||
memcpy(data+2,p,l);
|
||||
l+=2;
|
||||
|
||||
if (l<6 || (l+2)>left) goto err;
|
||||
if (type==IPPROTO_AH)
|
||||
{
|
||||
if (l>=1024 || ((l+2) & 3)) goto err;
|
||||
memcpy(data+2,p,l);
|
||||
l+=2;
|
||||
data[1] = (l>>2)-2;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (l>=2048 || ((l+2) & 7)) goto err;
|
||||
memcpy(data+2,p,l);
|
||||
l+=2;
|
||||
data[1] = (l>>3)-1;
|
||||
}
|
||||
|
||||
data[0] = next; // may be overwritten later
|
||||
data[1] = (type==IPPROTO_AH) ? (l>>2)-2 : (l>>3)-1;
|
||||
if (!preserve_next) *last_proto = type;
|
||||
last_proto = data; // first byte of header holds type
|
||||
left -= l; data += l; filled += l;
|
||||
@@ -2013,7 +2031,7 @@ bool lua_reconstruct_iphdr(lua_State *L, int idx, struct ip *ip, size_t *len)
|
||||
|
||||
LUA_STACK_GUARD_ENTER(L)
|
||||
|
||||
if (*len<sizeof(struct ip) || lua_type(L,-1)!=LUA_TTABLE) return false;
|
||||
if (*len<sizeof(struct ip) || lua_type(L,idx)!=LUA_TTABLE) return false;
|
||||
|
||||
ip->ip_v = IPVERSION;
|
||||
|
||||
@@ -2183,7 +2201,7 @@ err:
|
||||
}
|
||||
bool lua_reconstruct_tcphdr(lua_State *L, int idx, struct tcphdr *tcp, size_t *len)
|
||||
{
|
||||
if (*len<sizeof(struct tcphdr) || lua_type(L,-1)!=LUA_TTABLE) return false;
|
||||
if (*len<sizeof(struct tcphdr) || lua_type(L,idx)!=LUA_TTABLE) return false;
|
||||
|
||||
LUA_STACK_GUARD_ENTER(L)
|
||||
|
||||
@@ -2258,7 +2276,7 @@ static int luacall_reconstruct_tcphdr(lua_State *L)
|
||||
|
||||
bool lua_reconstruct_udphdr(lua_State *L, int idx, struct udphdr *udp)
|
||||
{
|
||||
if (lua_type(L,-1)!=LUA_TTABLE) return false;
|
||||
if (lua_type(L,idx)!=LUA_TTABLE) return false;
|
||||
|
||||
LUA_STACK_GUARD_ENTER(L)
|
||||
|
||||
@@ -2302,7 +2320,7 @@ static int luacall_reconstruct_udphdr(lua_State *L)
|
||||
|
||||
bool lua_reconstruct_icmphdr(lua_State *L, int idx, struct icmp46 *icmp)
|
||||
{
|
||||
if (lua_type(L,-1)!=LUA_TTABLE) return false;
|
||||
if (lua_type(L,idx)!=LUA_TTABLE) return false;
|
||||
|
||||
LUA_STACK_GUARD_ENTER(L)
|
||||
|
||||
@@ -2538,7 +2556,7 @@ bool lua_reconstruct_dissect(lua_State *L, int idx, uint8_t *buf, size_t *len, b
|
||||
}
|
||||
else if (udp)
|
||||
{
|
||||
sz = (uint16_t)(lpayload+sizeof(struct udphdr));
|
||||
sz = lpayload+sizeof(struct udphdr);
|
||||
if (sz>0xFFFF)
|
||||
{
|
||||
DLOG_ERR("reconstruct_dissect: invalid payload length\n");
|
||||
@@ -2568,12 +2586,13 @@ bool lua_reconstruct_dissect(lua_State *L, int idx, uint8_t *buf, size_t *len, b
|
||||
DLOG_ERR("ipv4 frag : invalid ip_len\n");
|
||||
goto err;
|
||||
}
|
||||
if (frag_start>l)
|
||||
size_t frag_len = iplen-l3;
|
||||
if ((frag_start+frag_len)>l)
|
||||
{
|
||||
DLOG_ERR("ipv4 frag : fragment offset is outside of the packet\n");
|
||||
DLOG_ERR("ipv4 frag : fragment end is outside of the packet\n");
|
||||
goto err;
|
||||
}
|
||||
if (off) memmove(buf+l3,buf+l3+off,iplen-l3);
|
||||
if (off) memmove(buf+l3,buf+frag_start,frag_len);
|
||||
l = iplen; // shrink packet to iplen
|
||||
}
|
||||
else
|
||||
@@ -2811,7 +2830,7 @@ static int luacall_ntop(lua_State *L)
|
||||
{
|
||||
size_t l;
|
||||
const char *p;
|
||||
char s[40];
|
||||
char s[INET6_ADDRSTRLEN];
|
||||
int af=0;
|
||||
|
||||
lua_check_argc(L,"ntop",1);
|
||||
@@ -2831,9 +2850,10 @@ static int luacall_ntop(lua_State *L)
|
||||
lua_pushnil(L);
|
||||
return 1;
|
||||
}
|
||||
if (!inet_ntop(af,p,s,sizeof(s)))
|
||||
luaL_error(L, "inet_ntop error");
|
||||
lua_pushstring(L,s);
|
||||
if (inet_ntop(af,p,s,sizeof(s)))
|
||||
lua_pushstring(L,s);
|
||||
else
|
||||
lua_pushnil(L);
|
||||
|
||||
LUA_STACK_GUARD_RETURN(L,1)
|
||||
}
|
||||
@@ -3137,7 +3157,7 @@ static int lua_get_ifaddrs(lua_State *L)
|
||||
struct ifreq ifr;
|
||||
const char *ifname;
|
||||
#ifdef __CYGWIN__
|
||||
char ifname_buf[16];
|
||||
char ifname_buf[IFNAMSIZ];
|
||||
#endif
|
||||
memset(&ifr,0,sizeof(ifr));
|
||||
|
||||
@@ -3178,6 +3198,7 @@ static int lua_get_ifaddrs(lua_State *L)
|
||||
#ifdef HAS_FILTER_SSID
|
||||
lua_pushf_str(L, "ssid", wlan_ssid_search_ifname(ifname));
|
||||
#endif
|
||||
memset(ifr.ifr_name,0,sizeof(ifr.ifr_name));
|
||||
strncpy(ifr.ifr_name, ifname, IFNAMSIZ - 1);
|
||||
if (sock>=0 && !ioctl(sock, SIOCGIFMTU, &ifr))
|
||||
lua_pushf_int(L, "mtu", ifr.ifr_mtu);
|
||||
@@ -3329,7 +3350,6 @@ static int luacall_tls_mod(lua_State *L)
|
||||
int argc=lua_gettop(L);
|
||||
|
||||
size_t fake_tls_len;
|
||||
bool bRes;
|
||||
const uint8_t *fake_tls = (uint8_t*)lua_reqlstring(L,1,&fake_tls_len);
|
||||
const char *modlist = lua_reqstring(L,2);
|
||||
|
||||
@@ -3349,8 +3369,10 @@ static int luacall_tls_mod(lua_State *L)
|
||||
uint8_t *newtls = lua_newuserdata(L, maxlen);
|
||||
|
||||
memcpy(newtls, fake_tls, newlen);
|
||||
bRes = TLSMod(&mod, payload, payload_len, newtls, &newlen, maxlen);
|
||||
lua_pushlstring(L,(char*)newtls,newlen);
|
||||
if (TLSMod(&mod, payload, payload_len, newtls, &newlen, maxlen))
|
||||
lua_pushlstring(L,(char*)newtls,newlen);
|
||||
else
|
||||
lua_pushnil(L);
|
||||
|
||||
lua_remove(L,-2);
|
||||
}
|
||||
@@ -3358,11 +3380,9 @@ static int luacall_tls_mod(lua_State *L)
|
||||
{
|
||||
// no mod. push it back
|
||||
lua_pushlstring(L,(char*)fake_tls,fake_tls_len);
|
||||
bRes = true;
|
||||
}
|
||||
lua_pushboolean(L, bRes);
|
||||
|
||||
LUA_STACK_GUARD_RETURN(L,2)
|
||||
LUA_STACK_GUARD_RETURN(L,1)
|
||||
}
|
||||
|
||||
struct userdata_zs
|
||||
@@ -3466,7 +3486,7 @@ static int luacall_gunzip_inflate(lua_State *L)
|
||||
size_t increment = bufchunk / 2;
|
||||
if (increment < Z_INFL_BUF_INCREMENT) increment = Z_INFL_BUF_INCREMENT;
|
||||
|
||||
do
|
||||
for(;;)
|
||||
{
|
||||
if ((bufsize - size) < BUFMIN)
|
||||
{
|
||||
@@ -3489,11 +3509,20 @@ static int luacall_gunzip_inflate(lua_State *L)
|
||||
}
|
||||
uzs->zs.avail_out = bufsize - size;
|
||||
uzs->zs.next_out = buf + size;
|
||||
r = inflate(&uzs->zs, Z_NO_FLUSH);
|
||||
if (r != Z_OK && r != Z_STREAM_END) goto zerr;
|
||||
size = bufsize - uzs->zs.avail_out;
|
||||
} while (r == Z_OK && uzs->zs.avail_in);
|
||||
|
||||
r = inflate(&uzs->zs, Z_NO_FLUSH);
|
||||
|
||||
size = bufsize - uzs->zs.avail_out;
|
||||
if (r==Z_STREAM_END) break;
|
||||
if (r==Z_BUF_ERROR)
|
||||
{
|
||||
if (uzs->zs.avail_in)
|
||||
goto zerr;
|
||||
else
|
||||
break; // OK
|
||||
}
|
||||
if (r!=Z_OK) goto zerr;
|
||||
}
|
||||
lua_pushlstring(L, (const char*)buf, size);
|
||||
lua_pushboolean(L, r==Z_STREAM_END);
|
||||
end:
|
||||
@@ -3516,7 +3545,7 @@ static void z_free(voidpf opaque, voidpf address)
|
||||
static int luacall_gzip_init(lua_State *L)
|
||||
{
|
||||
// gzip_init(windowBits, level, memlevel) return zstream
|
||||
lua_check_argc_range(L,"gunzip_init",0,3);
|
||||
lua_check_argc_range(L,"gzip_init",0,3);
|
||||
|
||||
LUA_STACK_GUARD_ENTER(L)
|
||||
|
||||
@@ -3567,7 +3596,7 @@ static int luacall_gzip_deflate(lua_State *L)
|
||||
|
||||
int argc=lua_gettop(L);
|
||||
size_t l=0;
|
||||
int r;
|
||||
int r, flush;
|
||||
size_t bufsize=0, size=0;
|
||||
uint8_t *buf=NULL, *newbuf;
|
||||
struct userdata_zs *uzs = lua_uzs(L, 1, false);
|
||||
@@ -3580,7 +3609,8 @@ static int luacall_gzip_deflate(lua_State *L)
|
||||
size_t increment = bufchunk / 2;
|
||||
if (increment < Z_DEFL_BUF_INCREMENT) increment = Z_DEFL_BUF_INCREMENT;
|
||||
|
||||
do
|
||||
flush = l ? Z_NO_FLUSH : Z_FINISH;
|
||||
for(;;)
|
||||
{
|
||||
if ((bufsize - size) < BUFMIN)
|
||||
{
|
||||
@@ -3603,10 +3633,19 @@ static int luacall_gzip_deflate(lua_State *L)
|
||||
}
|
||||
uzs->zs.avail_out = bufsize - size;
|
||||
uzs->zs.next_out = buf + size;
|
||||
r = deflate(&uzs->zs, l ? Z_NO_FLUSH : Z_FINISH);
|
||||
if (r != Z_OK && r != Z_STREAM_END) goto zerr;
|
||||
|
||||
r = deflate(&uzs->zs, flush);
|
||||
|
||||
size = bufsize - uzs->zs.avail_out;
|
||||
} while (r == Z_OK && (uzs->zs.avail_in || !uzs->zs.avail_out));
|
||||
if (r==Z_STREAM_END) break;
|
||||
if (r==Z_OK)
|
||||
{
|
||||
if (uzs->zs.avail_out && !uzs->zs.avail_in && flush != Z_FINISH)
|
||||
break;
|
||||
}
|
||||
else
|
||||
goto zerr;
|
||||
}
|
||||
|
||||
lua_pushlstring(L, (const char*)buf, size);
|
||||
lua_pushboolean(L, r==Z_STREAM_END);
|
||||
@@ -3687,7 +3726,7 @@ static void lua_xtime(lua_State *L, struct tm *(*timefunc)(const time_t *,struct
|
||||
lua_pushf_int(L,"isdst", t.tm_isdst);
|
||||
lua_pushf_str(L,"zone", t.tm_zone);
|
||||
|
||||
char s[24];
|
||||
char s[40];
|
||||
snprintf(s,sizeof(s),"%02d.%02d.%04d %02d:%02d:%02d", t.tm_mday, t.tm_mon + 1, t.tm_year + 1900, t.tm_hour, t.tm_min, t.tm_sec);
|
||||
lua_pushf_str(L,"str", s);
|
||||
}
|
||||
@@ -3783,7 +3822,7 @@ static void lua_perror(lua_State *L)
|
||||
}
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
static int lua_panic (lua_State *L)
|
||||
static int lua_panic(lua_State *L)
|
||||
{
|
||||
lua_perror(L);
|
||||
DLOG_ERR("LUA PANIC: THIS IS FATAL. DYING.\n");
|
||||
@@ -3934,7 +3973,7 @@ static int luaL_doZfile(lua_State *L, const char *filename)
|
||||
luaL_error(L, "could not open lua file '%s'", fname);
|
||||
r = z_readfile(F, &buf, &size, 0);
|
||||
fclose(F);
|
||||
if (r != Z_OK)
|
||||
if (r != Z_STREAM_END)
|
||||
luaL_error(L, "could not unzip lua file '%s'", fname);
|
||||
r = luaL_loadbuffer(L, buf, size, fname);
|
||||
free(buf);
|
||||
@@ -3952,6 +3991,7 @@ static bool lua_init_scripts(void)
|
||||
|
||||
LIST_FOREACH(str, ¶ms.lua_init_scripts, next)
|
||||
{
|
||||
if (bQuit) return false;
|
||||
if (params.debug)
|
||||
{
|
||||
if (str->str[0]=='@')
|
||||
|
||||
218
nfq2/nfqws.c
218
nfq2/nfqws.c
@@ -43,6 +43,7 @@
|
||||
#endif
|
||||
|
||||
#ifdef __linux__
|
||||
#include <sys/ioctl.h>
|
||||
#include <libnetfilter_queue/libnetfilter_queue.h>
|
||||
#define NF_DROP 0
|
||||
#define NF_ACCEPT 1
|
||||
@@ -56,6 +57,7 @@ volatile sig_atomic_t bQuit = false;
|
||||
|
||||
static void onhup(int sig)
|
||||
{
|
||||
// async safe
|
||||
if (bQuit) return;
|
||||
|
||||
const char *msg = "HUP received ! Lists will be reloaded.\n";
|
||||
@@ -70,13 +72,13 @@ static void ReloadCheck()
|
||||
if (!LoadAllHostLists())
|
||||
{
|
||||
DLOG_ERR("hostlists load failed. this is fatal.\n");
|
||||
exit(1);
|
||||
exit(200);
|
||||
}
|
||||
ResetAllIpsetModTime();
|
||||
if (!LoadAllIpsets())
|
||||
{
|
||||
DLOG_ERR("ipset load failed. this is fatal.\n");
|
||||
exit(1);
|
||||
exit(200);
|
||||
}
|
||||
bReload = false;
|
||||
}
|
||||
@@ -84,6 +86,7 @@ static void ReloadCheck()
|
||||
|
||||
static void onusr1(int sig)
|
||||
{
|
||||
// this is debug-only signal. no async safety
|
||||
if (bQuit) return;
|
||||
|
||||
printf("\nCONNTRACK DUMP\n");
|
||||
@@ -92,6 +95,7 @@ static void onusr1(int sig)
|
||||
}
|
||||
static void onusr2(int sig)
|
||||
{
|
||||
// this is debug-only signal. no async safety
|
||||
if (bQuit) return;
|
||||
|
||||
printf("\nHOSTFAIL POOL DUMP\n");
|
||||
@@ -108,6 +112,7 @@ static void onusr2(int sig)
|
||||
}
|
||||
static void onint(int sig)
|
||||
{
|
||||
// theoretically lua_sethook is not async-safe. but it's one-time signal
|
||||
if (bQuit) return;
|
||||
const char *msg = "INT received !\n";
|
||||
size_t wr = write(1, msg, strlen(msg));
|
||||
@@ -116,6 +121,7 @@ static void onint(int sig)
|
||||
}
|
||||
static void onterm(int sig)
|
||||
{
|
||||
// theoretically lua_sethook is not async-safe. but it's one-time signal
|
||||
if (bQuit) return;
|
||||
const char *msg = "TERM received !\n";
|
||||
size_t wr = write(1, msg, strlen(msg));
|
||||
@@ -178,7 +184,7 @@ static void fuzzPacketData(unsigned int count)
|
||||
*packet = *packet ? (*packet & 1) ? 0x40 : 0x60 | (*packet & 0x0F) : (uint8_t)random();
|
||||
}
|
||||
modlen = random()%(sizeof(mod)+1);
|
||||
verdict = processPacketData(&mark,random()%1 ? "ifin" : NULL,random()%1 ? "ifout" : NULL,packet,len,mod,&modlen);
|
||||
verdict = processPacketData(&mark,(random() & 1) ? "ifin" : NULL,(random() & 1) ? "ifout" : NULL,packet,len,mod,&modlen);
|
||||
free(packet);
|
||||
}
|
||||
}
|
||||
@@ -235,6 +241,13 @@ static int write_pidfile(FILE **Fpid)
|
||||
|
||||
|
||||
#ifdef __linux__
|
||||
|
||||
struct nfq_cb_data
|
||||
{
|
||||
uint8_t *mod;
|
||||
int sock;
|
||||
};
|
||||
|
||||
// cookie must point to mod buffer with size RECONSTRUCT_MAX_SIZE
|
||||
static int nfq_cb(struct nfq_q_handle *qh, struct nfgenmsg *nfmsg, struct nfq_data *nfa, void *cookie)
|
||||
{
|
||||
@@ -242,27 +255,32 @@ static int nfq_cb(struct nfq_q_handle *qh, struct nfgenmsg *nfmsg, struct nfq_da
|
||||
size_t len;
|
||||
struct nfqnl_msg_packet_hdr *ph;
|
||||
uint8_t *data;
|
||||
uint32_t ifidx_out, ifidx_in;
|
||||
char ifout[IFNAMSIZ], ifin[IFNAMSIZ];
|
||||
size_t modlen;
|
||||
uint8_t *mod = (uint8_t*)cookie;
|
||||
struct nfq_cb_data *cbdata = (struct nfq_cb_data*)cookie;
|
||||
uint32_t mark;
|
||||
struct ifreq ifr_in, ifr_out;
|
||||
|
||||
ph = nfq_get_msg_packet_hdr(nfa);
|
||||
id = ph ? ntohl(ph->packet_id) : 0;
|
||||
if (!(ph = nfq_get_msg_packet_hdr(nfa))) return 0; // should not happen
|
||||
id = ntohl(ph->packet_id);
|
||||
|
||||
mark = nfq_get_nfmark(nfa);
|
||||
ilen = nfq_get_payload(nfa, &data);
|
||||
|
||||
ifidx_out = nfq_get_outdev(nfa);
|
||||
*ifout = 0;
|
||||
if (ifidx_out) if_indextoname(ifidx_out, ifout);
|
||||
// if_indextoname creates socket, calls ioctl, closes socket
|
||||
// code below prevents socket() and close() syscalls on every packet
|
||||
// this saves CPU 5-10 times
|
||||
|
||||
ifidx_in = nfq_get_indev(nfa);
|
||||
*ifin = 0;
|
||||
if (ifidx_in) if_indextoname(ifidx_in, ifin);
|
||||
*ifr_out.ifr_name = 0;
|
||||
ifr_out.ifr_ifindex = nfq_get_outdev(nfa);
|
||||
if (ifr_out.ifr_ifindex && ioctl(cbdata->sock, SIOCGIFNAME, &ifr_out)<0)
|
||||
DLOG_PERROR("ioctl(SIOCGIFNAME)");
|
||||
|
||||
DLOG("\npacket: id=%d len=%d mark=%08X ifin=%s(%u) ifout=%s(%u)\n", id, ilen, mark, ifin, ifidx_in, ifout, ifidx_out);
|
||||
*ifr_in.ifr_name = 0;
|
||||
ifr_in.ifr_ifindex = nfq_get_indev(nfa);
|
||||
if (ifr_in.ifr_ifindex && ioctl(cbdata->sock, SIOCGIFNAME, &ifr_in)<0)
|
||||
DLOG_PERROR("ioctl(SIOCGIFNAME)");
|
||||
|
||||
DLOG("\npacket: id=%d len=%d mark=%08X ifin=%s(%u) ifout=%s(%u)\n", id, ilen, mark, ifr_in.ifr_name, ifr_in.ifr_ifindex, ifr_out.ifr_name, ifr_out.ifr_ifindex);
|
||||
|
||||
if (ilen >= 0)
|
||||
{
|
||||
@@ -272,12 +290,12 @@ static int nfq_cb(struct nfq_q_handle *qh, struct nfgenmsg *nfmsg, struct nfq_da
|
||||
// to support increased sizes use separate mod buffer
|
||||
// this is not a problem because only LUA code can trigger VERDICT_MODIFY (and postnat workaround too, once a connection if first packet is dropped)
|
||||
// in case of VERIDCT_MODIFY packet is always reconstructed from dissect, so no difference where to save the data => no performance loss
|
||||
uint8_t verdict = processPacketData(&mark, ifin, ifout, data, len, mod, &modlen);
|
||||
uint8_t verdict = processPacketData(&mark, ifr_in.ifr_name, ifr_out.ifr_name, data, len, cbdata->mod, &modlen);
|
||||
switch (verdict & VERDICT_MASK)
|
||||
{
|
||||
case VERDICT_MODIFY:
|
||||
DLOG("packet: id=%d pass modified. len %zu => %zu\n", id, len, modlen);
|
||||
return nfq_set_verdict2(qh, id, NF_ACCEPT, mark, (uint32_t)modlen, mod);
|
||||
return nfq_set_verdict2(qh, id, NF_ACCEPT, mark, (uint32_t)modlen, cbdata->mod);
|
||||
case VERDICT_DROP:
|
||||
DLOG("packet: id=%d drop\n", id);
|
||||
return nfq_set_verdict2(qh, id, NF_DROP, mark, 0, NULL);
|
||||
@@ -301,7 +319,7 @@ static void nfq_deinit(struct nfq_handle **h, struct nfq_q_handle **qh)
|
||||
*h = NULL;
|
||||
}
|
||||
}
|
||||
static bool nfq_init(struct nfq_handle **h, struct nfq_q_handle **qh, uint8_t *mod_buffer)
|
||||
static bool nfq_init(struct nfq_handle **h, struct nfq_q_handle **qh, struct nfq_cb_data *cbdata)
|
||||
{
|
||||
nfq_deinit(h, qh);
|
||||
|
||||
@@ -312,26 +330,33 @@ static bool nfq_init(struct nfq_handle **h, struct nfq_q_handle **qh, uint8_t *m
|
||||
goto exiterr;
|
||||
}
|
||||
|
||||
// linux 3.8 - bind calls are NOOP. linux 3.8- - secondary bind to AF_INET6 will fail
|
||||
// old kernels seem to require both binds to ipv4 and ipv6. may not work without unbind
|
||||
|
||||
DLOG_CONDUP("unbinding existing nf_queue handler for AF_INET (if any)\n");
|
||||
if (nfq_unbind_pf(*h, AF_INET) < 0) {
|
||||
DLOG_PERROR("nfq_unbind_pf()");
|
||||
DLOG_PERROR("nfq_unbind_pf(AF_INET)");
|
||||
goto exiterr;
|
||||
}
|
||||
|
||||
DLOG_CONDUP("binding nfnetlink_queue as nf_queue handler for AF_INET\n");
|
||||
if (nfq_bind_pf(*h, AF_INET) < 0) {
|
||||
DLOG_PERROR("nfq_bind_pf()");
|
||||
DLOG_PERROR("nfq_bind_pf(AF_INET)");
|
||||
goto exiterr;
|
||||
}
|
||||
|
||||
DLOG_CONDUP("unbinding existing nf_queue handler for AF_INET6 (if any)\n");
|
||||
if (nfq_unbind_pf(*h, AF_INET6) < 0) {
|
||||
DLOG_PERROR("nfq_unbind_pf(AF_INET6)");
|
||||
}
|
||||
|
||||
DLOG_CONDUP("binding nfnetlink_queue as nf_queue handler for AF_INET6\n");
|
||||
if (nfq_bind_pf(*h, AF_INET6) < 0) {
|
||||
DLOG_PERROR("nfq_bind_pf()");
|
||||
// do not fail - kernel may not support ipv6
|
||||
DLOG_PERROR("nfq_bind_pf(AF_INET6)");
|
||||
}
|
||||
|
||||
DLOG_CONDUP("binding this socket to queue '%u'\n", params.qnum);
|
||||
*qh = nfq_create_queue(*h, params.qnum, &nfq_cb, mod_buffer);
|
||||
*qh = nfq_create_queue(*h, params.qnum, &nfq_cb, cbdata);
|
||||
if (!*qh) {
|
||||
DLOG_PERROR("nfq_create_queue()");
|
||||
goto exiterr;
|
||||
@@ -350,9 +375,15 @@ static bool nfq_init(struct nfq_handle **h, struct nfq_q_handle **qh, uint8_t *m
|
||||
if (nfq_set_queue_flags(*qh, NFQA_CFG_F_FAIL_OPEN, NFQA_CFG_F_FAIL_OPEN))
|
||||
{
|
||||
DLOG_ERR("can't set queue flags. its OK on linux <3.6\n");
|
||||
// dot not fail. not supported on old linuxes <3.6
|
||||
// dot not fail. not supported in old linuxes <3.6
|
||||
}
|
||||
|
||||
unsigned int rcvbuf = nfnl_rcvbufsiz(nfq_nfnlh(*h), Q_RCVBUF) / 2;
|
||||
if (rcvbuf==Q_RCVBUF)
|
||||
DLOG("set receive buffer size to %u\n", rcvbuf);
|
||||
else
|
||||
DLOG_CONDUP("could not set receive buffer size to %u. real size is %u\n", Q_RCVBUF, rcvbuf);
|
||||
|
||||
int yes = 1, fd = nfq_fd(*h);
|
||||
|
||||
#if defined SOL_NETLINK && defined NETLINK_NO_ENOBUFS
|
||||
@@ -375,6 +406,8 @@ static void notify_ready(void)
|
||||
#endif
|
||||
}
|
||||
|
||||
// extra space for netlink headers
|
||||
#define NFQ_MAX_RECV_SIZE (RECONSTRUCT_MAX_SIZE+4096)
|
||||
static int nfq_main(void)
|
||||
{
|
||||
struct nfq_handle *h = NULL;
|
||||
@@ -383,6 +416,7 @@ static int nfq_main(void)
|
||||
ssize_t rd;
|
||||
FILE *Fpid = NULL;
|
||||
uint8_t *buf=NULL, *mod=NULL;
|
||||
struct nfq_cb_data cbdata = { .sock = -1, .mod = NULL };
|
||||
|
||||
if (*params.pidfile && !(Fpid = fopen(params.pidfile, "w")))
|
||||
{
|
||||
@@ -424,13 +458,19 @@ static int nfq_main(void)
|
||||
goto exok;
|
||||
}
|
||||
|
||||
if (!(buf = malloc(RECONSTRUCT_MAX_SIZE)) || !(mod = malloc(RECONSTRUCT_MAX_SIZE)))
|
||||
if (!(buf = malloc(NFQ_MAX_RECV_SIZE)) || !(cbdata.mod = malloc(RECONSTRUCT_MAX_SIZE)))
|
||||
{
|
||||
DLOG_ERR("out of memory\n");
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (!nfq_init(&h, &qh, mod))
|
||||
if ((cbdata.sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
|
||||
{
|
||||
DLOG_PERROR("socket");
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (!nfq_init(&h, &qh, &cbdata))
|
||||
goto err;
|
||||
|
||||
#ifdef HAS_FILTER_SSID
|
||||
@@ -453,9 +493,14 @@ static int nfq_main(void)
|
||||
fd = nfq_fd(h);
|
||||
do
|
||||
{
|
||||
while ((rd = recv(fd, buf, RECONSTRUCT_MAX_SIZE, 0)) >= 0)
|
||||
if (bQuit) goto quit;
|
||||
while ((rd = recv(fd, buf, NFQ_MAX_RECV_SIZE, 0)) >= 0)
|
||||
{
|
||||
if (bQuit) goto quit;
|
||||
if (!rd)
|
||||
{
|
||||
DLOG_ERR("recv from nfq returned 0 !\n");
|
||||
goto err;
|
||||
}
|
||||
ReloadCheck();
|
||||
lua_do_gc();
|
||||
#ifdef HAS_FILTER_SSID
|
||||
@@ -463,22 +508,12 @@ static int nfq_main(void)
|
||||
if (!wlan_info_get_rate_limited())
|
||||
DLOG_ERR("cannot get wlan info\n");
|
||||
#endif
|
||||
if (rd)
|
||||
{
|
||||
int r = nfq_handle_packet(h, (char *)buf, (int)rd);
|
||||
if (r) DLOG_ERR("nfq_handle_packet error %d\n", r);
|
||||
}
|
||||
else
|
||||
{
|
||||
DLOG_ERR("recv from nfq returned 0 !\n");
|
||||
goto err;
|
||||
}
|
||||
int r = nfq_handle_packet(h, (char *)buf, (int)rd);
|
||||
if (r<0) DLOG_ERR("nfq_handle_packet result %d, errno %d : %s\n", r, errno, strerror(errno));
|
||||
if (bQuit) goto quit;
|
||||
}
|
||||
if (errno==EINTR)
|
||||
{
|
||||
if (bQuit) goto quit;
|
||||
continue;
|
||||
}
|
||||
e = errno;
|
||||
DLOG_ERR("recv: recv=%zd errno %d\n", rd, e);
|
||||
errno = e;
|
||||
@@ -486,10 +521,18 @@ static int nfq_main(void)
|
||||
// do not fail on ENOBUFS
|
||||
} while (e == ENOBUFS);
|
||||
|
||||
err:
|
||||
res=1;
|
||||
goto ex;
|
||||
|
||||
quit:
|
||||
DLOG_CONDUP("quit requested\n");
|
||||
exok:
|
||||
res=0;
|
||||
ex:
|
||||
free(mod);
|
||||
if (Fpid) fclose(Fpid);
|
||||
if (cbdata.sock>=0) close(cbdata.sock);
|
||||
free(cbdata.mod);
|
||||
free(buf);
|
||||
nfq_deinit(&h, &qh);
|
||||
lua_shutdown();
|
||||
@@ -498,13 +541,6 @@ ex:
|
||||
#endif
|
||||
rawsend_cleanup();
|
||||
return res;
|
||||
err:
|
||||
if (Fpid) fclose(Fpid);
|
||||
res=1;
|
||||
goto ex;
|
||||
quit:
|
||||
DLOG_CONDUP("quit requested\n");
|
||||
goto exok;
|
||||
}
|
||||
|
||||
#elif defined(BSD)
|
||||
@@ -606,6 +642,11 @@ static int dvt_main(void)
|
||||
|
||||
for (;;)
|
||||
{
|
||||
if (bQuit)
|
||||
{
|
||||
DLOG_CONDUP("quit requested\n");
|
||||
goto exitok;
|
||||
}
|
||||
FD_ZERO(&fdset);
|
||||
for (i = 0; i < fdct; i++) FD_SET(fd[i], &fdset);
|
||||
r = select(fdmax, &fdset, NULL, NULL, NULL);
|
||||
@@ -625,10 +666,11 @@ static int dvt_main(void)
|
||||
if (FD_ISSET(fd[i], &fdset))
|
||||
{
|
||||
socklen = sizeof(sa_from);
|
||||
rd = recvfrom(fd[i], buf, sizeof(buf), 0, (struct sockaddr*)&sa_from, &socklen);
|
||||
while ((rd = recvfrom(fd[i], buf, sizeof(buf), 0, (struct sockaddr*)&sa_from, &socklen))<0 && errno==EINTR);
|
||||
if (rd < 0)
|
||||
{
|
||||
DLOG_PERROR("recvfrom");
|
||||
if (errno==ENOBUFS) continue;
|
||||
goto exiterr;
|
||||
}
|
||||
else if (rd > 0)
|
||||
@@ -1243,7 +1285,7 @@ struct func_list *parse_lua_call(char *opt, struct func_list_head *flist)
|
||||
struct func_list *f = NULL;
|
||||
|
||||
if (!(name = item_name(&opt)))
|
||||
return false;
|
||||
return NULL;
|
||||
|
||||
if (!is_identifier(name) || !(f=funclist_add_tail(flist,name)))
|
||||
goto err;
|
||||
@@ -1681,6 +1723,7 @@ static void exithelp(void)
|
||||
" --port=<port>\t\t\t\t\t\t; divert port\n"
|
||||
#endif
|
||||
" --daemon\t\t\t\t\t\t; daemonize\n"
|
||||
" --chdir[=path]\t\t\t\t\t\t; change current directory. if no path specified use EXEDIR\n"
|
||||
" --pidfile=<filename>\t\t\t\t\t; write pid to file\n"
|
||||
#ifndef __CYGWIN__
|
||||
" --user=<username>\t\t\t\t\t; drop root privs\n"
|
||||
@@ -1844,6 +1887,7 @@ enum opt_indices {
|
||||
IDX_PORT,
|
||||
#endif
|
||||
IDX_DAEMON,
|
||||
IDX_CHDIR,
|
||||
IDX_PIDFILE,
|
||||
#ifndef __CYGWIN__
|
||||
IDX_USER,
|
||||
@@ -1948,6 +1992,7 @@ static const struct option long_options[] = {
|
||||
[IDX_PORT] = {"port", required_argument, 0, 0},
|
||||
#endif
|
||||
[IDX_DAEMON] = {"daemon", no_argument, 0, 0},
|
||||
[IDX_CHDIR] = {"chdir", optional_argument, 0, 0},
|
||||
[IDX_PIDFILE] = {"pidfile", required_argument, 0, 0},
|
||||
#ifndef __CYGWIN__
|
||||
[IDX_USER] = {"user", required_argument, 0, 0},
|
||||
@@ -2106,10 +2151,10 @@ int main(int argc, char **argv)
|
||||
|
||||
srandom(time(NULL));
|
||||
aes_init_keygen_tables(); // required for aes
|
||||
mask_from_bitcount6_prepare();
|
||||
set_env_exedir(argv[0]);
|
||||
set_console_io_buffering();
|
||||
#ifdef __CYGWIN__
|
||||
mask_from_bitcount6_prepare();
|
||||
memset(hash_wf,0,sizeof(hash_wf));
|
||||
prepare_low_appdata();
|
||||
#endif
|
||||
@@ -2165,8 +2210,11 @@ int main(int argc, char **argv)
|
||||
{
|
||||
if (*optarg == '@')
|
||||
{
|
||||
strncpy(params.debug_logfile, optarg + 1, sizeof(params.debug_logfile));
|
||||
params.debug_logfile[sizeof(params.debug_logfile) - 1] = 0;
|
||||
if (!realpath_any(optarg+1,params.debug_logfile))
|
||||
{
|
||||
DLOG_ERR("bad file '%s'\n",optarg+1);
|
||||
exit_clean(1);
|
||||
}
|
||||
FILE *F = fopen(params.debug_logfile, "wt");
|
||||
if (!F)
|
||||
{
|
||||
@@ -2253,8 +2301,28 @@ int main(int argc, char **argv)
|
||||
case IDX_DAEMON:
|
||||
params.daemon = true;
|
||||
break;
|
||||
case IDX_CHDIR:
|
||||
{
|
||||
const char *d = optarg ? optarg : getenv("EXEDIR");
|
||||
if (!d)
|
||||
{
|
||||
DLOG_ERR("chdir: directory unknown\n");
|
||||
exit_clean(1);
|
||||
}
|
||||
DLOG("changing dir to '%s'\n",d);
|
||||
if (chdir(d))
|
||||
{
|
||||
DLOG_PERROR("chdir");
|
||||
exit_clean(1);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case IDX_PIDFILE:
|
||||
snprintf(params.pidfile, sizeof(params.pidfile), "%s", optarg);
|
||||
if (!realpath_any(optarg,params.pidfile))
|
||||
{
|
||||
DLOG_ERR("bad file '%s'\n",optarg);
|
||||
exit_clean(1);
|
||||
}
|
||||
break;
|
||||
#ifndef __CYGWIN__
|
||||
case IDX_USER:
|
||||
@@ -2358,8 +2426,11 @@ int main(int argc, char **argv)
|
||||
params.writeable_dir_enable = true;
|
||||
if (optarg)
|
||||
{
|
||||
strncpy(params.writeable_dir, optarg, sizeof(params.writeable_dir));
|
||||
params.writeable_dir[sizeof(params.writeable_dir) - 1] = 0;
|
||||
if (!realpath_any(optarg, params.writeable_dir))
|
||||
{
|
||||
DLOG_ERR("bad file '%s'\n",optarg);
|
||||
exit_clean(1);
|
||||
}
|
||||
}
|
||||
else
|
||||
*params.writeable_dir = 0;
|
||||
@@ -2370,10 +2441,22 @@ int main(int argc, char **argv)
|
||||
break;
|
||||
|
||||
case IDX_LUA_INIT:
|
||||
if (!strlist_add_tail(¶ms.lua_init_scripts, optarg))
|
||||
{
|
||||
DLOG_ERR("out of memory\n");
|
||||
exit_clean(1);
|
||||
char pabs[PATH_MAX+1], *p=optarg;
|
||||
if (*p=='@')
|
||||
{
|
||||
if (!realpath_any(p+1,pabs+1))
|
||||
{
|
||||
DLOG_ERR("bad file '%s'\n",p+1);
|
||||
exit_clean(1);
|
||||
}
|
||||
*(p=pabs)='@';
|
||||
}
|
||||
if (!strlist_add_tail(¶ms.lua_init_scripts, p))
|
||||
{
|
||||
DLOG_ERR("out of memory\n");
|
||||
exit_clean(1);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case IDX_LUA_GC:
|
||||
@@ -2455,7 +2538,7 @@ int main(int argc, char **argv)
|
||||
}
|
||||
break;
|
||||
case IDX_HOSTLIST_AUTO_FAIL_THRESHOLD:
|
||||
dp->hostlist_auto_fail_threshold = (uint8_t)atoi(optarg);
|
||||
dp->hostlist_auto_fail_threshold = atoi(optarg);
|
||||
if (dp->hostlist_auto_fail_threshold < 1 || dp->hostlist_auto_fail_threshold>20)
|
||||
{
|
||||
DLOG_ERR("auto hostlist fail threshold must be within 1..20\n");
|
||||
@@ -2464,7 +2547,7 @@ int main(int argc, char **argv)
|
||||
dp->b_hostlist_auto_fail_threshold = true;
|
||||
break;
|
||||
case IDX_HOSTLIST_AUTO_FAIL_TIME:
|
||||
dp->hostlist_auto_fail_time = (uint8_t)atoi(optarg);
|
||||
dp->hostlist_auto_fail_time = atoi(optarg);
|
||||
if (dp->hostlist_auto_fail_time < 1)
|
||||
{
|
||||
DLOG_ERR("auto hostlist fail time is not valid\n");
|
||||
@@ -2473,7 +2556,7 @@ int main(int argc, char **argv)
|
||||
dp->b_hostlist_auto_fail_time = true;
|
||||
break;
|
||||
case IDX_HOSTLIST_AUTO_RETRANS_THRESHOLD:
|
||||
dp->hostlist_auto_retrans_threshold = (uint8_t)atoi(optarg);
|
||||
dp->hostlist_auto_retrans_threshold = atoi(optarg);
|
||||
if (dp->hostlist_auto_retrans_threshold < 2 || dp->hostlist_auto_retrans_threshold>10)
|
||||
{
|
||||
DLOG_ERR("auto hostlist fail threshold must be within 2..10\n");
|
||||
@@ -2503,15 +2586,18 @@ int main(int argc, char **argv)
|
||||
break;
|
||||
case IDX_HOSTLIST_AUTO_DEBUG:
|
||||
{
|
||||
FILE *F = fopen(optarg, "a+t");
|
||||
if (!realpath_any(optarg,params.hostlist_auto_debuglog))
|
||||
{
|
||||
DLOG_ERR("bad file '%s'\n",optarg);
|
||||
exit_clean(1);
|
||||
}
|
||||
FILE *F = fopen(params.hostlist_auto_debuglog, "a+t");
|
||||
if (!F)
|
||||
{
|
||||
DLOG_ERR("cannot create %s\n", optarg);
|
||||
exit_clean(1);
|
||||
}
|
||||
fclose(F);
|
||||
strncpy(params.hostlist_auto_debuglog, optarg, sizeof(params.hostlist_auto_debuglog));
|
||||
params.hostlist_auto_debuglog[sizeof(params.hostlist_auto_debuglog) - 1] = '\0';
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
@@ -6,9 +6,7 @@
|
||||
#define HAS_FILTER_SSID 1
|
||||
#endif
|
||||
|
||||
#ifdef __CYGWIN__
|
||||
extern volatile sig_atomic_t bQuit;
|
||||
#endif
|
||||
int main(int argc, char *argv[]);
|
||||
|
||||
// when something changes that can break LUA compatibility this version should be increased
|
||||
|
||||
@@ -26,7 +26,14 @@ void rawpacket_queue_destroy(struct rawpacket_tailhead *q)
|
||||
while((rp = rawpacket_dequeue(q))) rawpacket_free(rp);
|
||||
}
|
||||
|
||||
struct rawpacket *rawpacket_queue(struct rawpacket_tailhead *q,const struct sockaddr_storage* dst,uint32_t fwmark_orig,uint32_t fwmark,const char *ifin,const char *ifout,const void *data,size_t len,size_t len_payload,const t_ctrack_positions *tpos)
|
||||
struct rawpacket *rawpacket_queue(
|
||||
struct rawpacket_tailhead *q,
|
||||
const struct sockaddr_storage* dst,
|
||||
uint32_t fwmark_orig,uint32_t fwmark,
|
||||
const char *ifin,const char *ifout,
|
||||
const void *data,size_t len,size_t len_payload,
|
||||
const t_ctrack_positions *tpos,
|
||||
bool server_side)
|
||||
{
|
||||
struct rawpacket *rp = malloc(sizeof(struct rawpacket));
|
||||
if (!rp) return NULL;
|
||||
@@ -61,6 +68,7 @@ struct rawpacket *rawpacket_queue(struct rawpacket_tailhead *q,const struct sock
|
||||
}
|
||||
else
|
||||
rp->tpos_present = false;
|
||||
rp->server_side = server_side;
|
||||
|
||||
TAILQ_INSERT_TAIL(q, rp, next);
|
||||
|
||||
|
||||
@@ -18,6 +18,7 @@ struct rawpacket
|
||||
uint8_t *packet;
|
||||
t_ctrack_positions tpos;
|
||||
bool tpos_present;
|
||||
bool server_side; // true = reasm of packets from the server side
|
||||
TAILQ_ENTRY(rawpacket) next;
|
||||
};
|
||||
TAILQ_HEAD(rawpacket_tailhead, rawpacket);
|
||||
@@ -26,6 +27,6 @@ void rawpacket_queue_init(struct rawpacket_tailhead *q);
|
||||
void rawpacket_queue_destroy(struct rawpacket_tailhead *q);
|
||||
bool rawpacket_queue_empty(const struct rawpacket_tailhead *q);
|
||||
unsigned int rawpacket_queue_count(const struct rawpacket_tailhead *q);
|
||||
struct rawpacket *rawpacket_queue(struct rawpacket_tailhead *q,const struct sockaddr_storage* dst,uint32_t fwmark_orig,uint32_t fwmark,const char *ifin,const char *ifout,const void *data,size_t len,size_t len_payload,const t_ctrack_positions *tpos);
|
||||
struct rawpacket *rawpacket_queue(struct rawpacket_tailhead *q,const struct sockaddr_storage* dst,uint32_t fwmark_orig,uint32_t fwmark,const char *ifin,const char *ifout,const void *data,size_t len,size_t len_payload,const t_ctrack_positions *tpos,bool server_side);
|
||||
struct rawpacket *rawpacket_dequeue(struct rawpacket_tailhead *q);
|
||||
void rawpacket_free(struct rawpacket *rp);
|
||||
|
||||
@@ -116,7 +116,7 @@ static char log_buf[4096];
|
||||
static size_t log_buf_sz=0;
|
||||
static void syslog_log_function(int priority, const char *line)
|
||||
{
|
||||
syslog(priority,"%s",log_buf);
|
||||
syslog(priority,"%s",line);
|
||||
}
|
||||
|
||||
static int DLOG_FILENAME(const char *filename, const char *format, ...)
|
||||
@@ -130,7 +130,7 @@ static int DLOG_FILENAME(const char *filename, const char *format, ...)
|
||||
}
|
||||
static void file_log_function(int priority, const char *line)
|
||||
{
|
||||
DLOG_FILENAME(params.debug_logfile,"%s",log_buf);
|
||||
DLOG_FILENAME(params.debug_logfile,"%s",line);
|
||||
}
|
||||
|
||||
#ifdef __ANDROID__
|
||||
@@ -405,7 +405,7 @@ static struct desync_profile_list *desync_profile_entry_alloc()
|
||||
struct desync_profile_list *dp_list_add(struct desync_profile_list_head *head)
|
||||
{
|
||||
struct desync_profile_list *entry = desync_profile_entry_alloc();
|
||||
if (!entry) return false;
|
||||
if (!entry) return NULL;
|
||||
|
||||
struct desync_profile_list *tail, *item;
|
||||
LIST_TAIL(head, tail, item);
|
||||
|
||||
@@ -23,7 +23,8 @@
|
||||
|
||||
#define RAW_SNDBUF (64*1024) // in bytes
|
||||
|
||||
#define Q_MAXLEN 1024 // in packets
|
||||
#define Q_MAXLEN 4096 // in packets
|
||||
#define Q_RCVBUF (1024*1024) // in bytes
|
||||
|
||||
#define HOSTLIST_AUTO_FAIL_THRESHOLD_DEFAULT 3
|
||||
#define HOSTLIST_AUTO_FAIL_TIME_DEFAULT 60
|
||||
|
||||
@@ -493,7 +493,6 @@ void kavl_bit_destroy(struct kavl_bit_elem **hdr)
|
||||
if (!e) break;
|
||||
kavl_bit_destroy_elem(e);
|
||||
}
|
||||
free(*hdr);
|
||||
}
|
||||
struct kavl_bit_elem *kavl_bit_add(struct kavl_bit_elem **hdr, void *data, unsigned int bitlen, size_t struct_size)
|
||||
{
|
||||
@@ -1033,7 +1032,7 @@ static ip_cache4 *ipcache4Add(ip_cache4 **ipcache, const struct in_addr *a, cons
|
||||
}
|
||||
static void ipcache4Print(ip_cache4 *ipcache)
|
||||
{
|
||||
char s_ip[16];
|
||||
char s_ip[INET_ADDRSTRLEN];
|
||||
time_t now;
|
||||
ip_cache4 *ipc, *tmp;
|
||||
|
||||
@@ -1091,7 +1090,7 @@ static ip_cache6 *ipcache6Add(ip_cache6 **ipcache, const struct in6_addr *a, con
|
||||
}
|
||||
static void ipcache6Print(ip_cache6 *ipcache)
|
||||
{
|
||||
char s_ip[40];
|
||||
char s_ip[INET6_ADDRSTRLEN];
|
||||
time_t now;
|
||||
ip_cache6 *ipc, *tmp;
|
||||
|
||||
|
||||
114
nfq2/protocol.c
114
nfq2/protocol.c
@@ -145,7 +145,6 @@ bool posmarker_parse(const char *s, struct proto_pos *m)
|
||||
m->pos = 0;
|
||||
}
|
||||
return true;
|
||||
|
||||
}
|
||||
bool posmarker_list_parse(const char *s, struct proto_pos *m, int *mct)
|
||||
{
|
||||
@@ -249,7 +248,7 @@ void ResolveMultiPos(const uint8_t *data, size_t sz, t_l7payload l7payload, cons
|
||||
}
|
||||
|
||||
|
||||
static const char *http_methods[] = { "GET ","POST ","HEAD ","OPTIONS ","PUT ","DELETE ","CONNECT ","TRACE ",NULL };
|
||||
static const char *http_methods[] = { "GET ","POST ","HEAD ","OPTIONS ","PUT ","DELETE ","CONNECT ","TRACE ", "PATCH ", NULL };
|
||||
static const char *HttpMethod(const uint8_t *data, size_t len)
|
||||
{
|
||||
const char **method;
|
||||
@@ -332,7 +331,7 @@ bool IsHttpReply(const uint8_t *data, size_t len)
|
||||
data[10]>='0' && data[10]<='9' &&
|
||||
data[11]>='0' && data[11]<='9';
|
||||
}
|
||||
int HttpReplyCode(const uint8_t *data, size_t len)
|
||||
int HttpReplyCode(const uint8_t *data)
|
||||
{
|
||||
return (data[9]-'0')*100 + (data[10]-'0')*10 + (data[11]-'0');
|
||||
}
|
||||
@@ -371,7 +370,7 @@ bool HttpReplyLooksLikeDPIRedirect(const uint8_t *data, size_t len, const char *
|
||||
|
||||
if (!host || !*host || !IsHttpReply(data, len)) return false;
|
||||
|
||||
code = HttpReplyCode(data,len);
|
||||
code = HttpReplyCode(data);
|
||||
|
||||
if ((code!=302 && code!=307) || !HttpExtractHeader(data,len,"\nLocation:",loc,sizeof(loc))) return false;
|
||||
|
||||
@@ -551,10 +550,14 @@ bool TLSFindExtLenOffsetInHandshake(const uint8_t *data, size_t len, size_t *off
|
||||
l += data[l] + 1;
|
||||
// CipherSuitesLength
|
||||
if (len < (l + 2)) return false;
|
||||
l += (data[0]==0x02 ? 0 : pntoh16(data + l)) + 2;
|
||||
if (data[0]==0x01) // client hello ?
|
||||
l += pntoh16(data + l);
|
||||
l+=2;
|
||||
// CompressionMethodsLength
|
||||
if (len < (l + 1)) return false;
|
||||
l += data[l] + 1;
|
||||
if (data[0]==0x01) // client hello ?
|
||||
l += data[l];
|
||||
l++;
|
||||
// ExtensionsLength
|
||||
if (len < (l + 2)) return false;
|
||||
*off = l;
|
||||
@@ -562,7 +565,7 @@ bool TLSFindExtLenOffsetInHandshake(const uint8_t *data, size_t len, size_t *off
|
||||
}
|
||||
bool TLSFindExtLen(const uint8_t *data, size_t len, size_t *off)
|
||||
{
|
||||
if (!TLSFindExtLenOffsetInHandshake(data+5,len-5,off))
|
||||
if (len<5 || !TLSFindExtLenOffsetInHandshake(data+5,len-5,off))
|
||||
return false;
|
||||
*off+=5;
|
||||
return true;
|
||||
@@ -646,9 +649,11 @@ bool TLSAdvanceToHostInSNI(const uint8_t **ext, size_t *elen, size_t *slen)
|
||||
// u8 data+2 - server name type. 0=host_name
|
||||
// u16 data+3 - server name length
|
||||
if (*elen < 5 || (*ext)[2] != 0) return false;
|
||||
uint16_t nll = pntoh16(*ext);
|
||||
*slen = pntoh16(*ext + 3);
|
||||
if (nll<(*slen+3) || *slen > *elen-5) return false;
|
||||
*ext += 5; *elen -= 5;
|
||||
return *slen <= *elen;
|
||||
return true;
|
||||
}
|
||||
static bool TLSExtractHostFromExt(const uint8_t *ext, size_t elen, char *host, size_t len_host)
|
||||
{
|
||||
@@ -1191,16 +1196,16 @@ bool QUICDecryptInitial(const uint8_t *data, size_t data_len, uint8_t *clean, si
|
||||
return false;
|
||||
}
|
||||
|
||||
uint64_t payload_len,token_len;
|
||||
size_t pn_offset;
|
||||
uint64_t payload_len,token_len,pn_offset;
|
||||
pn_offset = 1 + 4 + 1 + data[5];
|
||||
if (pn_offset >= data_len) return false;
|
||||
// SCID length
|
||||
pn_offset += 1 + data[pn_offset];
|
||||
if ((pn_offset + tvb_get_size(data[pn_offset])) >= data_len) return false;
|
||||
if (pn_offset >= data_len || (pn_offset + tvb_get_size(data[pn_offset])) >= data_len) return false;
|
||||
// token length
|
||||
pn_offset += tvb_get_varint(data + pn_offset, &token_len);
|
||||
pn_offset += token_len;
|
||||
if (pn_offset >= data_len) return false;
|
||||
if ((pn_offset + tvb_get_size(data[pn_offset])) >= data_len) return false;
|
||||
if (pn_offset >= data_len || (pn_offset + tvb_get_size(data[pn_offset])) >= data_len) return false;
|
||||
pn_offset += tvb_get_varint(data + pn_offset, &payload_len);
|
||||
if (payload_len<20 || (pn_offset + payload_len)>data_len) return false;
|
||||
|
||||
@@ -1221,17 +1226,17 @@ bool QUICDecryptInitial(const uint8_t *data, size_t data_len, uint8_t *clean, si
|
||||
|
||||
phton64(aesiv + sizeof(aesiv) - 8, pntoh64(aesiv + sizeof(aesiv) - 8) ^ pkn);
|
||||
|
||||
size_t cryptlen = payload_len - pkn_len - 16;
|
||||
uint64_t cryptlen = payload_len - pkn_len - 16;
|
||||
if (cryptlen > *clean_len) return false;
|
||||
*clean_len = cryptlen;
|
||||
*clean_len = (size_t)cryptlen;
|
||||
const uint8_t *decrypt_begin = data + pn_offset + pkn_len;
|
||||
|
||||
uint8_t atag[16],header[2048];
|
||||
size_t header_len = pn_offset + pkn_len;
|
||||
uint64_t header_len = pn_offset + pkn_len;
|
||||
if (header_len > sizeof(header)) return false; // not likely header will be so large
|
||||
memcpy(header, data, header_len);
|
||||
header[0] = packet0;
|
||||
for(size_t i = 0; i < pkn_len; i++) header[header_len - 1 - i] = (uint8_t)(pkn >> (8 * i));
|
||||
for(uint8_t i = 0; i < pkn_len; i++) header[header_len - 1 - i] = (uint8_t)(pkn >> (8 * i));
|
||||
|
||||
if (aes_gcm_crypt(AES_DECRYPT, clean, decrypt_begin, cryptlen, aeskey, sizeof(aeskey), aesiv, sizeof(aesiv), header, header_len, atag, sizeof(atag)))
|
||||
return false;
|
||||
@@ -1249,6 +1254,13 @@ static int cmp_range64(const void * a, const void * b)
|
||||
{
|
||||
return (((struct range64*)a)->offset < ((struct range64*)b)->offset) ? -1 : (((struct range64*)a)->offset > ((struct range64*)b)->offset) ? 1 : 0;
|
||||
}
|
||||
/*
|
||||
static bool intersected_u64(uint64_t l1, uint64_t r1, uint64_t l2, uint64_t r2)
|
||||
{
|
||||
return l1 <= r2 && l2 <= r1;
|
||||
}
|
||||
*/
|
||||
|
||||
bool QUICDefragCrypto(const uint8_t *clean,size_t clean_len, uint8_t *defrag,size_t *defrag_len, bool *bFull)
|
||||
{
|
||||
// Crypto frame can be split into multiple chunks
|
||||
@@ -1262,7 +1274,7 @@ bool QUICDefragCrypto(const uint8_t *clean,size_t clean_len, uint8_t *defrag,siz
|
||||
uint64_t offset,sz,szmax=0,zeropos=0,pos=0;
|
||||
bool found=false;
|
||||
struct range64 ranges[MAX_DEFRAG_PIECES];
|
||||
int i,range=0;
|
||||
int i,j,range=0;
|
||||
|
||||
while(pos<clean_len)
|
||||
{
|
||||
@@ -1284,24 +1296,54 @@ bool QUICDefragCrypto(const uint8_t *clean,size_t clean_len, uint8_t *defrag,siz
|
||||
if ((pos+sz)>clean_len) return false;
|
||||
|
||||
if ((offset+sz)>defrag_data_len) return false; // defrag buf overflow
|
||||
|
||||
// remove exact duplicates early to save cpu
|
||||
for(i=0;i<range;i++)
|
||||
if (ranges[i].offset==offset && ranges[i].len==sz)
|
||||
goto skip_range;
|
||||
|
||||
if (zeropos < offset)
|
||||
// make sure no uninitialized gaps exist in case of not full fragment coverage
|
||||
memset(defrag_data+zeropos,0,offset-zeropos);
|
||||
if ((offset+sz) > zeropos)
|
||||
zeropos=offset+sz;
|
||||
memcpy(defrag_data+offset,clean+pos,sz);
|
||||
if ((offset+sz) > szmax) szmax = offset+sz;
|
||||
|
||||
found=true;
|
||||
pos+=sz;
|
||||
|
||||
if ((offset+sz) > szmax) szmax = offset+sz;
|
||||
memcpy(defrag_data+offset,clean+pos,sz);
|
||||
ranges[range].offset = offset;
|
||||
ranges[range].len = sz;
|
||||
range++;
|
||||
skip_range:
|
||||
pos+=sz;
|
||||
}
|
||||
}
|
||||
if (found)
|
||||
{
|
||||
qsort(ranges, range, sizeof(*ranges), cmp_range64);
|
||||
|
||||
// for(i=0 ; i<range ; i++)
|
||||
// printf("range1 %llu-%llu\n",ranges[i].offset,ranges[i].offset+ranges[i].len);
|
||||
|
||||
if (range>0)
|
||||
{
|
||||
for (j=0,i=1; i < range; i++)
|
||||
{
|
||||
uint64_t current_end = ranges[j].offset + ranges[j].len;
|
||||
uint64_t next_start = ranges[i].offset;
|
||||
uint64_t next_end = ranges[i].offset + ranges[i].len;
|
||||
|
||||
if (next_start <= current_end)
|
||||
ranges[j].len = MAX(next_end,current_end) - ranges[j].offset;
|
||||
else
|
||||
ranges[++j] = ranges[i];
|
||||
}
|
||||
range = j+1;
|
||||
}
|
||||
|
||||
// for(i=0 ; i<range ; i++)
|
||||
// printf("range2 %llu-%llu\n",ranges[i].offset,ranges[i].offset+ranges[i].len);
|
||||
|
||||
defrag[0] = 6;
|
||||
defrag[1] = 0; // offset
|
||||
// 2..9 - length 64 bit
|
||||
@@ -1310,21 +1352,7 @@ bool QUICDefragCrypto(const uint8_t *clean,size_t clean_len, uint8_t *defrag,siz
|
||||
defrag[2] |= 0xC0; // 64 bit value
|
||||
*defrag_len = (size_t)(szmax+10);
|
||||
|
||||
qsort(ranges, range, sizeof(*ranges), cmp_range64);
|
||||
|
||||
//for(i=0 ; i<range ; i++)
|
||||
// printf("RANGE %zu len %zu\n",ranges[i].offset,ranges[i].len);
|
||||
|
||||
for(i=0,offset=0,*bFull=true ; i<range ; i++)
|
||||
{
|
||||
if (ranges[i].offset!=offset)
|
||||
{
|
||||
*bFull = false;
|
||||
break;
|
||||
}
|
||||
offset += ranges[i].len;
|
||||
}
|
||||
|
||||
*bFull = range==1 && !ranges[0].offset;
|
||||
//printf("bFull=%u\n",*bFull);
|
||||
}
|
||||
return found;
|
||||
@@ -1334,14 +1362,12 @@ bool IsQUICInitial(const uint8_t *data, size_t len)
|
||||
{
|
||||
// too small packets are not likely to be initials
|
||||
// long header, fixed bit
|
||||
if (len < 128 || (data[0] & 0xF0)!=0xC0) return false;
|
||||
if (len < 128) return false;
|
||||
|
||||
uint32_t ver = QUICExtractVersion(data,len);
|
||||
if (QUICDraftVersion(ver) < 11) return false;
|
||||
|
||||
// quic v1 : initial packets are 00b
|
||||
// quic v2 : initial packets are 01b
|
||||
if ((data[0] & 0x30) != (is_quic_v2(ver) ? 0x10 : 0x00)) return false;
|
||||
if ((data[0] & 0xF0) != (is_quic_v2(ver) ? 0xD0 : 0xC0)) return false;
|
||||
|
||||
uint64_t offset=5, sz, sz2;
|
||||
|
||||
@@ -1349,6 +1375,8 @@ bool IsQUICInitial(const uint8_t *data, size_t len)
|
||||
if (data[offset] > QUIC_MAX_CID_LENGTH) return false;
|
||||
offset += 1 + data[offset];
|
||||
|
||||
if (offset>=len) return false;
|
||||
|
||||
// SCID
|
||||
if (data[offset] > QUIC_MAX_CID_LENGTH) return false;
|
||||
offset += 1 + data[offset];
|
||||
@@ -1444,7 +1472,7 @@ bool IsStunMessage(const uint8_t *data, size_t len)
|
||||
(data[0]&0xC0)==0 && // 2 most significant bits must be zeroes
|
||||
(data[3]&3)==0 && // length must be a multiple of 4
|
||||
pntoh32(data+4)==0x2112A442 && // magic cookie
|
||||
pntoh16(data+2)==(len-20);
|
||||
pntoh16(data+2)<=(len-20);
|
||||
}
|
||||
#if defined(__GNUC__) && !defined(__llvm__)
|
||||
__attribute__((optimize ("no-strict-aliasing")))
|
||||
@@ -1459,7 +1487,7 @@ bool IsMTProto(const uint8_t *data, size_t len)
|
||||
return !memcmp(decrypt+56,"\xEF\xEF\xEF\xEF",4);
|
||||
*/
|
||||
// this way requires only one AES instead of 4
|
||||
uint8_t decrypt[16] __attribute__((aligned)), iv[16];
|
||||
uint8_t decrypt[16] __attribute__((aligned(16))), iv[16] __attribute__((aligned(16)));
|
||||
aes_context ctx;
|
||||
|
||||
memcpy(iv, data+40, 16);
|
||||
|
||||
@@ -104,7 +104,7 @@ bool HttpExtractHeader(const uint8_t *data, size_t len, const char *header, char
|
||||
bool HttpExtractHost(const uint8_t *data, size_t len, char *host, size_t len_host);
|
||||
bool IsHttpReply(const uint8_t *data, size_t len);
|
||||
// must be pre-checked by IsHttpReply
|
||||
int HttpReplyCode(const uint8_t *data, size_t len);
|
||||
int HttpReplyCode(const uint8_t *data);
|
||||
// must be pre-checked by IsHttpReply
|
||||
bool HttpReplyLooksLikeDPIRedirect(const uint8_t *data, size_t len, const char *host);
|
||||
|
||||
|
||||
17
nfq2/sec.c
17
nfq2/sec.c
@@ -6,6 +6,7 @@
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <grp.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "params.h"
|
||||
|
||||
@@ -18,7 +19,6 @@
|
||||
// __X32_SYSCALL_BIT defined in linux/unistd.h
|
||||
#include <linux/unistd.h>
|
||||
#include <syscall.h>
|
||||
#include <errno.h>
|
||||
|
||||
/************ SECCOMP ************/
|
||||
|
||||
@@ -350,10 +350,19 @@ void daemonize(void)
|
||||
DLOG_PERROR("setsid");
|
||||
exit(21);
|
||||
}
|
||||
if (close(STDIN_FILENO)<0 || close(STDOUT_FILENO)<0 || close(STDERR_FILENO)<0)
|
||||
if (close(STDIN_FILENO)<0 && errno!=EBADF)
|
||||
{
|
||||
// will work only if debug not to console
|
||||
DLOG_PERROR("close");
|
||||
DLOG_PERROR("close(stdin)");
|
||||
exit(22);
|
||||
}
|
||||
if (close(STDOUT_FILENO)<0 && errno!=EBADF)
|
||||
{
|
||||
DLOG_PERROR("close(stdout)");
|
||||
exit(22);
|
||||
}
|
||||
if (close(STDERR_FILENO)<0 && errno!=EBADF)
|
||||
{
|
||||
DLOG_PERROR("close(stderr)");
|
||||
exit(22);
|
||||
}
|
||||
/* redirect fd's 0,1,2 to /dev/null */
|
||||
|
||||
27
nfq2/sec.h
27
nfq2/sec.h
@@ -18,6 +18,25 @@ bool dropcaps(void);
|
||||
#define arch_nr (offsetof(struct seccomp_data, arch))
|
||||
#define syscall_arg(x) (offsetof(struct seccomp_data, args[x]))
|
||||
|
||||
#ifndef __AUDIT_ARCH_64BIT
|
||||
#define __AUDIT_ARCH_64BIT 0x80000000
|
||||
#endif
|
||||
#ifndef __AUDIT_ARCH_LE
|
||||
#define __AUDIT_ARCH_LE 0x40000000
|
||||
#endif
|
||||
#ifndef EM_RISCV
|
||||
#define EM_RISCV 243
|
||||
#endif
|
||||
#ifndef AUDIT_ARCH_RISCV64
|
||||
#define AUDIT_ARCH_RISCV64 (EM_RISCV | __AUDIT_ARCH_64BIT | __AUDIT_ARCH_LE)
|
||||
#endif
|
||||
#ifndef EM_LOONGARCH
|
||||
#define EM_LOONGARCH 258
|
||||
#endif
|
||||
#ifndef AUDIT_ARCH_LOONGARCH64
|
||||
#define AUDIT_ARCH_LOONGARCH64 (EM_LOONGARCH | __AUDIT_ARCH_64BIT | __AUDIT_ARCH_LE)
|
||||
#endif
|
||||
|
||||
#if defined(__aarch64__)
|
||||
|
||||
# define ARCH_NR AUDIT_ARCH_AARCH64
|
||||
@@ -72,6 +91,14 @@ bool dropcaps(void);
|
||||
|
||||
# define ARCH_NR AUDIT_ARCH_RISCV64
|
||||
|
||||
#elif defined(__loongarch__) && __loongarch_grlen == 64
|
||||
|
||||
# define ARCH_NR AUDIT_ARCH_LOONGARCH64
|
||||
|
||||
#elif defined(__e2k__)
|
||||
|
||||
# define ARCH_NR AUDIT_ARCH_E2K
|
||||
|
||||
#else
|
||||
|
||||
# error "Platform does not support seccomp filter yet"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright (c) 2003-2021, Troy D. Hanson http://troydhanson.github.io/uthash/
|
||||
Copyright (c) 2003-2025, Troy D. Hanson https://troydhanson.github.io/uthash/
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
@@ -30,12 +30,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#include <stddef.h> /* ptrdiff_t */
|
||||
#include <stdlib.h> /* exit */
|
||||
|
||||
#if defined(HASH_DEFINE_OWN_STDINT) && HASH_DEFINE_OWN_STDINT
|
||||
/* This codepath is provided for backward compatibility, but I plan to remove it. */
|
||||
#warning "HASH_DEFINE_OWN_STDINT is deprecated; please use HASH_NO_STDINT instead"
|
||||
typedef unsigned int uint32_t;
|
||||
typedef unsigned char uint8_t;
|
||||
#elif defined(HASH_NO_STDINT) && HASH_NO_STDINT
|
||||
#if defined(HASH_NO_STDINT) && HASH_NO_STDINT
|
||||
/* The user doesn't have <stdint.h>, and must figure out their own way
|
||||
to provide definitions for uint8_t and uint32_t. */
|
||||
#else
|
||||
#include <stdint.h> /* uint8_t, uint32_t */
|
||||
#endif
|
||||
@@ -51,6 +48,8 @@ typedef unsigned char uint8_t;
|
||||
#else /* VS2008 or older (or VS2010 in C mode) */
|
||||
#define NO_DECLTYPE
|
||||
#endif
|
||||
#elif defined(__MCST__) /* Elbrus C Compiler */
|
||||
#define DECLTYPE(x) (__typeof(x))
|
||||
#elif defined(__BORLANDC__) || defined(__ICCARM__) || defined(__LCC__) || defined(__WATCOMC__)
|
||||
#define NO_DECLTYPE
|
||||
#else /* GNU, Sun and other compilers */
|
||||
@@ -157,7 +156,7 @@ do {
|
||||
if (head) { \
|
||||
unsigned _hf_bkt; \
|
||||
HASH_TO_BKT(hashval, (head)->hh.tbl->num_buckets, _hf_bkt); \
|
||||
if (HASH_BLOOM_TEST((head)->hh.tbl, hashval) != 0) { \
|
||||
if (HASH_BLOOM_TEST((head)->hh.tbl, hashval)) { \
|
||||
HASH_FIND_IN_BKT((head)->hh.tbl, hh, (head)->hh.tbl->buckets[ _hf_bkt ], keyptr, keylen, hashval, out); \
|
||||
} \
|
||||
} \
|
||||
@@ -194,7 +193,7 @@ do {
|
||||
} while (0)
|
||||
|
||||
#define HASH_BLOOM_BITSET(bv,idx) (bv[(idx)/8U] |= (1U << ((idx)%8U)))
|
||||
#define HASH_BLOOM_BITTEST(bv,idx) (bv[(idx)/8U] & (1U << ((idx)%8U)))
|
||||
#define HASH_BLOOM_BITTEST(bv,idx) ((bv[(idx)/8U] & (1U << ((idx)%8U))) != 0)
|
||||
|
||||
#define HASH_BLOOM_ADD(tbl,hashv) \
|
||||
HASH_BLOOM_BITSET((tbl)->bloom_bv, ((hashv) & (uint32_t)((1UL << (tbl)->bloom_nbits) - 1U)))
|
||||
@@ -206,7 +205,7 @@ do {
|
||||
#define HASH_BLOOM_MAKE(tbl,oomed)
|
||||
#define HASH_BLOOM_FREE(tbl)
|
||||
#define HASH_BLOOM_ADD(tbl,hashv)
|
||||
#define HASH_BLOOM_TEST(tbl,hashv) (1)
|
||||
#define HASH_BLOOM_TEST(tbl,hashv) 1
|
||||
#define HASH_BLOOM_BYTELEN 0U
|
||||
#endif
|
||||
|
||||
@@ -450,7 +449,7 @@ do {
|
||||
|
||||
#define HASH_DELETE_HH(hh,head,delptrhh) \
|
||||
do { \
|
||||
struct UT_hash_handle *_hd_hh_del = (delptrhh); \
|
||||
const struct UT_hash_handle *_hd_hh_del = (delptrhh); \
|
||||
if ((_hd_hh_del->prev == NULL) && (_hd_hh_del->next == NULL)) { \
|
||||
HASH_BLOOM_FREE((head)->hh.tbl); \
|
||||
uthash_free((head)->hh.tbl->buckets, \
|
||||
@@ -593,7 +592,9 @@ do {
|
||||
|
||||
|
||||
/* SAX/FNV/OAT/JEN hash functions are macro variants of those listed at
|
||||
* http://eternallyconfuzzled.com/tuts/algorithms/jsw_tut_hashing.aspx */
|
||||
* http://eternallyconfuzzled.com/tuts/algorithms/jsw_tut_hashing.aspx
|
||||
* (archive link: https://archive.is/Ivcan )
|
||||
*/
|
||||
#define HASH_SAX(key,keylen,hashv) \
|
||||
do { \
|
||||
unsigned _sx_i; \
|
||||
|
||||
@@ -28,12 +28,6 @@ bool service_run(int argc, char *argv[])
|
||||
return StartServiceCtrlDispatcherA(ServiceTable);
|
||||
}
|
||||
|
||||
static void service_set_status(DWORD state)
|
||||
{
|
||||
ServiceStatus.dwCurrentState = state;
|
||||
SetServiceStatus(hStatus, &ServiceStatus);
|
||||
}
|
||||
|
||||
// Control handler function
|
||||
void service_controlhandler(DWORD request)
|
||||
{
|
||||
|
||||
@@ -4,6 +4,6 @@
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
bool service_run();
|
||||
bool service_run(int argc, char *argv[]);
|
||||
|
||||
#endif
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Reference in New Issue
Block a user