mirror of
https://github.com/bol-van/zapret2.git
synced 2026-03-14 06:13:09 +00:00
Compare commits
209 Commits
| 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 | ||
|
|
6638140880 | ||
|
|
41bac1833e | ||
|
|
c3b1cc3eb9 | ||
|
|
6f52fb08f9 | ||
|
|
08549b570b | ||
|
|
13daef5167 | ||
|
|
1fd6063cd7 | ||
|
|
5e4f78228e | ||
|
|
2e255ca59f | ||
|
|
565a8abffc | ||
|
|
69f1576f7e | ||
|
|
0917cb21bb | ||
|
|
8f316ae1a2 | ||
|
|
caaf5e7a2e | ||
|
|
dbfbd6e6d3 | ||
|
|
397fe60b5f | ||
|
|
e096ed64bc | ||
|
|
0f2def9bd5 | ||
|
|
85721e4b82 | ||
|
|
0fd9314df9 | ||
|
|
a9e2bfe49c | ||
|
|
bd7a40f5a9 | ||
|
|
bcd50f5215 | ||
|
|
927cca3d44 | ||
|
|
162e8906a6 | ||
|
|
3f7180379b | ||
|
|
5d0af6b058 | ||
|
|
392e1cc1ef | ||
|
|
8a5643851d | ||
|
|
6299a46ab7 | ||
|
|
c5ecc0493d | ||
|
|
7bb8b1d7b3 | ||
|
|
401bd83f82 | ||
|
|
c117c30849 | ||
|
|
6828e7352c | ||
|
|
943e548f93 | ||
|
|
539c329da3 | ||
|
|
4c6902c17c | ||
|
|
9121d949f6 | ||
|
|
64c1f96f80 | ||
|
|
3334786fe3 | ||
|
|
20a0fa671d | ||
|
|
747de07c85 | ||
|
|
6384af6607 | ||
|
|
3046dd8013 | ||
|
|
c80ae95a09 | ||
|
|
d7e5fc1a7c | ||
|
|
97a6b9dd5b | ||
|
|
cfd2df41c4 | ||
|
|
f47f4a0cae | ||
|
|
823a2e2e5d | ||
|
|
0cdbedde74 | ||
|
|
36e243863b |
2
.github/ISSUE_TEMPLATE/issue-warning.md
vendored
2
.github/ISSUE_TEMPLATE/issue-warning.md
vendored
@@ -18,5 +18,7 @@ Discussions - место для обсуждения вопросов между
|
||||
Если вы игнорируете данное требование, вы не достигните своих целей , а только добавите желания удалить ваш issue или при настойчивости забанить.
|
||||
Идите в дискуссии, не захламляйте issues.
|
||||
|
||||
Так же будут немедленно удаляться любые issue, связанные с реакцией антивирусов. При агрессии или настойчивости - бан. (подсказка : вирусов нет, удаляйте если не верите)
|
||||
|
||||
Here is the place for bugs only. All questions, especially user-like questions (non-technical) go to Discussions.
|
||||
There're also no viruses here. All virus claims and everyting non-technical and non-bugs will be instantly deleted, closed or moved to Discussions.
|
||||
|
||||
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
|
||||
|
||||
@@ -5,9 +5,9 @@ pktws_oob()
|
||||
# $1 - test function
|
||||
# $2 - domain
|
||||
|
||||
local dropacks urp
|
||||
local urp
|
||||
for urp in b 0 2 midsld; do
|
||||
pktws_curl_test_update "$1" "$2" --in-range=-s1 --lua-desync=oob:urp=$urp$dropack
|
||||
pktws_curl_test_update "$1" "$2" --in-range=-s1 --lua-desync=oob:urp=$urp
|
||||
done
|
||||
}
|
||||
|
||||
|
||||
@@ -63,7 +63,7 @@ pktws_seqovl_tests_tls()
|
||||
for split in '1 2' 'sniext sniext+1' 'sniext+3 sniext+4' 'midsld-1 midsld' '1 2,midsld'; do
|
||||
f="$(extract_arg 1 $split)"
|
||||
f2="$(extract_arg 2 $split)"
|
||||
pktws_curl_test_update $1 $2 $PAYLOAD --lua-desync=$MULTIDISORDER:pos=$f2:seqovl=$f && ok=1
|
||||
pktws_curl_test_update $1 $2 $pre $PAYLOAD --lua-desync=$MULTIDISORDER:pos=$f2:seqovl=$f && ok=1
|
||||
pktws_curl_test_update $testf $domain ${SEQOVL_PATTERN_HTTPS:+--blob=$pat:@"$SEQOVL_PATTERN_HTTPS" }$rnd_mod $pre $PAYLOAD --lua-desync=$MULTIDISORDER:pos=$f2:seqovl=$f:seqovl_pattern=$pat && ok=1
|
||||
done
|
||||
[ "$ok" = 1 ] && ok_any=1
|
||||
|
||||
@@ -11,7 +11,7 @@ pktws_check_http()
|
||||
|
||||
for split in '' multisplit $MULTIDISORDER; do
|
||||
pktws_curl_test_update "$1" "$2" --lua-desync=syndata ${split:+$PAYLOAD --lua-desync=$split}
|
||||
pktws_curl_test_update "$1" "$2" --lua-desync=syndata:blob=fake_default_http $PAYLOAD ${split:+$PAYLOAD --lua-desync=$split}
|
||||
pktws_curl_test_update "$1" "$2" --lua-desync=syndata:blob=fake_default_http ${split:+$PAYLOAD --lua-desync=$split}
|
||||
done
|
||||
}
|
||||
|
||||
|
||||
@@ -69,11 +69,11 @@ pktws_fake_https_vary_()
|
||||
{
|
||||
local ok_any=0 testf=$1 domain="$2" fooling="$3" pre="$4" post="$5"
|
||||
shift; shift; shift
|
||||
pktws_curl_test_update $testf $domain ${FAKE_HTTPS:+--blob=$fake:@"$FAKE_HTTPS" }${FAKED_PATTERN_HTTPS:+--blob=faked_pat:@"$FAKED_PATTERN_HTTPS" }$pre $PAYLOAD --lua-desync=fake:blob=$fake:$fooling:repeats=$FAKE_REPEATS --lua-desync=$splitf:${FAKED_PATTERN_HTTPS+pattern=faked_pat:}pos=$split:$fooling $post && ok_any=1
|
||||
pktws_curl_test_update $testf $domain ${FAKED_PATTERN_HTTPS:+--blob=faked_pat:@"$FAKED_PATTERN_HTTPS" }$pre $PAYLOAD --lua-desync=fake:blob=0x00000000:$fooling:repeats=$FAKE_REPEATS --lua-desync=$splitf:${FAKED_PATTERN_HTTPS+pattern=faked_pat:}pos=$split:$fooling $post && ok_any=1
|
||||
pktws_curl_test_update $testf $domain ${FAKE_HTTPS:+--blob=$fake:@"$FAKE_HTTPS" }${FAKED_PATTERN_HTTPS:+--blob=faked_pat:@"$FAKED_PATTERN_HTTPS" }$pre $PAYLOAD --lua-desync=fake:blob=0x00000000:$fooling:repeats=$FAKE_REPEATS --lua-desync=fake:blob=$fake:$fooling:tls_mod=rnd,dupsid:repeats=$FAKE_REPEATS --lua-desync=$splitf:${FAKED_PATTERN_HTTPS+pattern=faked_pat:}pos=$split:$fooling $post && ok_any=1
|
||||
pktws_curl_test_update $testf $domain ${FAKE_HTTPS:+--blob=$fake:@"$FAKE_HTTPS" }${FAKED_PATTERN_HTTPS:+--blob=faked_pat:@"$FAKED_PATTERN_HTTPS" }$pre $PAYLOAD --lua-desync=multisplit:blob=$fake:$fooling:pos=2:nodrop:repeats=$FAKE_REPEATS --lua-desync=$splitf:${FAKED_PATTERN_HTTPS+pattern=faked_pat:}pos=$split:$fooling $post && ok_any=1
|
||||
pktws_curl_test_update $testf $domain ${FAKE_HTTPS:+--blob=$fake:@"$FAKE_HTTPS" }${FAKED_PATTERN_HTTPS:+--blob=faked_pat:@"$FAKED_PATTERN_HTTPS" }$pre $PAYLOAD --lua-desync=fake:blob=$fake:$fooling:tls_mod=rnd,dupsid,padencap:repeats=$FAKE_REPEATS --lua-desync=$splitf:${FAKED_PATTERN_HTTPS+pattern=faked_pat:}pos=$split:$fooling $post && ok_any=1
|
||||
pktws_curl_test_update $testf $domain ${FAKE_HTTPS:+--blob=$fake:@"$FAKE_HTTPS" }${FAKED_PATTERN_HTTPS:+--blob=faked_pat:@"$FAKED_PATTERN_HTTPS" }$pre $PAYLOAD --lua-desync=fake:blob=$fake:$fooling:repeats=$FAKE_REPEATS --lua-desync=$splitf:${FAKED_PATTERN_HTTPS:+pattern=faked_pat:}pos=$split:$fooling $post && ok_any=1
|
||||
pktws_curl_test_update $testf $domain ${FAKED_PATTERN_HTTPS:+--blob=faked_pat:@"$FAKED_PATTERN_HTTPS" }$pre $PAYLOAD --lua-desync=fake:blob=0x00000000:$fooling:repeats=$FAKE_REPEATS --lua-desync=$splitf:${FAKED_PATTERN_HTTPS:+pattern=faked_pat:}pos=$split:$fooling $post && ok_any=1
|
||||
pktws_curl_test_update $testf $domain ${FAKE_HTTPS:+--blob=$fake:@"$FAKE_HTTPS" }${FAKED_PATTERN_HTTPS:+--blob=faked_pat:@"$FAKED_PATTERN_HTTPS" }$pre $PAYLOAD --lua-desync=fake:blob=0x00000000:$fooling:repeats=$FAKE_REPEATS --lua-desync=fake:blob=$fake:$fooling:tls_mod=rnd,dupsid:repeats=$FAKE_REPEATS --lua-desync=$splitf:${FAKED_PATTERN_HTTPS:+pattern=faked_pat:}pos=$split:$fooling $post && ok_any=1
|
||||
pktws_curl_test_update $testf $domain ${FAKE_HTTPS:+--blob=$fake:@"$FAKE_HTTPS" }${FAKED_PATTERN_HTTPS:+--blob=faked_pat:@"$FAKED_PATTERN_HTTPS" }$pre $PAYLOAD --lua-desync=multisplit:blob=$fake:$fooling:pos=2:nodrop:repeats=$FAKE_REPEATS --lua-desync=$splitf:${FAKED_PATTERN_HTTPS:+pattern=faked_pat:}pos=$split:$fooling $post && ok_any=1
|
||||
pktws_curl_test_update $testf $domain ${FAKE_HTTPS:+--blob=$fake:@"$FAKE_HTTPS" }${FAKED_PATTERN_HTTPS:+--blob=faked_pat:@"$FAKED_PATTERN_HTTPS" }$pre $PAYLOAD --lua-desync=fake:blob=$fake:$fooling:tls_mod=rnd,dupsid,padencap:repeats=$FAKE_REPEATS --lua-desync=$splitf:${FAKED_PATTERN_HTTPS:+pattern=faked_pat:}pos=$split:$fooling $post && ok_any=1
|
||||
[ "$ok_any" = 1 ] && ok=1
|
||||
|
||||
}
|
||||
|
||||
@@ -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,9 +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
|
||||
|
||||
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
|
||||
|
||||
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.
|
||||
|
||||
|
||||
@@ -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
|
||||
)
|
||||
@@ -59,45 +59,46 @@
|
||||
- [Random Data Generation](#random-data-generation)
|
||||
- [brandom](#brandom)
|
||||
- [Parsing](#parsing)
|
||||
- [parse\_hex](#parse_hex)
|
||||
- [parse_hex](#parse_hex)
|
||||
- [Cryptography](#cryptography)
|
||||
- [bcryptorandom](#bcryptorandom)
|
||||
- [bxor,bor,band](#bxorborband)
|
||||
- [hash](#hash)
|
||||
- [aes](#aes)
|
||||
- [aes\_gcm](#aes_gcm)
|
||||
- [aes\_ctr](#aes_ctr)
|
||||
- [aes_gcm](#aes_gcm)
|
||||
- [aes_ctr](#aes_ctr)
|
||||
- [hkdf](#hkdf)
|
||||
- [Compression](#compression)
|
||||
- [gunzip](#gunzip)
|
||||
- [gzip](#gzip)
|
||||
- [System functions](#system-functions)
|
||||
- [uname](#uname)
|
||||
- [clock\_gettime](#clock_gettime)
|
||||
- [clock_gettime](#clock_gettime)
|
||||
- [getpid](#getpid)
|
||||
- [stat](#stat)
|
||||
- [time](#time)
|
||||
- [Packet handling options](#packet-handling-options)
|
||||
- [standard reconstruct](#standard-reconstruct)
|
||||
- [standard rawsend](#standard-rawsend)
|
||||
- [Dissection and reconstruction](#dissection-and-reconstruction)
|
||||
- [dissect](#dissect)
|
||||
- [reconstruct\_dissect](#reconstruct_dissect)
|
||||
- [reconstruct\_hdr](#reconstruct_hdr)
|
||||
- [csum\_fix](#csum_fix)
|
||||
- [reconstruct_dissect](#reconstruct_dissect)
|
||||
- [reconstruct_hdr](#reconstruct_hdr)
|
||||
- [csum_fix](#csum_fix)
|
||||
- [conntrack](#conntrack)
|
||||
- [Obtaining IP addresses](#obtaining-ip-addresses)
|
||||
- [Receiving and sending Packets](#receiving-and-sending-packets)
|
||||
- [rawsend](#rawsend)
|
||||
- [raw\_packet](#raw_packet)
|
||||
- [raw_packet](#raw_packet)
|
||||
- [Working with payloads](#working-with-payloads)
|
||||
- [Markers](#markers)
|
||||
- [resolve\_pos](#resolve_pos)
|
||||
- [tls\_mod](#tls_mod)
|
||||
- [resolve_pos](#resolve_pos)
|
||||
- [tls_mod](#tls_mod)
|
||||
- [Instance execution management](#instance-execution-management)
|
||||
- [instance\_cutoff](#instance_cutoff)
|
||||
- [lua\_cutoff](#lua_cutoff)
|
||||
- [execution\_plan](#execution_plan)
|
||||
- [execution\_plan\_cancel](#execution_plan_cancel)
|
||||
- [instance_cutoff](#instance_cutoff)
|
||||
- [lua_cutoff](#lua_cutoff)
|
||||
- [execution_plan](#execution_plan)
|
||||
- [execution_plan_cancel](#execution_plan_cancel)
|
||||
- [zapret-lib.lua base function library](#zapret-liblua-base-function-library)
|
||||
- [Base desync functions](#base-desync-functions)
|
||||
- [luaexec](#luaexec)
|
||||
@@ -105,16 +106,16 @@
|
||||
- [pktdebug](#pktdebug)
|
||||
- [argdebug](#argdebug)
|
||||
- [posdebug](#posdebug)
|
||||
- [detect\_payload\_str](#detect_payload_str)
|
||||
- [desync\_orchestrator\_example](#desync_orchestrator_example)
|
||||
- [detect_payload_str](#detect_payload_str)
|
||||
- [desync_orchestrator_example](#desync_orchestrator_example)
|
||||
- [Utility functions](#utility-functions)
|
||||
- [var\_debug](#var_debug)
|
||||
- [var_debug](#var_debug)
|
||||
- [deepcopy](#deepcopy)
|
||||
- [logical\_xor](#logical_xor)
|
||||
- [array\_search](#array_search)
|
||||
- [logical_xor](#logical_xor)
|
||||
- [array_search](#array_search)
|
||||
- [String operations](#string-operations)
|
||||
- [in\_list](#in_list)
|
||||
- [find\_next\_line](#find_next_line)
|
||||
- [in_list](#in_list)
|
||||
- [find_next_line](#find_next_line)
|
||||
- [Raw string handling](#raw-string-handling)
|
||||
- [hex](#hex)
|
||||
- [pattern](#pattern)
|
||||
@@ -122,18 +123,18 @@
|
||||
- [TCP sequence number handling](#tcp-sequence-number-handling)
|
||||
- [Position handling](#position-handling)
|
||||
- [Dissection](#dissection)
|
||||
- [dissect\_url](#dissect_url)
|
||||
- [dissect\_nld](#dissect_nld)
|
||||
- [dissect\_http](#dissect_http)
|
||||
- [dissect\_tls](#dissect_tls)
|
||||
- [dissect_url](#dissect_url)
|
||||
- [dissect_nld](#dissect_nld)
|
||||
- [dissect_http](#dissect_http)
|
||||
- [dissect_tls](#dissect_tls)
|
||||
- [Working with L3 and L4 protocol elements](#working-with-l3-and-l4-protocol-elements)
|
||||
- [find\_tcp\_options](#find_tcp_options)
|
||||
- [find_tcp_options](#find_tcp_options)
|
||||
- [ip6hdr](#ip6hdr)
|
||||
- [ip protocol](#ip-protocol)
|
||||
- [packet\_len](#packet_len)
|
||||
- [packet_len](#packet_len)
|
||||
- [Working with hostnames](#working-with-hostnames)
|
||||
- [genhost](#genhost)
|
||||
- [host\_ip](#host_ip)
|
||||
- [host_ip](#host_ip)
|
||||
- [File name and path operations](#file-name-and-path-operations)
|
||||
- [Reading and writing Files](#reading-and-writing-files)
|
||||
- [Data compression](#data-compression)
|
||||
@@ -142,29 +143,29 @@
|
||||
- [standard ipid](#standard-ipid)
|
||||
- [standard fooling](#standard-fooling)
|
||||
- [standard ipfrag](#standard-ipfrag)
|
||||
- [apply\_ip\_id](#apply_ip_id)
|
||||
- [apply\_fooling](#apply_fooling)
|
||||
- [apply_ip_id](#apply_ip_id)
|
||||
- [apply_fooling](#apply_fooling)
|
||||
- [ipfrag2](#ipfrag2)
|
||||
- [wssize\_rewrite](#wssize_rewrite)
|
||||
- [dis\_reverse](#dis_reverse)
|
||||
- [wssize_rewrite](#wssize_rewrite)
|
||||
- [dis_reverse](#dis_reverse)
|
||||
- [IP addresses and interfaces](#ip-addresses-and-interfaces)
|
||||
- [Sending](#sending)
|
||||
- [rawsend\_dissect\_ipfrag](#rawsend_dissect_ipfrag)
|
||||
- [rawsend\_dissect\_segmented](#rawsend_dissect_segmented)
|
||||
- [rawsend\_payload\_segmented](#rawsend_payload_segmented)
|
||||
- [rawsend_dissect_ipfrag](#rawsend_dissect_ipfrag)
|
||||
- [rawsend_dissect_segmented](#rawsend_dissect_segmented)
|
||||
- [rawsend_payload_segmented](#rawsend_payload_segmented)
|
||||
- [Standard direction and payload filters](#standard-direction-and-payload-filters)
|
||||
- [Working with multi-packet payloads](#working-with-multi-packet-payloads)
|
||||
- [Orchestration](#orchestration)
|
||||
- [instance\_cutoff\_shim](#instance_cutoff_shim)
|
||||
- [cutoff\_shim\_check](#cutoff_shim_check)
|
||||
- [apply\_arg\_prefix](#apply_arg_prefix)
|
||||
- [apply\_execution\_plan](#apply_execution_plan)
|
||||
- [verdict\_aggregate](#verdict_aggregate)
|
||||
- [plan\_instance\_execute](#plan_instance_execute)
|
||||
- [plan\_instance\_pop](#plan_instance_pop)
|
||||
- [plan\_clear](#plan_clear)
|
||||
- [instance_cutoff_shim](#instance_cutoff_shim)
|
||||
- [cutoff_shim_check](#cutoff_shim_check)
|
||||
- [apply_arg_prefix](#apply_arg_prefix)
|
||||
- [apply_execution_plan](#apply_execution_plan)
|
||||
- [verdict_aggregate](#verdict_aggregate)
|
||||
- [plan_instance_execute](#plan_instance_execute)
|
||||
- [plan_instance_pop](#plan_instance_pop)
|
||||
- [plan_clear](#plan_clear)
|
||||
- [orchestrate](#orchestrate)
|
||||
- [replay\_execution\_plan](#replay_execution_plan)
|
||||
- [replay_execution_plan](#replay_execution_plan)
|
||||
- [zapret-antidpi.lua DPI attack program library](#zapret-antidpilua-dpi-attack-program-library)
|
||||
- [Standard parameter sets](#standard-parameter-sets)
|
||||
- [standard direction](#standard-direction)
|
||||
@@ -174,22 +175,22 @@
|
||||
- [send](#send)
|
||||
- [pktmod](#pktmod)
|
||||
- [HTTP fooling](#http-fooling)
|
||||
- [http\_hostcase](#http_hostcase)
|
||||
- [http\_domcase](#http_domcase)
|
||||
- [http\_methodeol](#http_methodeol)
|
||||
- [http\_unixeol](#http_unixeol)
|
||||
- [http_hostcase](#http_hostcase)
|
||||
- [http_domcase](#http_domcase)
|
||||
- [http_methodeol](#http_methodeol)
|
||||
- [http_unixeol](#http_unixeol)
|
||||
- [Window size replacement](#window-size-replacement)
|
||||
- [wsize](#wsize)
|
||||
- [wssize](#wssize)
|
||||
- [Fakes](#fakes)
|
||||
- [syndata](#syndata)
|
||||
- [tls\_client\_hello\_clone](#tls_client_hello_clone)
|
||||
- [tls_client_hello_clone](#tls_client_hello_clone)
|
||||
- [fake](#fake)
|
||||
- [rst](#rst)
|
||||
- [TCP segmentation](#tcp-segmentation)
|
||||
- [multisplit](#multisplit)
|
||||
- [multidisorder](#multidisorder)
|
||||
- [multidisorder\_legacy](#multidisorder_legacy)
|
||||
- [multidisorder_legacy](#multidisorder_legacy)
|
||||
- [fakedsplit](#fakedsplit)
|
||||
- [fakeddisorder](#fakeddisorder)
|
||||
- [hostfakesplit](#hostfakesplit)
|
||||
@@ -197,32 +198,35 @@
|
||||
- [oob](#oob)
|
||||
- [UDP Fooling](#udp-fooling)
|
||||
- [udplen](#udplen)
|
||||
- [dht\_dn](#dht_dn)
|
||||
- [dht_dn](#dht_dn)
|
||||
- [Other Functions](#other-functions)
|
||||
- [synack](#synack)
|
||||
- [synack\_split](#synack_split)
|
||||
- [synack_split](#synack_split)
|
||||
- [zapret-auto.lua automation and orchestration library](#zapret-autolua-automation-and-orchestration-library)
|
||||
- [State storage](#state-storage)
|
||||
- [automate\_conn\_record](#automate_conn_record)
|
||||
- [standard\_hostkey](#standard_hostkey)
|
||||
- [automate\_host\_record](#automate_host_record)
|
||||
- [automate_conn_record](#automate_conn_record)
|
||||
- [standard_hostkey](#standard_hostkey)
|
||||
- [automate_host_record](#automate_host_record)
|
||||
- [Handling successes and failures](#handling-successes-and-failures)
|
||||
- [automate\_failure\_counter](#automate_failure_counter)
|
||||
- [automate\_failure\_counter\_reset](#automate_failure_counter_reset)
|
||||
- [automate_failure_counter](#automate_failure_counter)
|
||||
- [automate_failure_counter_reset](#automate_failure_counter_reset)
|
||||
- [Success and failure detection](#success-and-failure-detection)
|
||||
- [automate\_failure\_check](#automate_failure_check)
|
||||
- [standard\_success\_detector](#standard_success_detector)
|
||||
- [standard\_failure\_detector](#standard_failure_detector)
|
||||
- [automate_failure_check](#automate_failure_check)
|
||||
- [standard_success_detector](#standard_success_detector)
|
||||
- [standard_failure_detector](#standard_failure_detector)
|
||||
- [Orchestrators](#orchestrators)
|
||||
- [circular](#circular)
|
||||
- [repeater](#repeater)
|
||||
- [condition](#condition)
|
||||
- [per_instance_condition](#per_instance_condition)
|
||||
- [stopif](#stopif)
|
||||
- [iff functions](#iff-functions)
|
||||
- [cond\_true](#cond_true)
|
||||
- [cond\_false](#cond_false)
|
||||
- [cond\_random](#cond_random)
|
||||
- [cond\_payload\_str](#cond_payload_str)
|
||||
- [cond_true](#cond_true)
|
||||
- [cond_false](#cond_false)
|
||||
- [cond_random](#cond_random)
|
||||
- [cond_payload_str](#cond_payload_str)
|
||||
- [cond_tcp_has_ts](#cond_tcp_has_ts)
|
||||
- [cond_lua](#cond_lua)
|
||||
- [Auxiliary programs](#auxiliary-programs)
|
||||
- [ip2net](#ip2net)
|
||||
- [mdig](#mdig)
|
||||
@@ -246,16 +250,16 @@
|
||||
- [List management system](#list-management-system)
|
||||
- [Standard list files](#standard-list-files)
|
||||
- [ipset scripts](#ipset-scripts)
|
||||
- [clear\_lists.sh](#clear_listssh)
|
||||
- [create\_ipset.sh](#create_ipsetsh)
|
||||
- [get\_config.sh](#get_configsh)
|
||||
- [get\_user.sh](#get_usersh)
|
||||
- [get\_ipban.sh](#get_ipbansh)
|
||||
- [get\_exclude.sh](#get_excludesh)
|
||||
- [get\_antifilter\_\*.sh](#get_antifilter_sh)
|
||||
- [get\_antizapret\_domains.sh](#get_antizapret_domainssh)
|
||||
- [get\_refilter\_\*.sh](#get_refilter_sh)
|
||||
- [get\_reestr\_\*.sh](#get_reestr_sh)
|
||||
- [clear_lists.sh](#clear_listssh)
|
||||
- [create_ipset.sh](#create_ipsetsh)
|
||||
- [get_config.sh](#get_configsh)
|
||||
- [get_user.sh](#get_usersh)
|
||||
- [get_ipban.sh](#get_ipbansh)
|
||||
- [get_exclude.sh](#get_excludesh)
|
||||
- [get_antifilter_*.sh](#get_antifilter_sh)
|
||||
- [get_antizapret_domains.sh](#get_antizapret_domainssh)
|
||||
- [get_refilter_*.sh](#get_refilter_sh)
|
||||
- [get_reestr_*.sh](#get_reestr_sh)
|
||||
- [ipban system](#ipban-system)
|
||||
- [Init scripts](#init-scripts)
|
||||
- [Firewall integration](#firewall-integration)
|
||||
@@ -633,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
|
||||
@@ -751,9 +756,11 @@ Table of recognizable payload types and flow protocols
|
||||
| tls | tcp | tls_client_hello<br>tls_server_hello |
|
||||
| xmpp | tcp | xmpp_stream<br>xmpp_starttls<br>xmpp_proceed<br>xmpp_features |
|
||||
| mtproto | tcp | mtproto_initial |
|
||||
| bt | tcp | bt_handshake |
|
||||
| quic | udp | quic_initial |
|
||||
| wireguard | udp | wireguard_initiation<br>wireguard_response<br>wireguard_cookie<br>wireguard_keepalive |
|
||||
| dht | udp | dht |
|
||||
| utp_bt | udp | utp_bt_handshake |
|
||||
| discord | udp | discord_ip_discovery |
|
||||
| stun | udp | stun |
|
||||
| dns | udp | dns_query dns_response |
|
||||
@@ -1387,6 +1394,7 @@ All multi-byte numeric values are automatically converted from network byte orde
|
||||
| :------------ | :----- | :--------------------------------------------------------------- |
|
||||
| ip | table | IPv4 header |
|
||||
| ip6 | table | IPv6 header |
|
||||
| frag_off | number | IP fragment offset. present only in IP fragments. |
|
||||
| tcp | table | TCP header |
|
||||
| udp | table | UDP header |
|
||||
| icmp | table | ICMP header |
|
||||
@@ -1991,6 +1999,34 @@ If successful returns the following table :
|
||||
|
||||
In case of error returns 3 values : nil, error string, error number (errno).
|
||||
|
||||
#### time
|
||||
|
||||
```
|
||||
function localtime(unixtime)
|
||||
function gmtime(unixtime)
|
||||
function timelocal(tm)
|
||||
function timegm(tm)
|
||||
```
|
||||
|
||||
localtime and gmtime return dissected unixtime similar to C "struct tm". timelocal and timegm are reverse functions.
|
||||
|
||||
| Field | Type | Description |
|
||||
| :------- | :----- | :---------- |
|
||||
| sec* | number | second |
|
||||
| min* | number | minute |
|
||||
| hour* | number | hour |
|
||||
| mon* | number | month starting from 0 |
|
||||
| mday* | number | day of month starting from 1 |
|
||||
| year* | number | full year, not from 1900 |
|
||||
| wday | number | day of week. 0 = sunday |
|
||||
| yday | number | day of year starting from 0 |
|
||||
| isdst* | number | not zero if summer time in effect |
|
||||
| zone | string | time zone |
|
||||
| str | string | formatted string: "dd.mm.yyyy hh:mi:ss" |
|
||||
|
||||
Fields marked with `*` are required for reverse translation.
|
||||
|
||||
|
||||
### Packet handling options
|
||||
|
||||
The following functions use standard sets of options: `rawsend` and `reconstruct`.
|
||||
@@ -2067,10 +2103,12 @@ Those functions receive an already prepared dissect.
|
||||
function reconstruct_dissect(dissect[, reconstruct_opts])
|
||||
```
|
||||
|
||||
Returns `raw_ip`. All checksums are calculated automatically. L4 checksums are intentionally corrupted if `badsum` is specified in `reconstruct_opts`.
|
||||
Returns `raw_ip`. All checksums are calculated automatically. L4 checksums are intentionally corrupted if `badsum` is specified in [reconstruct_opts](#standard-reconstruct).
|
||||
|
||||
Reconstructing dissects with IP fragmentation involves a specific interaction between Lua and C code.
|
||||
The Lua code must prepare a dissect of the full packet intended for fragmentation, but fill certain fields as they should appear in the fragment:
|
||||
Reconstruction of fragmented IP packets involves special magic.
|
||||
|
||||
1. if the "frag_off" field is present, tcp/udp/icmp headers are ignored, payload contains raw ip payload. Incoming fragmented packets come in this form. nfqws2 does not defragment at the IP layer. But this is very persistently done by Linux systems - in order for a fragment to come to nfqws2, you need to try hard by inserting "notrack" into prerouting or output. Dissects in this form can be reconstructed as is. But preparing them in Lua is extremely inconvenient, since you will have to go through the black magic of working with a binary representation.
|
||||
2. If the "frag_off" field is absent, fragment reconstruction is performed on the entire packet's dissect involving both Lua and C code. Lua code must prepare a dissect of the full packet intended for fragmentation, but fill certain fields as they should appear in the fragment:
|
||||
|
||||
- **ipv4**: `ip.ip_len` must be calculated as it should appear in the fragment.
|
||||
The C code uses `ip.ip_len` to determine the size of the fragmented portion.
|
||||
@@ -2296,6 +2334,7 @@ Returns an array of information about all subsequent, pending instances in the c
|
||||
| range | table | effective range of [counters](#in-profile-filters) `--in-range` or `--out-range` depending on the current direction |
|
||||
| payload | table | effective payload filter : payload name indexed table. |
|
||||
| payload_filter | string | effective payload filter : a comma-separated list of payload names. |
|
||||
| arg | table | instance arguments |
|
||||
|
||||
**range**
|
||||
|
||||
@@ -3492,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
|
||||
|
||||
@@ -3501,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
|
||||
@@ -3515,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
|
||||
|
||||
```
|
||||
@@ -3531,10 +3579,10 @@ Retrieves, removes, and returns the first element of the [execution plan](#execu
|
||||
### plan_clear
|
||||
|
||||
```
|
||||
function plan_clear(desync)
|
||||
function plan_clear(desync, max)
|
||||
```
|
||||
|
||||
Clears the [execution plan](#execution_plan) in `desync.plan` by removing all `instance` elements.
|
||||
Clears up to the "max" instances if "max" is defined or the whole [execution plan](#execution_plan) in `desync.plan`.
|
||||
|
||||
### orchestrate
|
||||
|
||||
@@ -3548,10 +3596,10 @@ If `ctx=nil`, it does nothing, assuming the plan is already in `desync.plan`.
|
||||
### replay_execution_plan
|
||||
|
||||
```
|
||||
function replay_execution_plan(desync)
|
||||
function replay_execution_plan(desync, max)
|
||||
```
|
||||
|
||||
Executes the entire [execution plan](#execution_plan) from `desync.plan`, respecting the [instance cutoff](#instance_cutoff) and standard [payload](#in-profile-filters) and [range](#in-profile-filters) filters.
|
||||
Executes up to the "max" instances if "max" is defined, or the entire [execution plan](#execution_plan) from `desync.plan`, respecting the [instance cutoff](#instance_cutoff) and standard [payload](#in-profile-filters) and [range](#in-profile-filters) filters.
|
||||
|
||||
# zapret-antidpi.lua DPI attack program library
|
||||
|
||||
@@ -4349,13 +4397,26 @@ function condition(ctx, desync)
|
||||
|
||||
- arg: `iff` - name of the [iff function](#iff-functions)
|
||||
- arg: `neg` - invert the `iff` value; defaults to `false`
|
||||
- arg: `instances` - how many following instances to execute conditionally. all if not defined.
|
||||
|
||||
`condition` calls `iff`. If `iff xor neg = true`, all instances in the `plan` are executed; otherwise, the plan is cleared.
|
||||
|
||||
### per_instance_condition
|
||||
|
||||
```
|
||||
function per_instance_condition(ctx, desync)
|
||||
```
|
||||
|
||||
- arg: `instances` - how many following instances to execute conditionally. all if not defined.
|
||||
|
||||
All following instanced are called only if they have "cond" argument with the "iff" function name and it returns true. The "cond_neg" argument inverts "cond" result.
|
||||
Names are not iff/neg to avoid conflict with other orchestrators.
|
||||
|
||||
|
||||
### stopif
|
||||
|
||||
```
|
||||
function condition(ctx, desync)
|
||||
function stopif(ctx, desync)
|
||||
```
|
||||
|
||||
- arg: `iff` - name of the [iff function](#iff-functions)
|
||||
@@ -4407,6 +4468,23 @@ function cond_payload_str(desync)
|
||||
Returns `true` if the substring `pattern` is present in `desync.dis.payload`.
|
||||
This is a basic signature detector. If the C code does not recognize the protocol you need, you can write your own signature detector and run subsequent instances under a `condition` orchestrator using your detector as the `iff` function.
|
||||
|
||||
#### cond_tcp_has_ts
|
||||
|
||||
```
|
||||
function cond_tcp_ts(desync)
|
||||
```
|
||||
|
||||
Returns `true` if the dissect is tcp and has tcp timestamp option.
|
||||
|
||||
#### cond_lua
|
||||
|
||||
```
|
||||
function cond_lua(desync)
|
||||
```
|
||||
|
||||
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
|
||||
|
||||
@@ -5044,7 +5122,7 @@ filter_apply_hostlist_target()
|
||||
# $1 - name of the variable containing nfqws2 options
|
||||
```
|
||||
|
||||
Replaces the `<HOSTLIST>` and `<HOSTLIST_AUTO>` markers in $1 depending on the [MODE_FILTER](#config-file) and the presence of list files in ipset.
|
||||
Replaces the `<HOSTLIST>` and `<HOSTLIST_NOAUTO>` markers in $1 depending on the [MODE_FILTER](#config-file) and the presence of list files in ipset.
|
||||
|
||||
```
|
||||
standard_mode_daemons()
|
||||
@@ -5136,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
|
||||
|
||||
```
|
||||
@@ -5424,8 +5511,8 @@ There are several options :
|
||||
|
||||
## Windows Server
|
||||
|
||||
winws2 is linked against wlanapi.dll which is absent by default.
|
||||
To solve this problem run power shell as administrator and execute command `Install-WindowsFeature -Name Wireless-Networking`.
|
||||
To use `--ssid-filter` install wireless networking feature.
|
||||
Run power shell as administrator and execute command `Install-WindowsFeature -Name Wireless-Networking`.
|
||||
Then reboot the system.
|
||||
|
||||
## Windows ARM64
|
||||
|
||||
265
docs/manual.md
265
docs/manual.md
@@ -38,7 +38,7 @@
|
||||
- [Структура track](#структура-track)
|
||||
- [Особенности обработки icmp](#особенности-обработки-icmp)
|
||||
- [Особенности обработки raw ip](#особенности-обработки-raw-ip)
|
||||
- [C интерфейс nfqws2](#c-интерфейс-nfqws2)
|
||||
- [С интерфейс nfqws2](#с-интерфейс-nfqws2)
|
||||
- [Базовые константы](#базовые-константы)
|
||||
- [Стандартные блобы](#стандартные-блобы)
|
||||
- [Переменные окружения](#переменные-окружения)
|
||||
@@ -56,45 +56,46 @@
|
||||
- [Генерация случайных данных](#генерация-случайных-данных)
|
||||
- [brandom](#brandom)
|
||||
- [Парсинг](#парсинг)
|
||||
- [parse\_hex](#parse_hex)
|
||||
- [parse_hex](#parse_hex)
|
||||
- [Криптография](#криптография)
|
||||
- [bcryptorandom](#bcryptorandom)
|
||||
- [bxor,bor,band](#bxorborband)
|
||||
- [hash](#hash)
|
||||
- [aes](#aes)
|
||||
- [aes\_gcm](#aes_gcm)
|
||||
- [aes\_ctr](#aes_ctr)
|
||||
- [aes_gcm](#aes_gcm)
|
||||
- [aes_ctr](#aes_ctr)
|
||||
- [hkdf](#hkdf)
|
||||
- [Компрессия](#компрессия)
|
||||
- [gunzip](#gunzip)
|
||||
- [gzip](#gzip)
|
||||
- [Системные функции](#системные-функции)
|
||||
- [uname](#uname)
|
||||
- [clock\_gettime](#clock_gettime)
|
||||
- [clock_gettime](#clock_gettime)
|
||||
- [getpid](#getpid)
|
||||
- [stat](#stat)
|
||||
- [time](#time)
|
||||
- [Опции по работе с пакетами](#опции-по-работе-с-пакетами)
|
||||
- [standard reconstruct](#standard-reconstruct)
|
||||
- [standard rawsend](#standard-rawsend)
|
||||
- [Диссекция и реконструкция](#диссекция-и-реконструкция)
|
||||
- [dissect](#dissect)
|
||||
- [reconstruct\_dissect](#reconstruct_dissect)
|
||||
- [reconstruct\_hdr](#reconstruct_hdr)
|
||||
- [csum\_fix](#csum_fix)
|
||||
- [reconstruct_dissect](#reconstruct_dissect)
|
||||
- [reconstruct_hdr](#reconstruct_hdr)
|
||||
- [csum_fix](#csum_fix)
|
||||
- [conntrack](#conntrack)
|
||||
- [Получение ip адресов](#получение-ip-адресов)
|
||||
- [Прием и отсылка пакетов](#прием-и-отсылка-пакетов)
|
||||
- [rawsend](#rawsend)
|
||||
- [raw\_packet](#raw_packet)
|
||||
- [raw_packet](#raw_packet)
|
||||
- [Работа с пейлоадами](#работа-с-пейлоадами)
|
||||
- [маркеры](#маркеры)
|
||||
- [resolve\_pos](#resolve_pos)
|
||||
- [tls\_mod](#tls_mod)
|
||||
- [resolve_pos](#resolve_pos)
|
||||
- [tls_mod](#tls_mod)
|
||||
- [Управление выполнением инстансов](#управление-выполнением-инстансов)
|
||||
- [instance\_cutoff](#instance_cutoff)
|
||||
- [lua\_cutoff](#lua_cutoff)
|
||||
- [execution\_plan](#execution_plan)
|
||||
- [execution\_plan\_cancel](#execution_plan_cancel)
|
||||
- [instance_cutoff](#instance_cutoff)
|
||||
- [lua_cutoff](#lua_cutoff)
|
||||
- [execution_plan](#execution_plan)
|
||||
- [execution_plan_cancel](#execution_plan_cancel)
|
||||
- [Библиотека базовых функций zapret-lib.lua](#библиотека-базовых-функций-zapret-liblua)
|
||||
- [Базовые desync функции](#базовые-desync-функции)
|
||||
- [luaexec](#luaexec)
|
||||
@@ -102,16 +103,16 @@
|
||||
- [pktdebug](#pktdebug)
|
||||
- [argdebug](#argdebug)
|
||||
- [posdebug](#posdebug)
|
||||
- [detect\_payload\_str](#detect_payload_str)
|
||||
- [desync\_orchestrator\_example](#desync_orchestrator_example)
|
||||
- [detect_payload_str](#detect_payload_str)
|
||||
- [desync_orchestrator_example](#desync_orchestrator_example)
|
||||
- [Служебные функции](#служебные-функции)
|
||||
- [var\_debug](#var_debug)
|
||||
- [var_debug](#var_debug)
|
||||
- [deepcopy](#deepcopy)
|
||||
- [logical\_xor](#logical_xor)
|
||||
- [array\_search](#array_search)
|
||||
- [logical_xor](#logical_xor)
|
||||
- [array_search](#array_search)
|
||||
- [Работа со строками](#работа-со-строками)
|
||||
- [in\_list](#in_list)
|
||||
- [find\_next\_line](#find_next_line)
|
||||
- [in_list](#in_list)
|
||||
- [find_next_line](#find_next_line)
|
||||
- [Обслуживание raw string](#обслуживание-raw-string)
|
||||
- [hex](#hex)
|
||||
- [pattern](#pattern)
|
||||
@@ -119,18 +120,18 @@
|
||||
- [Обслуживание tcp sequence numbers](#обслуживание-tcp-sequence-numbers)
|
||||
- [Обслуживание позиций](#обслуживание-позиций)
|
||||
- [Диссекция](#диссекция)
|
||||
- [dissect\_url](#dissect_url)
|
||||
- [dissect\_nld](#dissect_nld)
|
||||
- [dissect\_http](#dissect_http)
|
||||
- [dissect\_tls](#dissect_tls)
|
||||
- [dissect_url](#dissect_url)
|
||||
- [dissect_nld](#dissect_nld)
|
||||
- [dissect_http](#dissect_http)
|
||||
- [dissect_tls](#dissect_tls)
|
||||
- [Работа с элементами L3 и L4 протоколов](#работа-с-элементами-l3-и-l4-протоколов)
|
||||
- [find\_tcp\_options](#find_tcp_options)
|
||||
- [find_tcp_options](#find_tcp_options)
|
||||
- [ip6hdr](#ip6hdr)
|
||||
- [ip protocol](#ip-protocol)
|
||||
- [packet\_len](#packet_len)
|
||||
- [packet_len](#packet_len)
|
||||
- [Работа с именами хостов](#работа-с-именами-хостов)
|
||||
- [genhost](#genhost)
|
||||
- [host\_ip](#host_ip)
|
||||
- [host_ip](#host_ip)
|
||||
- [Операции с именами файлов и путями](#операции-с-именами-файлов-и-путями)
|
||||
- [Чтение и запись файлов](#чтение-и-запись-файлов)
|
||||
- [Компрессия данных](#компрессия-данных)
|
||||
@@ -139,29 +140,29 @@
|
||||
- [standard ipid](#standard-ipid)
|
||||
- [standard fooling](#standard-fooling)
|
||||
- [standard ipfrag](#standard-ipfrag)
|
||||
- [apply\_ip\_id](#apply_ip_id)
|
||||
- [apply\_fooling](#apply_fooling)
|
||||
- [apply_ip_id](#apply_ip_id)
|
||||
- [apply_fooling](#apply_fooling)
|
||||
- [ipfrag2](#ipfrag2)
|
||||
- [wssize\_rewrite](#wssize_rewrite)
|
||||
- [dis\_reverse](#dis_reverse)
|
||||
- [wssize_rewrite](#wssize_rewrite)
|
||||
- [dis_reverse](#dis_reverse)
|
||||
- [IP адреса и интерфейсы](#ip-адреса-и-интерфейсы)
|
||||
- [Отсылка](#отсылка)
|
||||
- [rawsend\_dissect\_ipfrag](#rawsend_dissect_ipfrag)
|
||||
- [rawsend\_dissect\_segmented](#rawsend_dissect_segmented)
|
||||
- [rawsend\_payload\_segmented](#rawsend_payload_segmented)
|
||||
- [rawsend_dissect_ipfrag](#rawsend_dissect_ipfrag)
|
||||
- [rawsend_dissect_segmented](#rawsend_dissect_segmented)
|
||||
- [rawsend_payload_segmented](#rawsend_payload_segmented)
|
||||
- [Стандартные фильтры direction и payload](#стандартные-фильтры-direction-и-payload)
|
||||
- [Работа с многопакетными пейлоадами](#работа-с-многопакетными-пейлоадами)
|
||||
- [Работа с многопакетными пейлоадам](#работа-с-многопакетными-пейлоадам)
|
||||
- [Оркестрация](#оркестрация)
|
||||
- [instance\_cutoff\_shim](#instance_cutoff_shim)
|
||||
- [cutoff\_shim\_check](#cutoff_shim_check)
|
||||
- [apply\_arg\_prefix](#apply_arg_prefix)
|
||||
- [apply\_execution\_plan](#apply_execution_plan)
|
||||
- [verdict\_aggregate](#verdict_aggregate)
|
||||
- [plan\_instance\_execute](#plan_instance_execute)
|
||||
- [plan\_instance\_pop](#plan_instance_pop)
|
||||
- [plan\_clear](#plan_clear)
|
||||
- [instance_cutoff_shim](#instance_cutoff_shim)
|
||||
- [cutoff_shim_check](#cutoff_shim_check)
|
||||
- [apply_arg_prefix](#apply_arg_prefix)
|
||||
- [apply_execution_plan](#apply_execution_plan)
|
||||
- [verdict_aggregate](#verdict_aggregate)
|
||||
- [plan_instance_execute](#plan_instance_execute)
|
||||
- [plan_instance_pop](#plan_instance_pop)
|
||||
- [plan_clear](#plan_clear)
|
||||
- [orchestrate](#orchestrate)
|
||||
- [replay\_execution\_plan](#replay_execution_plan)
|
||||
- [replay_execution_plan](#replay_execution_plan)
|
||||
- [Библиотека программ атаки на DPI zapret-antidpi.lua](#библиотека-программ-атаки-на-dpi-zapret-antidpilua)
|
||||
- [Стандартные наборы параметров](#стандартные-наборы-параметров)
|
||||
- [standard direction](#standard-direction)
|
||||
@@ -171,22 +172,22 @@
|
||||
- [send](#send)
|
||||
- [pktmod](#pktmod)
|
||||
- [Дурение http](#дурение-http)
|
||||
- [http\_hostcase](#http_hostcase)
|
||||
- [http\_domcase](#http_domcase)
|
||||
- [http\_methodeol](#http_methodeol)
|
||||
- [http\_unixeol](#http_unixeol)
|
||||
- [http_hostcase](#http_hostcase)
|
||||
- [http_domcase](#http_domcase)
|
||||
- [http_methodeol](#http_methodeol)
|
||||
- [http_unixeol](#http_unixeol)
|
||||
- [Замена window size](#замена-window-size)
|
||||
- [wsize](#wsize)
|
||||
- [wssize](#wssize)
|
||||
- [Фейки](#фейки)
|
||||
- [syndata](#syndata)
|
||||
- [tls\_client\_hello\_clone](#tls_client_hello_clone)
|
||||
- [tls_client_hello_clone](#tls_client_hello_clone)
|
||||
- [fake](#fake)
|
||||
- [rst](#rst)
|
||||
- [TCP сегментация](#tcp-сегментация)
|
||||
- [multisplit](#multisplit)
|
||||
- [multidisorder](#multidisorder)
|
||||
- [multidisorder\_legacy](#multidisorder_legacy)
|
||||
- [multidisorder_legacy](#multidisorder_legacy)
|
||||
- [fakedsplit](#fakedsplit)
|
||||
- [fakeddisorder](#fakeddisorder)
|
||||
- [hostfakesplit](#hostfakesplit)
|
||||
@@ -194,32 +195,35 @@
|
||||
- [oob](#oob)
|
||||
- [Дурение udp](#дурение-udp)
|
||||
- [udplen](#udplen)
|
||||
- [dht\_dn](#dht_dn)
|
||||
- [dht_dn](#dht_dn)
|
||||
- [Другие функции](#другие-функции)
|
||||
- [synack](#synack)
|
||||
- [synack\_split](#synack_split)
|
||||
- [synack_split](#synack_split)
|
||||
- [Библиотека программ автоматизации и оркестрации zapret-auto.lua](#библиотека-программ-автоматизации-и-оркестрации-zapret-autolua)
|
||||
- [Хранилище состояний](#хранилище-состояний)
|
||||
- [automate\_conn\_record](#automate_conn_record)
|
||||
- [standard\_hostkey](#standard_hostkey)
|
||||
- [automate\_host\_record](#automate_host_record)
|
||||
- [automate_conn_record](#automate_conn_record)
|
||||
- [standard_hostkey](#standard_hostkey)
|
||||
- [automate_host_record](#automate_host_record)
|
||||
- [Обслуживание удач и неудач](#обслуживание-удач-и-неудач)
|
||||
- [automate\_failure\_counter](#automate_failure_counter)
|
||||
- [automate\_failure\_counter\_reset](#automate_failure_counter_reset)
|
||||
- [automate_failure_counter](#automate_failure_counter)
|
||||
- [automate_failure_counter_reset](#automate_failure_counter_reset)
|
||||
- [Детекция удач и неудач](#детекция-удач-и-неудач)
|
||||
- [automate\_failure\_check](#automate_failure_check)
|
||||
- [standard\_success\_detector](#standard_success_detector)
|
||||
- [standard\_failure\_detector](#standard_failure_detector)
|
||||
- [automate_failure_check](#automate_failure_check)
|
||||
- [standard_success_detector](#standard_success_detector)
|
||||
- [standard_failure_detector](#standard_failure_detector)
|
||||
- [Оркестраторы](#оркестраторы)
|
||||
- [circular](#circular)
|
||||
- [repeater](#repeater)
|
||||
- [condition](#condition)
|
||||
- [per_instance_condition](#per_instance_condition)
|
||||
- [stopif](#stopif)
|
||||
- [iff функции](#iff-функции)
|
||||
- [cond\_true](#cond_true)
|
||||
- [cond\_false](#cond_false)
|
||||
- [cond\_random](#cond_random)
|
||||
- [cond\_payload\_str](#cond_payload_str)
|
||||
- [cond_true](#cond_true)
|
||||
- [cond_false](#cond_false)
|
||||
- [cond_random](#cond_random)
|
||||
- [cond_payload_str](#cond_payload_str)
|
||||
- [cond_tcp_has_ts](#cond_tcp_has_ts)
|
||||
- [cond_lua](#cond_lua)
|
||||
- [Вспомогательные программы](#вспомогательные-программы)
|
||||
- [ip2net](#ip2net)
|
||||
- [mdig](#mdig)
|
||||
@@ -243,16 +247,16 @@
|
||||
- [Система ведения листов](#система-ведения-листов)
|
||||
- [Стандартные файлы листов](#стандартные-файлы-листов)
|
||||
- [Скрипты ipset](#скрипты-ipset)
|
||||
- [clear\_lists.sh](#clear_listssh)
|
||||
- [create\_ipset.sh](#create_ipsetsh)
|
||||
- [get\_config.sh](#get_configsh)
|
||||
- [get\_user.sh](#get_usersh)
|
||||
- [get\_ipban.sh](#get_ipbansh)
|
||||
- [get\_exclude.sh](#get_excludesh)
|
||||
- [get\_antifilter\_\*.sh](#get_antifilter_sh)
|
||||
- [get\_antizapret\_domains.sh](#get_antizapret_domainssh)
|
||||
- [get\_refilter\_\*.sh](#get_refilter_sh)
|
||||
- [get\_reestr\_\*.sh](#get_reestr_sh)
|
||||
- [clear_lists.sh](#clear_listssh)
|
||||
- [create_ipset.sh](#create_ipsetsh)
|
||||
- [get_config.sh](#get_configsh)
|
||||
- [get_user.sh](#get_usersh)
|
||||
- [get_ipban.sh](#get_ipbansh)
|
||||
- [get_exclude.sh](#get_excludesh)
|
||||
- [get_antifilter_*.sh](#get_antifilter_sh)
|
||||
- [get_antizapret_domains.sh](#get_antizapret_domainssh)
|
||||
- [get_refilter_*.sh](#get_refilter_sh)
|
||||
- [get_reestr_*.sh](#get_reestr_sh)
|
||||
- [Система ipban](#система-ipban)
|
||||
- [Стартовые скрипты](#стартовые-скрипты)
|
||||
- [Интеграция с firewall](#интеграция-с-firewall)
|
||||
@@ -692,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
|
||||
@@ -725,9 +730,9 @@ MULTI-STRATEGY:
|
||||
--ipset-exclude=<filename> ; фильтр профиля : исключающий список ip адресов или подсетей из файла. может быть смешанным ipv4+ipv6.
|
||||
--ipset-exclude-ip=<ip_list> ; фильтр профиля : исключающий фиксированный список ip адресов или подсетей через запятую
|
||||
--hostlist=<filename> ; фильтр профиля : включающий список доменов из файла
|
||||
--hostlist-domains=<domain_list> ; фильтр профиля : включающий фиксированный список доменов из файла
|
||||
--hostlist-domains=<domain_list> ; фильтр профиля : включающий фиксированный список доменов через запятую
|
||||
--hostlist-exclude=<filename> ; фильтр профиля : исключающий список доменов из файла
|
||||
--hostlist-exclude-domains=<domain_list> ; фильтр профиля : исключающий фиксированный список доменов из файла
|
||||
--hostlist-exclude-domains=<domain_list> ; фильтр профиля : исключающий фиксированный список доменов через запятую
|
||||
--hostlist-auto=<filename> ; фильтр профиля : автоматически пополняемый по обратной связи включающий фильтр доменов
|
||||
--hostlist-auto-fail-threshold=<int> ; параметр автолиста : количество неудач подряд для занесения в лист. по умолчанию 3
|
||||
--hostlist-auto-fail-time=<int> ; параметр автолиста : максимальное время между неудачами без сброса счетчика. по умолчанию 60 секунд
|
||||
@@ -810,9 +815,11 @@ nfqws2 сигнатурно распознает типы пейлоадов о
|
||||
| tls | tcp | tls_client_hello<br>tls_server_hello |
|
||||
| xmpp | tcp | xmpp_stream<br>xmpp_starttls<br>xmpp_proceed<br>xmpp_features |
|
||||
| mtproto | tcp | mtproto_initial |
|
||||
| bt | tcp | bt_handshake |
|
||||
| quic | udp | quic_initial |
|
||||
| wireguard | udp | wireguard_initiation<br>wireguard_response<br>wireguard_cookie<br>wireguard_keepalive |
|
||||
| dht | udp | dht |
|
||||
| utp_bt | udp | utp_bt_handshake |
|
||||
| discord | udp | discord_ip_discovery |
|
||||
| stun | udp | stun |
|
||||
| dns | udp | dns_query<br>dns_response |
|
||||
@@ -1527,6 +1534,7 @@ ipv6 extension headers и tcp options представляются в форме
|
||||
| :------------ | :----- | :--------------------------------------------------------------- |
|
||||
| ip | table | заголовок ipv4 |
|
||||
| ip6 | table | заголовок ipv6 |
|
||||
| frag_off | number | смещение IP фрагмента. присутствует только в IP фрагментах. |
|
||||
| tcp | table | заголовок tcp |
|
||||
| udp | table | заголовок udp |
|
||||
| icmp | table | заголовок icmp |
|
||||
@@ -2137,6 +2145,32 @@ function stat(filename)
|
||||
|
||||
В случае неудачи возвращает 3 значения : nil, строка ошибки, код ошибки errno.
|
||||
|
||||
#### time
|
||||
|
||||
```
|
||||
function localtime(unixtime)
|
||||
function gmtime(unixtime)
|
||||
function timelocal(tm)
|
||||
function timegm(tm)
|
||||
```
|
||||
|
||||
Функции localtime и gmtime возвращают таблицу, аналогичную struct tm в C. timelocal и timegm - обратные функции.
|
||||
|
||||
| Поле | Тип | Описание |
|
||||
| :------- | :----- | :---------- |
|
||||
| sec* | number | секунды |
|
||||
| min* | number | минуты |
|
||||
| hour* | number | часы |
|
||||
| mon* | number | месяц, начиная с 0 |
|
||||
| mday* | number | день месяца |
|
||||
| year* | number | год - полный, не с 1900 года |
|
||||
| wday | number | день недели. 0 - воскресенье, 6 - суббота |
|
||||
| yday | number | номер дня в году, начиная с 0 |
|
||||
| isdst* | number | не 0, если включен переход на летнее/зимнее время |
|
||||
| zone | string | часовой пояс (timezone) |
|
||||
| str | string | отформатированная строка dd.mm.yyyy hh:mi:ss |
|
||||
|
||||
Поля, помеченные `*`, нужны для обратного перевода. Остальные не учитываются.
|
||||
|
||||
### Опции по работе с пакетами
|
||||
|
||||
@@ -2217,10 +2251,12 @@ function dissect(raw_ip)
|
||||
function reconstruct_dissect(dissect[, reconstruct_opts])
|
||||
```
|
||||
|
||||
Возвращает raw_ip. Все чексуммы считаются автоматически. L4 чексуммы портятся, если задан badsum в reconstruct_opts.
|
||||
Возвращает raw_ip. Все чексуммы считаются автоматически. L4 чексуммы портятся, если задан badsum в [reconstruct_opts](#standard-reconstruct).
|
||||
|
||||
Реконструкция диссектов с IP фрагментацией происходит особым образом - с участием как Lua, так и C кода.
|
||||
Lua код должен подготовить диссект полного пакета, подлежащего фрагментации, но заполнить некоторые поля такими, какими они должны быть во фрагменте.
|
||||
Реконструкция диссектов с IP фрагментацией происходит особым образом. Есть 2 варианта.
|
||||
|
||||
1. Если присутствует поле "frag_off", tcp/udp/icmp хедеры игнорируются, payload содержит raw ip payload. В таком виде приходят диссекты фрагментированных IP пакетов. nfqws2 не выполняет дефрагментацию на IP уровне. Но это очень настойчиво делают Linux системы - чтобы пришел фрагмент в nfqws2 надо сильно постараться, вставив в prerouting или output "notrack". Диссекты в таком виде могут быть реконструированы как есть. Но готовить их в Lua крайне неудобно, поскольку придется проходить через черную магию работы с бинарным представлением.
|
||||
2. Если поле "frag_off" отсутствует, реконструкция фрагментов выполняется из диссекта целого пакета с участием как Lua, так и C кода. Lua код должен подготовить диссект полного пакета, подлежащего фрагментации, но заполнить некоторые поля такими, какими они должны быть во фрагменте.
|
||||
|
||||
- ipv4 : ip.ip_len должен быть рассчитан таким, каким он должен быть во фрагменте.
|
||||
По ip.ip_len С код определяет размер фрагментированной части.
|
||||
@@ -2452,6 +2488,7 @@ function execution_plan(ctx)
|
||||
| range | table | эффективный диапазон [счетчиков](#внутрипрофильные-фильтры) `--in-range` или `--out-range` в зависимости от текущего направления |
|
||||
| payload | table | эффективный фильтр payload . таблица с индексами - названиями типа пейлоада |
|
||||
| payload_filter | string | эффективный фильтр payload . список названий пейлоадов через запятую (иное представление payload) |
|
||||
| arg | table | аргументы инстанса |
|
||||
|
||||
**range**
|
||||
|
||||
@@ -3672,7 +3709,8 @@ function cutoff_shim_check(desync)
|
||||
function apply_arg_prefix(desync)
|
||||
```
|
||||
|
||||
Выполняет подстановку значений аргументов из desync.arg, начинающихся с `%` и `#`.
|
||||
Выполняет подстановку значений аргументов из desync.arg, начинающихся с `%` и `#`, `\`.
|
||||
Функция ставит специальную метку в desync.arg , чтобы избежать двойного разименования. Повторные вызовы безопасны, но не обновляют desync.arg при изменении блобов.
|
||||
|
||||
### apply_execution_plan
|
||||
|
||||
@@ -3682,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
|
||||
@@ -3696,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
|
||||
|
||||
```
|
||||
@@ -3712,10 +3758,10 @@ function plan_instance_pop(desync)
|
||||
### plan_clear
|
||||
|
||||
```
|
||||
function plan_clear(desync)
|
||||
function plan_clear(desync, max)
|
||||
```
|
||||
|
||||
Очищает [execution plan](#execution_plan) в desync.plan - удаляет все `instance`.
|
||||
Очищает первые max инстансов, если max задан, либо весь [execution plan](#execution_plan) в desync.plan.
|
||||
|
||||
### orchestrate
|
||||
|
||||
@@ -3729,10 +3775,10 @@ function orchestrate(ctx, desync)
|
||||
### replay_execution_plan
|
||||
|
||||
```
|
||||
function replay_execution_plan(desync)
|
||||
function replay_execution_plan(desync, max)
|
||||
```
|
||||
|
||||
Выполняет весь [execution plan](#execution_plan) из desync.plan с учетом [instance cutoff](#instance_cutoff) и стандартных фильтров [payload](#внутрипрофильные-фильтры) и [range](#внутрипрофильные-фильтры).
|
||||
Выполняет max инстансов, если max задан, либо весь [execution plan](#execution_plan) из desync.plan с учетом [instance cutoff](#instance_cutoff) и стандартных фильтров [payload](#внутрипрофильные-фильтры) и [range](#внутрипрофильные-фильтры).
|
||||
|
||||
# Библиотека программ атаки на DPI zapret-antidpi.lua
|
||||
|
||||
@@ -4531,13 +4577,25 @@ function condition(ctx, desync)
|
||||
|
||||
- arg: iff - имя [функции условия](#iff-функции)
|
||||
- arg: neg - инвертировать значение iff. по умолчанию - false
|
||||
- arg: instances - сколько последующих инстансов выполнять условно. все, если не задано.
|
||||
|
||||
condition вызывает iff. если iff xor neg = true, выполняются все инстансы plan, иначе план очищается.
|
||||
|
||||
### per_instance_condition
|
||||
|
||||
```
|
||||
function per_instance_condition(ctx, desync)
|
||||
```
|
||||
|
||||
- arg: instances - сколько последующих инстансов выполнять условно. все, если не задано.
|
||||
|
||||
Все последующие инстансы вызываются только, если у них есть аргумент "cond", содержащий iff функцию, и она возвращает true. Аргумент "cond_neg" инвертирует ее значение.
|
||||
Имена аргументов не iff/neg, чтобы исключить конфликт с другими оркестраторами.
|
||||
|
||||
### stopif
|
||||
|
||||
```
|
||||
function condition(ctx, desync)
|
||||
function stopif(ctx, desync)
|
||||
```
|
||||
|
||||
- arg: iff - имя [функции условия](#iff-функции)
|
||||
@@ -4589,6 +4647,23 @@ function cond_payload_str(desync)
|
||||
Возвращает true, если в desync.dis.payload присутствует подстрока pattern.
|
||||
Это простейший сигнатурый детектор. Если C код не распознает нужный вам протокол, вы можете написать свой сигнатурный детектор и запускать последующие инстансы под оркестратором condition с вашим детектором в качестве iff.
|
||||
|
||||
#### cond_tcp_has_ts
|
||||
|
||||
```
|
||||
function cond_tcp_ts(desync)
|
||||
```
|
||||
|
||||
Возвращает true, если диссект является tcp и присутствует timestamp tcp option.
|
||||
|
||||
#### cond_lua
|
||||
|
||||
```
|
||||
function cond_lua(desync)
|
||||
```
|
||||
|
||||
Выполняет Lua код из аргумента "cond_code". Код возвращает значение условия через return. Возможна прямая адресация таблицы desync.
|
||||
desync.arg передаются с НЕ разименованными `%`, `#`, `\`, поскольку разименование может ссылаться на блобы, создаваемые предыдущими условно вызываемыми инстансами.
|
||||
|
||||
# Вспомогательные программы
|
||||
|
||||
## ip2net
|
||||
@@ -4734,7 +4809,7 @@ blockcheck2 способен определить подменяется ли DN
|
||||
|
||||
Ситуация нестабильности стратегий - явление частое. Бывает у провайдера балансировка нагрузки , и разные запросы проходят через разные DPI. То работает, то не работает. Стабильность стратегий тестируется за счет множественных повторений - попыток. Количество попыток задается в диалоге или через [shell переменные](#shell-переменные).
|
||||
|
||||
[Поддерживается](#shell-переменные) параллельный режим. В нем каждая попытка выполняется в отдельном дочернем процессе, а потом собираются результаты со всех процессов. Режим включается только через (переменную PARALLEL](#shell-переменные). Может значительно ускорить тестирование, но так же может и нарваться на rate limit - ситуацию, когда сервер вас ограничивает или банит из-за слишком частой долбежки.
|
||||
[Поддерживается](#shell-переменные) параллельный режим. В нем каждая попытка выполняется в отдельном дочернем процессе, а потом собираются результаты со всех процессов. Режим включается только через [переменную PARALLEL](#shell-переменные). Может значительно ускорить тестирование, но так же может и нарваться на rate limit - ситуацию, когда сервер вас ограничивает или банит из-за слишком частой долбежки.
|
||||
|
||||
### Уровни сканирования
|
||||
|
||||
@@ -5226,7 +5301,7 @@ filter_apply_hostlist_target()
|
||||
# $1 - имя переменной с опциями nfqws2
|
||||
```
|
||||
|
||||
Осуществляет замену маркеров `<HOSTLIST>` и `<HOSTLIST_AUTO>` в $1 зависимости от режима фильтрации [MODE_FILTER](#файл-config) и наличия файлов листов в ipset.
|
||||
Осуществляет замену маркеров `<HOSTLIST>` и `<HOSTLIST_NOAUTO>` в $1 зависимости от режима фильтрации [MODE_FILTER](#файл-config) и наличия файлов листов в ipset.
|
||||
|
||||
```
|
||||
standard_mode_daemons()
|
||||
@@ -5318,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
|
||||
|
||||
```
|
||||
@@ -5634,8 +5717,8 @@ WinDivert 2.2.2-A, который идет в поставке zapret.
|
||||
|
||||
## Windows Server
|
||||
|
||||
winws2 слинкован с wlanapi.dll, который по умолчанию не установлен в Windows Server.
|
||||
Для решения этой проблемы запустите power shell под администратором и выполните команду `Install-WindowsFeature -Name Wireless-Networking`.
|
||||
Для работы `--ssid-filter` необходимо установить поддержку беспроводных сетей.
|
||||
Запустите power shell под администратором и выполните команду `Install-WindowsFeature -Name Wireless-Networking`.
|
||||
После чего перезагрузите систему.
|
||||
|
||||
## Windows ARM64
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -54,7 +54,7 @@ standard rawsend :
|
||||
|
||||
standard payload :
|
||||
|
||||
* payload - comma separarated list of allowed payload types. if not present - allow non-empty known payloads.
|
||||
* payload - comma separated list of allowed payload types. if not present - allow non-empty known payloads.
|
||||
|
||||
standard ip_id :
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -107,10 +107,10 @@ end
|
||||
-- hostname is original hostname
|
||||
function is_dpi_redirect(hostname, location)
|
||||
local ds = dissect_url(location)
|
||||
if ds.domain then
|
||||
if ds and ds.domain then
|
||||
local sld1 = dissect_nld(hostname,2)
|
||||
local sld2 = dissect_nld(ds.domain,2)
|
||||
return sld2 and sld1~=sld2
|
||||
return sld2 and sld1~=sld2 and true or false
|
||||
end
|
||||
return false
|
||||
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)
|
||||
@@ -405,6 +405,34 @@ function cond_payload_str(desync)
|
||||
end
|
||||
return desync.dis.payload and string.find(desync.dis.payload,desync.arg.pattern,1,true)
|
||||
end
|
||||
-- true if dissect is tcp and timestamp tcp option is present
|
||||
function cond_tcp_has_ts(desync)
|
||||
return desync.dis.tcp and find_tcp_option(desync.dis.tcp.options, TCP_KIND_TS)
|
||||
end
|
||||
-- exec lua code in "code" arg and return it's result
|
||||
function cond_lua(desync)
|
||||
if not desync.arg.cond_code then
|
||||
error("cond_lua: no 'cond_code' parameter")
|
||||
end
|
||||
local fname = desync.func_instance.."_cond_cond_code"
|
||||
if not _G[fname] then
|
||||
local err
|
||||
_G[fname], err = load(desync.arg.cond_code, fname)
|
||||
if not _G[fname] then
|
||||
error(err)
|
||||
return
|
||||
end
|
||||
end
|
||||
-- allow dynamic cond_code to access desync
|
||||
_G.desync = desync
|
||||
local res, v = pcall(_G[fname])
|
||||
_G.desync = nil
|
||||
if not res then
|
||||
error(v);
|
||||
end
|
||||
return v
|
||||
end
|
||||
|
||||
-- check iff function available. error if not
|
||||
function require_iff(desync, name)
|
||||
if not desync.arg.iff then
|
||||
@@ -418,18 +446,57 @@ end
|
||||
-- for example, this can be used by custom protocol detectors
|
||||
-- arg: iff - condition function. takes desync as arg and returns bool. (cant use 'if' because of reserved word)
|
||||
-- arg: neg - invert condition function result
|
||||
-- arg: instances - how many instances execute conditionally. all if not defined
|
||||
-- test case : --lua-desync=condition:iff=cond_random --lua-desync=argdebug:testarg=1 --lua-desync=argdebug:testarg=2:morearg=xyz
|
||||
function condition(ctx, desync)
|
||||
require_iff(desync, "condition")
|
||||
orchestrate(ctx, desync)
|
||||
if logical_xor(_G[desync.arg.iff](desync), desync.arg.neg) then
|
||||
DLOG("condition: true")
|
||||
return replay_execution_plan(desync)
|
||||
else
|
||||
DLOG("condition: false")
|
||||
plan_clear(desync)
|
||||
plan_clear(desync, tonumber(desync.arg.instances))
|
||||
if #desync.plan>0 then
|
||||
DLOG("condition: executing remaining "..#desync.plan.." instance(s)")
|
||||
end
|
||||
end
|
||||
return replay_execution_plan(desync)
|
||||
end
|
||||
-- execute further desync instances.
|
||||
-- each instance may have "cond" and "cond_neg" args.
|
||||
-- "cond" - condition function. "neg" - invert condition function result
|
||||
-- arg: instances - how many instances execute conditionally. all if not defined
|
||||
function per_instance_condition(ctx, desync)
|
||||
orchestrate(ctx, desync)
|
||||
|
||||
local verdict = VERDICT_PASS
|
||||
local n = 0
|
||||
local max = tonumber(desync.arg.instances)
|
||||
while not max or n<max do
|
||||
local instance = plan_instance_pop(desync)
|
||||
if not instance then break end
|
||||
if instance.arg.cond then
|
||||
if type(_G[instance.arg.cond])~="function" then
|
||||
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_preapplied(desync, verdict, instance)
|
||||
else
|
||||
DLOG("per_instance_condition: condition not satisfied. skipping '"..instance.func_instance.."'")
|
||||
end
|
||||
else
|
||||
DLOG("per_instance_condition: no 'cond' arg in '"..instance.func_instance.."'. skipping")
|
||||
end
|
||||
n = n + 1
|
||||
end
|
||||
if #desync.plan>0 then
|
||||
DLOG("per_instance_condition: executing remaining "..#desync.plan.." instance(s) unconditionally")
|
||||
end
|
||||
return verdict_aggregate(verdict, replay_execution_plan(desync))
|
||||
end
|
||||
|
||||
-- clear execution plan if user provided 'iff' functions returns true
|
||||
-- can be used with other orchestrators to stop execution conditionally
|
||||
-- arg: iff - condition function. takes desync as arg and returns bool. (cant use 'if' because of reserved word)
|
||||
|
||||
@@ -29,8 +29,11 @@ function luaexec(ctx, desync)
|
||||
end
|
||||
-- allow dynamic code to access desync
|
||||
_G.desync = desync
|
||||
_G[fname]()
|
||||
local res, err = pcall(_G[fname])
|
||||
_G.desync = nil
|
||||
if not res then
|
||||
error(err);
|
||||
end
|
||||
end
|
||||
|
||||
-- basic desync function
|
||||
@@ -93,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
|
||||
@@ -146,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
|
||||
@@ -160,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
|
||||
@@ -170,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)
|
||||
@@ -189,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
|
||||
@@ -198,16 +203,28 @@ 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
|
||||
function plan_clear(desync)
|
||||
while table.remove(desync.plan) do end
|
||||
function plan_clear(desync, max)
|
||||
if max then
|
||||
local n=0
|
||||
while n<max and table.remove(desync.plan,1) do n=n+1 end
|
||||
else
|
||||
while table.remove(desync.plan) do end
|
||||
end
|
||||
end
|
||||
-- this approach allows nested orchestrators
|
||||
function orchestrate(ctx, desync)
|
||||
@@ -230,12 +247,17 @@ function desync_copy(desync)
|
||||
return dcopy
|
||||
end
|
||||
-- redo what whould be done without orchestration
|
||||
function replay_execution_plan(desync)
|
||||
function replay_execution_plan(desync, max)
|
||||
local verdict = VERDICT_PASS
|
||||
while true do
|
||||
local n=0
|
||||
while not max or n<max do
|
||||
local instance = plan_instance_pop(desync)
|
||||
if not instance then break end
|
||||
verdict = plan_instance_execute(desync, verdict, instance)
|
||||
n = n + 1
|
||||
end
|
||||
if max and n>=max then
|
||||
DLOG("replay_execution_plan: reached max instances limit "..max)
|
||||
end
|
||||
return verdict
|
||||
end
|
||||
@@ -322,24 +344,25 @@ end
|
||||
-- convert array a to packed string using 'packer' function. only numeric indexes starting from 1, order preserved
|
||||
function barray(a, packer)
|
||||
if a then
|
||||
local s=""
|
||||
local sa={}
|
||||
for i=1,#a do
|
||||
s = s .. packer(a[i])
|
||||
sa[i] = packer(a[i])
|
||||
end
|
||||
return s
|
||||
return table.concat(sa)
|
||||
end
|
||||
end
|
||||
-- convert table a to packed string using 'packer' function. any indexes, any order
|
||||
function btable(a, packer)
|
||||
if a then
|
||||
local s=""
|
||||
local sa={}
|
||||
local i=1
|
||||
for k,v in pairs(a) do
|
||||
s = s .. packer(v)
|
||||
sa[i] = packer(v)
|
||||
i=i+1
|
||||
end
|
||||
return s
|
||||
return table.concat(sa)
|
||||
end
|
||||
end
|
||||
|
||||
-- sequence comparision functions. they work only within 2G interval
|
||||
-- seq1>=seq2
|
||||
function seq_ge(seq1, seq2)
|
||||
@@ -419,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
|
||||
@@ -530,6 +553,7 @@ function blob(desync, name, def)
|
||||
error("blob '"..name.."' unavailable")
|
||||
end
|
||||
end
|
||||
blob = tostring(blob)
|
||||
end
|
||||
return blob
|
||||
end
|
||||
@@ -614,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
|
||||
@@ -626,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
|
||||
@@ -790,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
|
||||
@@ -857,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)
|
||||
@@ -872,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
|
||||
@@ -890,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)))
|
||||
@@ -909,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
|
||||
@@ -925,18 +968,18 @@ 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
|
||||
local bin
|
||||
if fooling_options.ip6_hopbyhop then
|
||||
bin = prepare_bin(fooling_options.ip6_hopbyhop,"\x00\x00\x00\x00\x00\x00")
|
||||
insert_ip6_exthdr(dis.ip6,nil,IPPROTO_HOPOPTS,bin)
|
||||
insert_ip6_exthdr(dis.ip6,1,IPPROTO_HOPOPTS,bin)
|
||||
end
|
||||
if fooling_options.ip6_hopbyhop2 then
|
||||
bin = prepare_bin(fooling_options.ip6_hopbyhop2,"\x00\x00\x00\x00\x00\x00")
|
||||
insert_ip6_exthdr(dis.ip6,nil,IPPROTO_HOPOPTS,bin)
|
||||
insert_ip6_exthdr(dis.ip6,1,IPPROTO_HOPOPTS,bin)
|
||||
end
|
||||
-- for possible unfragmentable part
|
||||
if fooling_options.ip6_destopt then
|
||||
@@ -1094,7 +1137,7 @@ end
|
||||
|
||||
-- option : ipfrag.ipfrag_disorder - send fragments from last to first
|
||||
function rawsend_dissect_ipfrag(dis, options)
|
||||
if options and options.ipfrag and options.ipfrag.ipfrag then
|
||||
if options and options.ipfrag and options.ipfrag.ipfrag and not dis.frag then
|
||||
local frag_func = options.ipfrag.ipfrag=="" and "ipfrag2" or options.ipfrag.ipfrag
|
||||
if type(_G[frag_func]) ~= "function" then
|
||||
error("rawsend_dissect_ipfrag: ipfrag function '"..tostring(frag_func).."' does not exist")
|
||||
@@ -1146,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
|
||||
@@ -1165,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
|
||||
@@ -1530,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
|
||||
@@ -1601,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
|
||||
@@ -1623,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)
|
||||
@@ -1641,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)
|
||||
@@ -1661,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)
|
||||
@@ -2110,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))
|
||||
|
||||
@@ -2149,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)
|
||||
@@ -2225,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
|
||||
|
||||
@@ -2433,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
|
||||
@@ -2448,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)
|
||||
@@ -2458,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)
|
||||
|
||||
@@ -82,13 +82,13 @@ end
|
||||
|
||||
-- test case :
|
||||
-- endpoint1:
|
||||
-- --filter-icmp=0,8,128,129 --filter-ipp=193,198,209,250 --filter-tcp=* --filter-udp=* --in-range=a --lua-desync=ippxor:xor=192:dataxor=0xABCD
|
||||
-- --filter-icmp=0,8,128,129 --filter-ipp=193,198,209,250 --filter-tcp=* --filter-udp=* --in-range=a --lua-desync=ippxor:ippxor=192:dataxor=0xABCD
|
||||
-- nft add rule inet ztest pre meta mark and 0x40000000 == 0 meta l4proto {193, 198, 209, 250} queue num 200 bypass
|
||||
-- nft add rule inet ztest post meta mark and 0x40000000 == 0 tcp dport "{5001}" queue num 200 bypass
|
||||
-- nft add rule inet ztest post meta mark and 0x40000000 == 0 udp dport "{5001}" queue num 200 bypass
|
||||
-- iperf -i 1 -c endpoint2
|
||||
-- endpoint2:
|
||||
-- --filter-icmp=0,8,128,129 --filter-ipp=193,198,209,250 --filter-tcp=* --filter-udp=* --in-range=a --lua-desync=ippxor:xor=192:dataxor=0xABCD --server
|
||||
-- --filter-icmp=0,8,128,129 --filter-ipp=193,198,209,250 --filter-tcp=* --filter-udp=* --in-range=a --lua-desync=ippxor:ippxor=192:dataxor=0xABCD --server
|
||||
-- nft add rule inet ztest pre meta mark and 0x40000000 == 0 meta l4proto {193, 198, 209, 250} queue num 200 bypass
|
||||
-- nft add rule inet ztest post meta mark and 0x40000000 == 0 tcp sport "{5001}" queue num 200 bypass
|
||||
-- nft add rule inet ztest post meta mark and 0x40000000 == 0 udp sport "{5001}" queue num 200 bypass
|
||||
@@ -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
|
||||
|
||||
@@ -14,7 +14,7 @@ end
|
||||
|
||||
function test_all(...)
|
||||
test_run({
|
||||
test_crypto, test_bin, test_gzip, test_ipstr, test_dissect, test_csum, test_resolve,
|
||||
test_crypto, test_bin, test_time, test_gzip, test_ipstr, test_dissect, test_csum, test_resolve,
|
||||
test_get_source_ip, test_ifaddrs, test_rawsend},...)
|
||||
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)
|
||||
@@ -415,6 +413,42 @@ function test_bin(...)
|
||||
test_run({test_ub, test_bit, test_swap, test_ux},...)
|
||||
end
|
||||
|
||||
function test_time(...)
|
||||
print("* time")
|
||||
|
||||
local unixtime=os.time()
|
||||
local tm = localtime(unixtime);
|
||||
local t
|
||||
print()
|
||||
print("now: "..tm.str.." "..tm.zone.." = "..unixtime)
|
||||
local tm = gmtime(unixtime);
|
||||
print("gmt: "..tm.str.." "..tm.zone.." = "..unixtime)
|
||||
print()
|
||||
for i=1,20 do
|
||||
unixtime = math.random(0,0x7FFFFFFF);
|
||||
tm = localtime(unixtime);
|
||||
t = timelocal(tm)
|
||||
print("timelocal: "..tm.str.." "..tm.zone.." = "..t)
|
||||
print( t==unixtime and "LOCALTIME OK" or "LOCALTIME FAILED" )
|
||||
test_assert(t==unixtime)
|
||||
|
||||
unixtime = math.random(0,0x7FFFFFFF);
|
||||
tm = gmtime(unixtime);
|
||||
t = timegm(tm)
|
||||
print("timegm: "..tm.str.." "..tm.zone.." = "..t)
|
||||
print( t==unixtime and "GMTIME OK" or "GMTIME FAILED" )
|
||||
test_assert(t==unixtime)
|
||||
end
|
||||
unixtime = math.random(0x80000000,0xFFFFFFFF);
|
||||
tm = gmtime(unixtime)
|
||||
t = timegm(tm)
|
||||
print( t==unixtime and "TIME 0x80000000..0xFFFFFFFF OK" or "TIME 0x80000000..0xFFFFFFFF FAILED : "..unixtime.." != "..t.." ("..tm.str..")" )
|
||||
unixtime = math.random(0x100000000,0x200000000);
|
||||
tm = gmtime(unixtime)
|
||||
t = timegm(tm)
|
||||
print( t==unixtime and "TIME 64 OK" or "TIME 64 FAILED : "..unixtime.." != "..t.." ("..tm.str..")" )
|
||||
end
|
||||
|
||||
function test_gzip()
|
||||
print("* gzip")
|
||||
|
||||
@@ -473,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))
|
||||
@@ -577,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)
|
||||
@@ -695,6 +729,8 @@ function test_csum()
|
||||
|
||||
raw = reconstruct_dissect({ip=ip, tcp=tcp, payload=payload})
|
||||
dis1 = dissect(raw)
|
||||
ip.ip_len = IP_BASE_LEN + #ip.options + #tcpb + #payload
|
||||
ip4b = reconstruct_iphdr(ip)
|
||||
tcpb = csum_tcp_fix(ip4b,tcpb,payload)
|
||||
dis2 = dissect(ip4b..tcpb..payload)
|
||||
print( dis1.tcp.th_sum==dis2.tcp.th_sum and "TCP+IP4 CSUM OK" or "TCP+IP4 CSUM FAILED" )
|
||||
@@ -736,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) ..
|
||||
@@ -749,13 +780,19 @@ 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)
|
||||
dis2 = dissect(ip4b..udpb..payload)
|
||||
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)
|
||||
@@ -911,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
|
||||
@@ -959,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
|
||||
@@ -1045,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
|
||||
|
||||
@@ -220,7 +220,7 @@ static void *t_resolver(void *arg)
|
||||
{
|
||||
if ((family == AF_INET && (glob.family & FAMILY4)) || (family == AF_INET6 && (glob.family & FAMILY6)))
|
||||
{
|
||||
unsigned int mask;
|
||||
unsigned int mask=0;
|
||||
bool mask_needed = false;
|
||||
if (s_mask)
|
||||
{
|
||||
|
||||
@@ -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,17 +1,26 @@
|
||||
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
|
||||
LIBS_BSD = -lz -lm
|
||||
LIBS_CYGWIN = -lz -Lwindows/windivert -Iwindows -lwlanapi -lole32 -loleaut32 -liphlpapi -lntdll
|
||||
LIBS_CYGWIN = -lz -Lwindows/windivert -Iwindows -lole32 -loleaut32 -liphlpapi -lntdll
|
||||
LIBS_CYGWIN32 = -lwindivert32
|
||||
LIBS_CYGWIN64 = -lwindivert64
|
||||
RES_CYGWIN32 = windows/res/winws_res32.o
|
||||
@@ -26,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))
|
||||
|
||||
@@ -133,21 +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:
|
||||
|
||||
@@ -19,10 +19,10 @@ struct icmp46
|
||||
uint16_t icmp_cksum;
|
||||
union
|
||||
{
|
||||
uint32_t icmp_data32;
|
||||
uint16_t icmp_data16[2];
|
||||
uint8_t icmp_data8[4];
|
||||
};
|
||||
uint32_t data32;
|
||||
uint16_t data16[2];
|
||||
uint8_t data8[4];
|
||||
} data;
|
||||
};
|
||||
|
||||
uint16_t csum_tcpudp_magic(uint32_t saddr, uint32_t daddr, size_t len, uint8_t proto, uint16_t sum);
|
||||
|
||||
@@ -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,13 +349,13 @@ 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) {
|
||||
taddr2str(t->conn.l3proto, &t->conn.src, sa1, sizeof(sa1));
|
||||
taddr2str(t->conn.l3proto, &t->conn.dst, sa2, sizeof(sa2));
|
||||
printf("%s [%s]:%u => [%s]:%u : %s : t0=%llu last=t0+%llu now=last+%llu client=d%llu/n%llu/b%llu server=d%llu/n%llu/b%lld ",
|
||||
printf("%s [%s]:%u => [%s]:%u : %s : t0=%llu last=t0+%llu now=last+%llu client=d%llu/n%llu/b%llu server=d%llu/n%llu/b%llu ",
|
||||
proto_name(t->conn.l4proto),
|
||||
sa1, t->conn.sport, sa2, t->conn.dport,
|
||||
t->conn.l4proto == IPPROTO_TCP ? connstate_s[t->track.pos.state] : "-",
|
||||
@@ -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;
|
||||
|
||||
@@ -391,7 +391,9 @@ int gcm_finish(gcm_context *ctx, // pointer to user-provided GCM context
|
||||
uint64_t orig_add_len = ctx->add_len * 8;
|
||||
size_t i;
|
||||
|
||||
if (tag_len != 0) memcpy(tag, ctx->base_ectr, tag_len);
|
||||
if (tag_len>16) return -1;
|
||||
|
||||
if (tag_len) memcpy(tag, ctx->base_ectr, tag_len);
|
||||
|
||||
if (orig_len || orig_add_len) {
|
||||
memset(work_buf, 0x00, 16);
|
||||
@@ -443,10 +445,12 @@ 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...
|
||||
*/
|
||||
gcm_start(ctx, mode, iv, iv_len, add, add_len);
|
||||
gcm_update(ctx, length, input, output);
|
||||
gcm_finish(ctx, tag, tag_len);
|
||||
return(0);
|
||||
if (tag_len>16) return -1;
|
||||
|
||||
int ret;
|
||||
if ((ret=gcm_start(ctx, mode, iv, iv_len, add, add_len))) return ret;
|
||||
if ((ret=gcm_update(ctx, length, input, output))) return ret;
|
||||
return gcm_finish(ctx, tag, tag_len);
|
||||
}
|
||||
|
||||
|
||||
@@ -477,23 +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 (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;
|
||||
|
||||
@@ -64,12 +64,12 @@
|
||||
* Add "length" to the length.
|
||||
* Set Corrupted when overflow has occurred.
|
||||
*/
|
||||
static uint32_t addTemp;
|
||||
#define SHA224_256AddLength(context, length) \
|
||||
(addTemp = (context)->Length_Low, (context)->Corrupted = \
|
||||
(((context)->Length_Low += (length)) < addTemp) && \
|
||||
(++(context)->Length_High == 0) ? shaInputTooLong : \
|
||||
(context)->Corrupted )
|
||||
static int SHA224_256AddLength(SHA256Context *context, uint32_t length)
|
||||
{
|
||||
uint32_t addTemp = context->Length_Low;
|
||||
if (((context->Length_Low += length) < addTemp) && (++(context)->Length_High == 0)) context->Corrupted = shaInputTooLong;
|
||||
return context->Corrupted;
|
||||
}
|
||||
|
||||
/* Local Function Prototypes */
|
||||
static int SHA224_256Reset(SHA256Context *context, uint32_t *H0);
|
||||
|
||||
402
nfq2/darkmagic.c
402
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);
|
||||
}
|
||||
@@ -102,8 +102,8 @@ bool tcp_syn_segment(const struct tcphdr *tcphdr)
|
||||
|
||||
void extract_ports(const struct tcphdr *tcphdr, const struct udphdr *udphdr,uint8_t *proto, uint16_t *sport, uint16_t *dport)
|
||||
{
|
||||
if (sport) *sport = htons(tcphdr ? tcphdr->th_sport : udphdr ? udphdr->uh_sport : 0);
|
||||
if (dport) *dport = htons(tcphdr ? tcphdr->th_dport : udphdr ? udphdr->uh_dport : 0);
|
||||
if (sport) *sport = ntohs(tcphdr ? tcphdr->th_sport : udphdr ? udphdr->uh_sport : 0);
|
||||
if (dport) *dport = ntohs(tcphdr ? tcphdr->th_dport : udphdr ? udphdr->uh_dport : 0);
|
||||
if (proto) *proto = tcphdr ? IPPROTO_TCP : udphdr ? IPPROTO_UDP : IPPROTO_NONE;
|
||||
}
|
||||
|
||||
@@ -178,8 +178,8 @@ void extract_endpoints(const struct ip *ip,const struct ip6_hdr *ip6hdr,const st
|
||||
}
|
||||
else
|
||||
{
|
||||
memset(src,0,sizeof(*src));
|
||||
memset(dst,0,sizeof(*dst));
|
||||
if (src) memset(src,0,sizeof(*src));
|
||||
if (dst) memset(dst,0,sizeof(*dst));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
@@ -358,9 +358,9 @@ void str_icmphdr(char *s, size_t s_len, bool v6, const struct icmp46 *icmp)
|
||||
char stype[32];
|
||||
str_icmp_type_name(stype,sizeof(stype),v6,icmp->icmp_type);
|
||||
if (icmp->icmp_type==ICMP_ECHO || icmp->icmp_type==ICMP_ECHOREPLY || icmp->icmp_type==ICMP6_ECHO_REQUEST || icmp->icmp_type==ICMP6_ECHO_REPLY)
|
||||
snprintf(s,s_len,"icmp_type=%s icmp_code=%u id=0x%04X seq=%u",stype,icmp->icmp_code,ntohs(icmp->icmp_data16[0]),ntohs(icmp->icmp_data16[1]));
|
||||
snprintf(s,s_len,"icmp_type=%s icmp_code=%u id=0x%04X seq=%u",stype,icmp->icmp_code,ntohs(icmp->data.data16[0]),ntohs(icmp->data.data16[1]));
|
||||
else
|
||||
snprintf(s,s_len,"icmp_type=%s icmp_code=%u data=0x%08X",stype,icmp->icmp_code,ntohl(icmp->icmp_data32));
|
||||
snprintf(s,s_len,"icmp_type=%s icmp_code=%u data=0x%08X",stype,icmp->icmp_code,ntohl(icmp->data.data32));
|
||||
}
|
||||
void print_icmphdr(const struct icmp46 *icmp, bool v6)
|
||||
{
|
||||
@@ -378,10 +378,16 @@ bool proto_check_ipv4(const uint8_t *data, size_t len)
|
||||
uint8_t off = ((struct ip*)data)->ip_hl << 2;
|
||||
return off>=sizeof(struct ip) && len>=off;
|
||||
}
|
||||
bool proto_check_ipv4_payload(const uint8_t *data, size_t len)
|
||||
{
|
||||
return len >= ntohs(((struct ip*)data)->ip_len);
|
||||
}
|
||||
// move to transport protocol
|
||||
void proto_skip_ipv4(const uint8_t **data, size_t *len)
|
||||
void proto_skip_ipv4(const uint8_t **data, size_t *len, bool *frag, uint16_t *frag_off)
|
||||
{
|
||||
uint8_t off = ((struct ip*)*data)->ip_hl << 2;
|
||||
if (frag_off) *frag_off = (ntohs(((struct ip*)*data)->ip_off) & IP_OFFMASK) << 3;
|
||||
if (frag) *frag = ntohs(((struct ip*)*data)->ip_off) & (IP_OFFMASK|IP_MF);
|
||||
*data += off;
|
||||
*len -= off;
|
||||
}
|
||||
@@ -430,21 +436,25 @@ bool proto_check_ipv6_payload(const uint8_t *data, size_t len)
|
||||
}
|
||||
// move to transport protocol
|
||||
// proto_type = 0 => error
|
||||
void proto_skip_ipv6(const uint8_t **data, size_t *len, uint8_t *proto_type)
|
||||
void proto_skip_ipv6(const uint8_t **data, size_t *len, uint8_t *proto_type, bool *frag, uint16_t *frag_off)
|
||||
{
|
||||
size_t hdrlen;
|
||||
uint8_t HeaderType;
|
||||
uint16_t plen;
|
||||
struct ip6_hdr *ip6 = (struct ip6_hdr*)*data;
|
||||
uint16_t plen;
|
||||
uint16_t fr_off=0;
|
||||
bool fr=false;
|
||||
uint8_t HeaderType;
|
||||
|
||||
if (proto_type) *proto_type = 0; // put error in advance
|
||||
if (frag) *frag = false;
|
||||
if (frag_off) *frag_off = 0;
|
||||
|
||||
HeaderType = ip6->ip6_nxt;
|
||||
if (proto_type) *proto_type = HeaderType;
|
||||
plen = ntohs(ip6->ip6_ctlun.ip6_un1.ip6_un1_plen);
|
||||
*data += sizeof(struct ip6_hdr); *len -= sizeof(struct ip6_hdr); // skip ipv6 base header
|
||||
if (plen < *len) *len = plen;
|
||||
while (*len) // need at least one byte for NextHeader field
|
||||
while (*len && !(fr && fr_off)) // need at least one byte for NextHeader field. stop after fragment header if not first fragment
|
||||
{
|
||||
switch (HeaderType)
|
||||
{
|
||||
@@ -459,6 +469,11 @@ void proto_skip_ipv6(const uint8_t **data, size_t *len, uint8_t *proto_type)
|
||||
break;
|
||||
case IPPROTO_FRAGMENT: // fragment. length fixed to 8, hdrlen field defined as reserved
|
||||
hdrlen = 8;
|
||||
if (*len < hdrlen) return; // 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);
|
||||
if (frag_off) *frag_off = fr_off;
|
||||
if (frag) *frag = fr;
|
||||
break;
|
||||
case IPPROTO_AH:
|
||||
// special case. length in ah header is in 32-bit words minus 2
|
||||
@@ -484,16 +499,18 @@ void proto_skip_ipv6(const uint8_t **data, size_t *len, uint8_t *proto_type)
|
||||
uint8_t *proto_find_ip6_exthdr(struct ip6_hdr *ip6, size_t len, uint8_t proto)
|
||||
{
|
||||
size_t hdrlen;
|
||||
uint8_t HeaderType, last_proto, *data;
|
||||
uint16_t plen;
|
||||
uint8_t HeaderType, last_proto, *data;
|
||||
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);
|
||||
len -= sizeof(struct ip6_hdr);
|
||||
if (plen < len) len = plen;
|
||||
while (len) // need at least one byte for NextHeader field
|
||||
while (len && !(fr && fr_off)) // need at least one byte for NextHeader field. stop after fragment header if not first fragment
|
||||
{
|
||||
if (last_proto==proto) return data; // found
|
||||
switch (last_proto)
|
||||
@@ -504,15 +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 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:
|
||||
@@ -520,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;
|
||||
}
|
||||
@@ -537,19 +557,25 @@ void proto_dissect_l3l4(const uint8_t *data, size_t len, struct dissect *dis, bo
|
||||
dis->data_pkt = data;
|
||||
dis->len_pkt = len;
|
||||
|
||||
if (proto_check_ipv4(data, 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;
|
||||
proto_skip_ipv4(&data, &len);
|
||||
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;
|
||||
}
|
||||
else if (proto_check_ipv6(data, len) && (no_payload_check || proto_check_ipv6_payload(data, len)))
|
||||
{
|
||||
dis->ip6 = (const struct ip6_hdr *) data;
|
||||
p = data;
|
||||
proto_skip_ipv6(&data, &len, &dis->proto);
|
||||
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;
|
||||
}
|
||||
else
|
||||
@@ -558,31 +584,31 @@ void proto_dissect_l3l4(const uint8_t *data, size_t len, struct dissect *dis, bo
|
||||
}
|
||||
|
||||
dis->transport_len = len;
|
||||
dis->len_l4 = 0;
|
||||
|
||||
if (dis->proto==IPPROTO_TCP && proto_check_tcp(data, len))
|
||||
if (!dis->frag)
|
||||
{
|
||||
dis->tcp = (const struct tcphdr *) data;
|
||||
p = data;
|
||||
proto_skip_tcp(&data, &len);
|
||||
dis->len_l4 = data-p;
|
||||
}
|
||||
else if (dis->proto==IPPROTO_UDP && proto_check_udp(data, len) && (no_payload_check || proto_check_udp_payload(data, len)))
|
||||
{
|
||||
dis->udp = (const struct udphdr *) data;
|
||||
p = data;
|
||||
proto_skip_udp(&data, &len);
|
||||
dis->len_l4 = data-p;
|
||||
}
|
||||
else if ((dis->proto==IPPROTO_ICMP || dis->proto==IPPROTO_ICMPV6) && proto_check_icmp(data, len))
|
||||
{
|
||||
dis->icmp = (const struct icmp46 *) data;
|
||||
p = data;
|
||||
proto_skip_icmp(&data, &len);
|
||||
dis->len_l4 = data-p;
|
||||
}
|
||||
else
|
||||
{
|
||||
dis->len_l4 = 0;
|
||||
if (dis->proto==IPPROTO_TCP && proto_check_tcp(data, len))
|
||||
{
|
||||
dis->tcp = (const struct tcphdr *) data;
|
||||
p = data;
|
||||
proto_skip_tcp(&data, &len);
|
||||
dis->len_l4 = data-p;
|
||||
}
|
||||
else if (dis->proto==IPPROTO_UDP && proto_check_udp(data, len) && (no_payload_check || proto_check_udp_payload(data, len)))
|
||||
{
|
||||
dis->udp = (const struct udphdr *) data;
|
||||
p = data;
|
||||
proto_skip_udp(&data, &len);
|
||||
dis->len_l4 = data-p;
|
||||
}
|
||||
else if ((dis->proto==IPPROTO_ICMP || dis->proto==IPPROTO_ICMPV6) && proto_check_icmp(data, len))
|
||||
{
|
||||
dis->icmp = (const struct icmp46 *) data;
|
||||
p = data;
|
||||
proto_skip_icmp(&data, &len);
|
||||
dis->len_l4 = data-p;
|
||||
}
|
||||
}
|
||||
|
||||
dis->data_payload = data;
|
||||
@@ -777,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);
|
||||
}
|
||||
}
|
||||
@@ -902,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()
|
||||
@@ -1148,6 +1192,42 @@ static bool AdapterID2Name(const GUID *guid,char *name,DWORD name_len)
|
||||
return bRet;
|
||||
}
|
||||
|
||||
|
||||
typedef DWORD (WINAPI *t_WlanOpenHandle)(
|
||||
DWORD dwClientVersion,
|
||||
PVOID pReserved,
|
||||
PDWORD pdwNegotiatedVersion,
|
||||
PHANDLE phClientHandle
|
||||
);
|
||||
typedef DWORD (WINAPI *t_WlanCloseHandle)(
|
||||
HANDLE hClientHandle,
|
||||
PVOID pReserved
|
||||
);
|
||||
typedef DWORD (WINAPI *t_WlanEnumInterfaces)(
|
||||
HANDLE hClientHandle,
|
||||
PVOID pReserved,
|
||||
PWLAN_INTERFACE_INFO_LIST *ppInterfaceList
|
||||
);
|
||||
typedef DWORD (WINAPI *t_WlanQueryInterface)(
|
||||
HANDLE hClientHandle,
|
||||
const GUID *pInterfaceGuid,
|
||||
WLAN_INTF_OPCODE OpCode,
|
||||
PVOID pReserved,
|
||||
PDWORD pdwDataSize,
|
||||
PVOID *ppData,
|
||||
PWLAN_OPCODE_VALUE_TYPE pWlanOpcodeValueType
|
||||
);
|
||||
typedef DWORD (WINAPI *t_WlanFreeMemory)(
|
||||
PVOID pMemory
|
||||
);
|
||||
|
||||
t_WlanOpenHandle f_WlanOpenHandle = NULL;
|
||||
t_WlanCloseHandle f_WlanCloseHandle = NULL;
|
||||
t_WlanEnumInterfaces f_WlanEnumInterfaces = NULL;
|
||||
t_WlanQueryInterface f_WlanQueryInterface = NULL;
|
||||
t_WlanFreeMemory f_WlanFreeMemory = NULL;
|
||||
HMODULE hdll_wlanapi = NULL;
|
||||
|
||||
bool win_dark_init(const struct str_list_head *ssid_filter, const struct str_list_head *nlm_filter)
|
||||
{
|
||||
win_dark_deinit();
|
||||
@@ -1161,12 +1241,38 @@ bool win_dark_init(const struct str_list_head *ssid_filter, const struct str_lis
|
||||
if (FAILED(w_win32_error = CoCreateInstance(&CLSID_NetworkListManager, NULL, CLSCTX_ALL, &IID_INetworkListManager, (LPVOID*)&pNetworkListManager)))
|
||||
{
|
||||
CoUninitialize();
|
||||
DLOG_ERR("could not create CLSID_NetworkListManager. win32 error %u\n", w_win32_error);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
if (ssid_filter)
|
||||
{
|
||||
// dont load any crap from current dir
|
||||
hdll_wlanapi = LoadLibraryExW(L"wlanapi.dll",NULL,LOAD_LIBRARY_SEARCH_SYSTEM32);
|
||||
if (!hdll_wlanapi)
|
||||
{
|
||||
w_win32_error = GetLastError();
|
||||
DLOG_ERR("could not load wlanapi.dll. win32 error %u\n", w_win32_error);
|
||||
win_dark_deinit();
|
||||
return false;
|
||||
}
|
||||
f_WlanOpenHandle = (t_WlanOpenHandle)GetProcAddress(hdll_wlanapi,"WlanOpenHandle");
|
||||
f_WlanCloseHandle = (t_WlanCloseHandle)GetProcAddress(hdll_wlanapi,"WlanCloseHandle");
|
||||
f_WlanEnumInterfaces = (t_WlanEnumInterfaces)GetProcAddress(hdll_wlanapi,"WlanEnumInterfaces");
|
||||
f_WlanQueryInterface = (t_WlanQueryInterface)GetProcAddress(hdll_wlanapi,"WlanQueryInterface");
|
||||
f_WlanFreeMemory = (t_WlanFreeMemory)GetProcAddress(hdll_wlanapi,"WlanFreeMemory");
|
||||
if (!f_WlanOpenHandle || !f_WlanCloseHandle || !f_WlanEnumInterfaces || !f_WlanQueryInterface || !f_WlanFreeMemory)
|
||||
{
|
||||
w_win32_error = GetLastError();
|
||||
DLOG_ERR("could not import all required functions from wlanapi.dll\n");
|
||||
win_dark_deinit();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
nlm_filter_net = nlm_filter;
|
||||
wlan_filter_ssid = ssid_filter;
|
||||
return true;
|
||||
@@ -1180,6 +1286,16 @@ void win_dark_deinit(void)
|
||||
}
|
||||
if (nlm_filter_net) CoUninitialize();
|
||||
wlan_filter_ssid = nlm_filter_net = NULL;
|
||||
if (hdll_wlanapi)
|
||||
{
|
||||
FreeLibrary(hdll_wlanapi);
|
||||
hdll_wlanapi = NULL;
|
||||
f_WlanOpenHandle = NULL;
|
||||
f_WlanCloseHandle = NULL;
|
||||
f_WlanEnumInterfaces = NULL;
|
||||
f_WlanQueryInterface = NULL;
|
||||
f_WlanFreeMemory = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1361,16 +1477,16 @@ static bool wlan_filter_match(const struct str_list_head *ssid_list)
|
||||
return true;
|
||||
}
|
||||
|
||||
w_win32_error = WlanOpenHandle(2, NULL, &dwCurVersion, &hClient);
|
||||
w_win32_error = f_WlanOpenHandle(2, NULL, &dwCurVersion, &hClient);
|
||||
if (w_win32_error != ERROR_SUCCESS) goto fail;
|
||||
w_win32_error = WlanEnumInterfaces(hClient, NULL, &pIfList);
|
||||
w_win32_error = f_WlanEnumInterfaces(hClient, NULL, &pIfList);
|
||||
if (w_win32_error != ERROR_SUCCESS) goto fail;
|
||||
for (k = 0; k < pIfList->dwNumberOfItems; k++)
|
||||
{
|
||||
pIfInfo = pIfList->InterfaceInfo + k;
|
||||
if (pIfInfo->isState == wlan_interface_state_connected)
|
||||
{
|
||||
w_win32_error = WlanQueryInterface(hClient,
|
||||
w_win32_error = f_WlanQueryInterface(hClient,
|
||||
&pIfInfo->InterfaceGuid,
|
||||
wlan_intf_opcode_current_connection,
|
||||
NULL,
|
||||
@@ -1386,20 +1502,20 @@ static bool wlan_filter_match(const struct str_list_head *ssid_list)
|
||||
len = strlen(ssid->str);
|
||||
if (len==pConnectInfo->wlanAssociationAttributes.dot11Ssid.uSSIDLength && !memcmp(ssid->str,pConnectInfo->wlanAssociationAttributes.dot11Ssid.ucSSID,len))
|
||||
{
|
||||
WlanFreeMemory(pConnectInfo);
|
||||
f_WlanFreeMemory(pConnectInfo);
|
||||
goto found;
|
||||
}
|
||||
}
|
||||
|
||||
WlanFreeMemory(pConnectInfo);
|
||||
f_WlanFreeMemory(pConnectInfo);
|
||||
}
|
||||
}
|
||||
w_win32_error = 0;
|
||||
fail:
|
||||
bRes = false;
|
||||
ex:
|
||||
if (pIfList) WlanFreeMemory(pIfList);
|
||||
if (hClient) WlanCloseHandle(hClient, 0);
|
||||
if (pIfList) f_WlanFreeMemory(pIfList);
|
||||
if (hClient) f_WlanCloseHandle(hClient, 0);
|
||||
return bRes;
|
||||
found:
|
||||
w_win32_error = 0;
|
||||
@@ -1465,7 +1581,6 @@ void rawsend_cleanup(void)
|
||||
{
|
||||
if (w_filter)
|
||||
{
|
||||
CancelIoEx(w_filter,&ovl);
|
||||
WinDivertClose(w_filter);
|
||||
w_filter=NULL;
|
||||
}
|
||||
@@ -1493,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)
|
||||
@@ -1677,6 +1792,7 @@ static int rawsend_sendto_divert(sa_family_t family, int sock, const void *buf,
|
||||
{
|
||||
struct sockaddr_storage sa;
|
||||
socklen_t slen;
|
||||
ssize_t wr;
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
// since FreeBSD 14 it requires hardcoded ipv4 values, although can also send ipv6 frames
|
||||
@@ -1698,7 +1814,16 @@ static int rawsend_sendto_divert(sa_family_t family, int sock, const void *buf,
|
||||
#endif
|
||||
memset(&sa,0,slen);
|
||||
sa.ss_family = family;
|
||||
return sendto(sock, buf, len, 0, (struct sockaddr*)&sa, slen);
|
||||
while ((wr=sendto(sock, buf, len, 0, (struct sockaddr*)&sa, slen))<0 && errno==EINTR);
|
||||
if (wr<0)
|
||||
{
|
||||
char s[64];
|
||||
snprintf(s,sizeof(s),"rawsend_sendto_divert: sendto (%zu)",len);
|
||||
DLOG_PERROR(s);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return wr;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1779,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)
|
||||
{
|
||||
@@ -1830,47 +1956,32 @@ bool rawsend(const struct sockaddr* dst,uint32_t fwmark,const char *ifout,const
|
||||
#else
|
||||
|
||||
#ifdef __linux__
|
||||
struct sockaddr_storage sa_src;
|
||||
switch(dst->sa_family)
|
||||
{
|
||||
case AF_INET:
|
||||
if (!b_bind_fix4) goto nofix;
|
||||
extract_endpoints(data,NULL,NULL,NULL, &sa_src, NULL);
|
||||
break;
|
||||
case AF_INET6:
|
||||
if (!b_bind_fix6) goto nofix;
|
||||
extract_endpoints(NULL,data,NULL,NULL, &sa_src, NULL);
|
||||
break;
|
||||
default:
|
||||
return false; // should not happen
|
||||
}
|
||||
//printf("family %u dev %s bind : ", dst->sa_family, ifout); print_sockaddr((struct sockaddr *)&sa_src); printf("\n");
|
||||
|
||||
// force outgoing interface for raw packets. linux may choose it wrong if ip rules exist
|
||||
if (setsockopt(sock, SOL_SOCKET, SO_BINDTODEVICE, ifout, ifout ? strlen(ifout)+1 : 0) == -1)
|
||||
{
|
||||
DLOG_PERROR("rawsend: setsockopt(SO_BINDTODEVICE)");
|
||||
return false;
|
||||
}
|
||||
if (bind(sock, (const struct sockaddr*)&sa_src, dst->sa_family==AF_INET ? sizeof(struct sockaddr_in) : sizeof(struct sockaddr_in6)))
|
||||
{
|
||||
DLOG_PERROR("rawsend: bind (ignoring)");
|
||||
// do not fail. this can happen regardless of IP_FREEBIND
|
||||
// rebind to any address
|
||||
memset(&sa_src,0,sizeof(sa_src));
|
||||
sa_src.ss_family = dst->sa_family;
|
||||
if (bind(sock, (const struct sockaddr*)&sa_src, dst->sa_family==AF_INET ? sizeof(struct sockaddr_in) : sizeof(struct sockaddr_in6)))
|
||||
{
|
||||
DLOG_PERROR("rawsend: bind to any");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
nofix:
|
||||
#endif
|
||||
|
||||
// normal raw socket sendto
|
||||
bytes = sendto(sock, data, len, 0, (struct sockaddr*)&dst2, salen);
|
||||
if (bytes==-1)
|
||||
while ((bytes = sendto(sock, data, len, 0, (struct sockaddr*)&dst2, salen))<0 && errno==EINTR);
|
||||
if (bytes<0)
|
||||
{
|
||||
char s[40];
|
||||
char s[64];
|
||||
snprintf(s,sizeof(s),"rawsend: sendto (%zu)",len);
|
||||
DLOG_PERROR(s);
|
||||
return false;
|
||||
@@ -1988,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:
|
||||
@@ -1999,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)
|
||||
@@ -2050,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;
|
||||
}
|
||||
@@ -2134,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;
|
||||
@@ -2347,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)
|
||||
|
||||
@@ -174,10 +174,11 @@ void str_udphdr(char *s, size_t s_len, const struct udphdr *udphdr);
|
||||
void str_icmphdr(char *s, size_t s_len, bool v6, const struct icmp46 *icmp);
|
||||
|
||||
bool proto_check_ipv4(const uint8_t *data, size_t len);
|
||||
void proto_skip_ipv4(const uint8_t **data, size_t *len);
|
||||
bool proto_check_ipv4_payload(const uint8_t *data, size_t len);
|
||||
void proto_skip_ipv4(const uint8_t **data, size_t *len, bool *frag, uint16_t *frag_off);
|
||||
bool proto_check_ipv6(const uint8_t *data, size_t len);
|
||||
bool proto_check_ipv6_payload(const uint8_t *data, size_t len);
|
||||
void proto_skip_ipv6(const uint8_t **data, size_t *len, uint8_t *proto_type);
|
||||
void proto_skip_ipv6(const uint8_t **data, size_t *len, uint8_t *proto_type, bool *frag, uint16_t *frag_off);
|
||||
uint8_t *proto_find_ip6_exthdr(struct ip6_hdr *ip6, size_t len, uint8_t proto);
|
||||
bool proto_check_tcp(const uint8_t *data, size_t len);
|
||||
void proto_skip_tcp(const uint8_t **data, size_t *len);
|
||||
@@ -202,6 +203,8 @@ struct dissect
|
||||
size_t transport_len;
|
||||
const uint8_t *data_payload;
|
||||
size_t len_payload;
|
||||
bool frag;
|
||||
uint16_t frag_off;
|
||||
};
|
||||
void proto_dissect_l3l4(const uint8_t *data, size_t len, struct dissect *dis, bool no_payload_check);
|
||||
void reverse_ip(struct ip *ip, struct ip6_hdr *ip6);
|
||||
|
||||
289
nfq2/desync.c
289
nfq2/desync.c
@@ -188,7 +188,10 @@ static void packet_debug(bool replay, const struct dissect *dis)
|
||||
{
|
||||
char s_proto[16];
|
||||
str_proto_name(s_proto,sizeof(s_proto),dis->proto);
|
||||
DLOG("\nIP PROTO %s: len=%zu : ", s_proto, dis->len_payload);
|
||||
if (dis->frag)
|
||||
DLOG("\nIP FRAG off=%u PROTO %s: len=%zu : ", dis->frag_off, s_proto, dis->len_payload);
|
||||
else
|
||||
DLOG("\nIP PROTO %s: len=%zu : ", s_proto, dis->len_payload);
|
||||
hexdump_limited_dlog(dis->data_payload, dis->len_payload, PKTDATA_MAXDUMP);
|
||||
DLOG("\n");
|
||||
}
|
||||
@@ -286,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 : "");
|
||||
@@ -553,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);
|
||||
@@ -609,7 +612,8 @@ static uint8_t ct_new_postnat_fix(const t_ctrack *ctrack, const struct dissect *
|
||||
// if used in postnat chain, dropping initial packet will cause conntrack connection teardown
|
||||
// so we need to workaround this.
|
||||
// SYN and SYN,ACK checks are for conntrack-less mode
|
||||
if (ctrack && (params.server ? ctrack->pos.server.pcounter : ctrack->pos.client.pcounter) == 1 || dis->tcp && (tcp_syn_segment(dis->tcp) || tcp_synack_segment(dis->tcp)))
|
||||
if (ctrack && (params.server ? ctrack->pos.server.pcounter : ctrack->pos.client.pcounter) == 1 ||
|
||||
!ctrack && dis->tcp && (tcp_syn_segment(dis->tcp) || tcp_synack_segment(dis->tcp)))
|
||||
{
|
||||
if (dis->len_pkt > *len_mod_pkt)
|
||||
DLOG_ERR("linux postnat conntrack workaround cannot be applied\n");
|
||||
@@ -729,25 +733,20 @@ static bool ipcache_get_hostname(const struct in_addr *a4, const struct in6_addr
|
||||
if (!params.cache_hostname)
|
||||
{
|
||||
*hostname = 0;
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
if (params.debug)
|
||||
{
|
||||
char s[40];
|
||||
char s[INET6_ADDRSTRLEN];
|
||||
ntopa46(a4, a6, s, sizeof(s));
|
||||
DLOG("ipcache hostname search for %s\n", s);
|
||||
}
|
||||
ip_cache_item *ipc = ipcacheTouch(¶ms.ipcache, a4, a6, NULL);
|
||||
if (!ipc)
|
||||
{
|
||||
DLOG_ERR("ipcache_get_hostname: out of memory\n");
|
||||
return false;
|
||||
}
|
||||
if (ipc->hostname)
|
||||
ip_cache_item *ipc = ipcacheFind(¶ms.ipcache, a4, a6, NULL);
|
||||
if (ipc && ipc->hostname)
|
||||
{
|
||||
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);
|
||||
}
|
||||
@@ -756,31 +755,36 @@ static bool ipcache_get_hostname(const struct in_addr *a4, const struct in6_addr
|
||||
}
|
||||
else
|
||||
*hostname = 0;
|
||||
return true;
|
||||
return *hostname;
|
||||
}
|
||||
static void ipcache_update_ttl(t_ctrack *ctrack, const struct in_addr *a4, const struct in6_addr *a6, const char *iface)
|
||||
{
|
||||
// no need to cache ttl in server mode because first packet is incoming
|
||||
if (ctrack && !params.server)
|
||||
{
|
||||
ip_cache_item *ipc = ipcacheTouch(¶ms.ipcache, a4, a6, iface);
|
||||
if (!ipc)
|
||||
{
|
||||
DLOG_ERR("ipcache: out of memory\n");
|
||||
return;
|
||||
}
|
||||
ip_cache_item *ipc;
|
||||
if (ctrack->incoming_ttl)
|
||||
{
|
||||
ipc = ipcacheTouch(¶ms.ipcache, a4, a6, iface);
|
||||
if (!ipc)
|
||||
{
|
||||
DLOG_ERR("ipcache: out of memory\n");
|
||||
return;
|
||||
}
|
||||
if (ipc->ttl != ctrack->incoming_ttl)
|
||||
{
|
||||
DLOG("updated ttl cache\n");
|
||||
ipc->ttl = ctrack->incoming_ttl;
|
||||
}
|
||||
}
|
||||
else if (ipc->ttl)
|
||||
else
|
||||
{
|
||||
DLOG("got cached ttl %u\n", ipc->ttl);
|
||||
ctrack->incoming_ttl = ipc->ttl;
|
||||
ipc = ipcacheFind(¶ms.ipcache, a4, a6, iface);
|
||||
if (ipc && ipc->ttl)
|
||||
{
|
||||
DLOG("got cached ttl %u\n", ipc->ttl);
|
||||
ctrack->incoming_ttl = ipc->ttl;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -789,10 +793,8 @@ static void ipcache_get_ttl(t_ctrack *ctrack, const struct in_addr *a4, const st
|
||||
// no need to cache ttl in server mode because first packet is incoming
|
||||
if (ctrack && !ctrack->incoming_ttl && !params.server)
|
||||
{
|
||||
ip_cache_item *ipc = ipcacheTouch(¶ms.ipcache, a4, a6, iface);
|
||||
if (!ipc)
|
||||
DLOG_ERR("ipcache: out of memory\n");
|
||||
else if (ipc->ttl)
|
||||
ip_cache_item *ipc = ipcacheFind(¶ms.ipcache, a4, a6, iface);
|
||||
if (ipc && ipc->ttl)
|
||||
{
|
||||
DLOG("got cached ttl %u\n", ipc->ttl);
|
||||
ctrack->incoming_ttl = ipc->ttl;
|
||||
@@ -896,7 +898,7 @@ static uint8_t desync(
|
||||
if (LIST_FIRST(&dp->lua_desync))
|
||||
{
|
||||
lua_rawgeti(params.L, LUA_REGISTRYINDEX, params.ref_desync_ctx);
|
||||
t_lua_desync_context *ctx = (t_lua_desync_context *)luaL_checkudata(params.L, 1, "desync_ctx");
|
||||
t_lua_desync_context *ctx = (t_lua_desync_context *)luaL_checkudata(params.L, -1, "desync_ctx");
|
||||
// this is singleton stored in the registry. safe to pop
|
||||
lua_pop(params.L,1);
|
||||
|
||||
@@ -1135,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);
|
||||
}
|
||||
@@ -1263,7 +1265,7 @@ static bool play_prolog(
|
||||
hostname_is_ip = ps->ctrack->hostname_is_ip;
|
||||
if (!hostname && !ps->bReverse)
|
||||
{
|
||||
if (ipcache_get_hostname(ps->sdip4, ps->sdip6, ps->host, sizeof(ps->host), &hostname_is_ip) && *ps->host)
|
||||
if (ipcache_get_hostname(ps->sdip4, ps->sdip6, ps->host, sizeof(ps->host), &hostname_is_ip))
|
||||
if (!(hostname = ps->ctrack->hostname = strdup(ps->host)))
|
||||
DLOG_ERR("strdup(host): out of memory\n");
|
||||
}
|
||||
@@ -1451,7 +1453,8 @@ static uint8_t dpi_desync_tcp_packet_play(
|
||||
{L7P_HTTP_REPLY,L7_HTTP,IsHttpReply,false},
|
||||
{L7P_XMPP_STREAM,L7_XMPP,IsXMPPStream,false},
|
||||
{L7P_XMPP_PROCEED,L7_XMPP,IsXMPPProceedTLS,false},
|
||||
{L7P_XMPP_FEATURES,L7_XMPP,IsXMPPFeatures,false}
|
||||
{L7P_XMPP_FEATURES,L7_XMPP,IsXMPPFeatures,false},
|
||||
{L7P_BT_HANDSHAKE,L7_BT,IsBTHandshake,false}
|
||||
};
|
||||
protocol_probe(testers, sizeof(testers) / sizeof(*testers), dis->data_payload, dis->len_payload, ps.ctrack, &ps.l7proto, &ps.l7payload);
|
||||
|
||||
@@ -1531,10 +1534,11 @@ static uint8_t dpi_desync_tcp_packet_play(
|
||||
if (!ps.ctrack_replay || ReasmIsEmpty(&ps.ctrack_replay->reasm_client))
|
||||
{
|
||||
t_protocol_probe testers[] = {
|
||||
{L7P_TLS_CLIENT_HELLO,L7_TLS,IsTLSClientHelloPartial},
|
||||
{L7P_TLS_CLIENT_HELLO,L7_TLS,IsTLSClientHelloPartial,false},
|
||||
{L7P_HTTP_REQ,L7_HTTP,IsHttp,false},
|
||||
{L7P_XMPP_STREAM,L7_XMPP,IsXMPPStream,false},
|
||||
{L7P_XMPP_STARTTLS,L7_XMPP,IsXMPPStartTLS,false}
|
||||
{L7P_XMPP_STARTTLS,L7_XMPP,IsXMPPStartTLS,false},
|
||||
{L7P_BT_HANDSHAKE,L7_BT,IsBTHandshake,false}
|
||||
};
|
||||
protocol_probe(testers, sizeof(testers) / sizeof(*testers), rdata_payload, rlen_payload, ps.ctrack_replay, &ps.l7proto, &ps.l7payload);
|
||||
|
||||
@@ -1544,7 +1548,7 @@ static uint8_t dpi_desync_tcp_packet_play(
|
||||
if (ps.tpos && (ps.tpos->client.seq_last - ps.tpos->client.seq0)==1)
|
||||
{
|
||||
t_protocol_probe testers[] = {
|
||||
{L7P_MTPROTO_INITIAL,L7_MTPROTO,IsMTProto}
|
||||
{L7P_MTPROTO_INITIAL,L7_MTPROTO,IsMTProto,false}
|
||||
};
|
||||
protocol_probe(testers, sizeof(testers) / sizeof(*testers), rdata_payload, rlen_payload, ps.ctrack_replay, &ps.l7proto, &ps.l7payload);
|
||||
}
|
||||
@@ -1570,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))
|
||||
{
|
||||
@@ -1597,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;
|
||||
|
||||
@@ -1627,6 +1634,7 @@ static void udp_standard_protocol_probe(const uint8_t *data_payload, size_t len_
|
||||
{L7P_DHT,L7_DHT,IsDht,false},
|
||||
{L7P_DTLS_CLIENT_HELLO,L7_DTLS,IsDTLSClientHello,false},
|
||||
{L7P_DTLS_SERVER_HELLO,L7_DTLS,IsDTLSServerHello,false},
|
||||
{L7P_UTP_BT_HANDSHAKE,L7_UTP_BT,IsUTP_BTHandshake,false},
|
||||
{L7P_WIREGUARD_INITIATION,L7_WIREGUARD,IsWireguardHandshakeInitiation,false},
|
||||
{L7P_WIREGUARD_RESPONSE,L7_WIREGUARD,IsWireguardHandshakeResponse,false},
|
||||
{L7P_WIREGUARD_COOKIE,L7_WIREGUARD,IsWireguardHandshakeCookie,false},
|
||||
@@ -1640,11 +1648,15 @@ 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>=e) return NULL;
|
||||
if (a+1>=e) return NULL;
|
||||
// name pointer
|
||||
off = (*a & 0x3F)<<8 | a[1];
|
||||
p = b + off;
|
||||
@@ -1656,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;
|
||||
}
|
||||
@@ -1773,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);
|
||||
@@ -1797,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)
|
||||
{
|
||||
@@ -1839,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);
|
||||
}
|
||||
@@ -1873,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
|
||||
@@ -1944,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;
|
||||
@@ -1981,8 +2040,8 @@ static uint8_t dpi_desync_icmp_packet(
|
||||
hostname = ctrack->hostname;
|
||||
hostname_is_ip = ctrack->hostname_is_ip;
|
||||
}
|
||||
else if (ipcache_get_hostname(dis->ip ? &dis->ip->ip_dst : NULL, dis->ip6 ? &dis->ip6->ip6_dst : NULL, host, sizeof(host), &hostname_is_ip) && *host ||
|
||||
ipcache_get_hostname(dis->ip ? &dis->ip->ip_src : NULL, dis->ip6 ? &dis->ip6->ip6_src : NULL, host, sizeof(host), &hostname_is_ip) && *host)
|
||||
else if (ipcache_get_hostname(dis->ip ? &dis->ip->ip_dst : NULL, dis->ip6 ? &dis->ip6->ip6_dst : NULL, host, sizeof(host), &hostname_is_ip) ||
|
||||
ipcache_get_hostname(dis->ip ? &dis->ip->ip_src : NULL, dis->ip6 ? &dis->ip6->ip6_src : NULL, host, sizeof(host), &hostname_is_ip))
|
||||
{
|
||||
hostname = host;
|
||||
}
|
||||
@@ -2029,7 +2088,7 @@ static uint8_t dpi_desync_ip_packet(
|
||||
if (!!dis->ip == !!dis->ip6) return verdict;
|
||||
|
||||
struct sockaddr_storage src, dst;
|
||||
const char *ssid;
|
||||
const char *ssid = NULL;
|
||||
struct desync_profile *dp;
|
||||
|
||||
extract_endpoints(dis->ip, dis->ip6, NULL, NULL, &src, &dst);
|
||||
@@ -2048,8 +2107,8 @@ static uint8_t dpi_desync_ip_packet(
|
||||
bool hostname_is_ip = false;
|
||||
const char *hostname = NULL;
|
||||
char host[256];
|
||||
if (ipcache_get_hostname(dis->ip ? &dis->ip->ip_dst : NULL, dis->ip6 ? &dis->ip6->ip6_dst : NULL, host, sizeof(host), &hostname_is_ip) && *host ||
|
||||
ipcache_get_hostname(dis->ip ? &dis->ip->ip_src : NULL, dis->ip6 ? &dis->ip6->ip6_src : NULL, host, sizeof(host), &hostname_is_ip) && *host)
|
||||
if (ipcache_get_hostname(dis->ip ? &dis->ip->ip_dst : NULL, dis->ip6 ? &dis->ip6->ip6_dst : NULL, host, sizeof(host), &hostname_is_ip) ||
|
||||
ipcache_get_hostname(dis->ip ? &dis->ip->ip_src : NULL, dis->ip6 ? &dis->ip6->ip6_src : NULL, host, sizeof(host), &hostname_is_ip))
|
||||
{
|
||||
hostname = host;
|
||||
}
|
||||
@@ -2097,37 +2156,30 @@ static uint8_t dpi_desync_packet_play(
|
||||
if (!!dis.ip != !!dis.ip6)
|
||||
{
|
||||
packet_debug(!!replay_piece_count, &dis);
|
||||
|
||||
// fix csum if unmodified and if OS can pass wrong csum to queue (depends on OS)
|
||||
// modified means we have already fixed the checksum or made it invalid intentionally
|
||||
// this is the only point we VIOLATE const to fix the checksum in the original buffer to avoid copying to mod_pkt
|
||||
switch (dis.proto)
|
||||
if (dis.tcp)
|
||||
{
|
||||
case IPPROTO_TCP:
|
||||
if (dis.tcp)
|
||||
{
|
||||
verdict = dpi_desync_tcp_packet_play(replay_piece, replay_piece_count, reasm_offset, fwmark, ifin, ifout, tpos, &dis, mod_pkt, len_mod_pkt);
|
||||
verdict_tcp_csum_fix(verdict, (struct tcphdr *)dis.tcp, dis.transport_len, dis.ip, dis.ip6);
|
||||
}
|
||||
break;
|
||||
case IPPROTO_UDP:
|
||||
if (dis.udp)
|
||||
{
|
||||
verdict = dpi_desync_udp_packet_play(replay_piece, replay_piece_count, reasm_offset, fwmark, ifin, ifout, tpos, &dis, mod_pkt, len_mod_pkt);
|
||||
verdict_udp_csum_fix(verdict, (struct udphdr *)dis.udp, dis.transport_len, dis.ip, dis.ip6);
|
||||
}
|
||||
break;
|
||||
case IPPROTO_ICMP:
|
||||
case IPPROTO_ICMPV6:
|
||||
if (dis.icmp)
|
||||
{
|
||||
verdict = dpi_desync_icmp_packet(fwmark, ifin, ifout, &dis, mod_pkt, len_mod_pkt);
|
||||
verdict_icmp_csum_fix(verdict, (struct icmp46 *)dis.icmp, dis.transport_len, dis.ip6);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
verdict = dpi_desync_ip_packet(fwmark, ifin, ifout, &dis, mod_pkt, len_mod_pkt);
|
||||
verdict = dpi_desync_tcp_packet_play(replay_piece, replay_piece_count, reasm_offset, fwmark, ifin, ifout, tpos, &dis, mod_pkt, len_mod_pkt);
|
||||
verdict_tcp_csum_fix(verdict, (struct tcphdr *)dis.tcp, dis.transport_len, dis.ip, dis.ip6);
|
||||
}
|
||||
else if (dis.udp)
|
||||
{
|
||||
verdict = dpi_desync_udp_packet_play(replay_piece, replay_piece_count, reasm_offset, fwmark, ifin, ifout, tpos, &dis, mod_pkt, len_mod_pkt);
|
||||
verdict_udp_csum_fix(verdict, (struct udphdr *)dis.udp, dis.transport_len, dis.ip, dis.ip6);
|
||||
}
|
||||
else if (dis.icmp)
|
||||
{
|
||||
verdict = dpi_desync_icmp_packet(fwmark, ifin, ifout, &dis, mod_pkt, len_mod_pkt);
|
||||
verdict_icmp_csum_fix(verdict, (struct icmp46 *)dis.icmp, dis.transport_len, dis.ip6);
|
||||
}
|
||||
else
|
||||
verdict = dpi_desync_ip_packet(fwmark, ifin, ifout, &dis, mod_pkt, len_mod_pkt);
|
||||
}
|
||||
else
|
||||
DLOG("invalid packet - neither ipv4 or ipv6\n");
|
||||
return verdict;
|
||||
}
|
||||
uint8_t dpi_desync_packet(uint32_t fwmark, const char *ifin, const char *ifout, const uint8_t *data_pkt, size_t len_pkt, uint8_t *mod_pkt, size_t *len_mod_pkt)
|
||||
@@ -2145,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);
|
||||
@@ -2168,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;
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ bool pf_parse(const char *s, port_filter *pf)
|
||||
if (*s=='*' && s[1]==0)
|
||||
{
|
||||
pf->from=1; pf->to=0xFFFF;
|
||||
pf->neg=false;
|
||||
return true;
|
||||
}
|
||||
if (*s=='~')
|
||||
@@ -172,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);
|
||||
|
||||
455
nfq2/helpers.c
455
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(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,89 +457,150 @@ 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;
|
||||
for (k=0 ; (k+1)<sz ; k+=2) phton16(p+k, (uint16_t)random());
|
||||
if (sz & 1) p[sz-1]=(uint8_t)random();
|
||||
if (sz)
|
||||
{
|
||||
// alignment
|
||||
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();
|
||||
}
|
||||
}
|
||||
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
|
||||
|
||||
bool fill_crypto_random_bytes(uint8_t *p,size_t sz)
|
||||
|
||||
ssize_t read_intr(int fd, void *buf, size_t count)
|
||||
{
|
||||
ssize_t rd;
|
||||
while ((rd = read(fd, buf, count)) < 0 && errno == EINTR);
|
||||
return rd;
|
||||
}
|
||||
|
||||
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(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(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);
|
||||
}
|
||||
}
|
||||
@@ -543,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;
|
||||
}
|
||||
|
||||
@@ -594,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')
|
||||
@@ -616,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
|
||||
@@ -33,6 +36,10 @@ const char *strncasestr(const char *s,const char *find, size_t slen);
|
||||
// [a-zA-z][a-zA-Z0-9]*
|
||||
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);
|
||||
bool append_to_list_file(const char *filename, const char *s);
|
||||
@@ -102,19 +109,22 @@ 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)
|
||||
#define CLOCK_BOOT_OR_UPTIME CLOCK_UPTIME
|
||||
#else
|
||||
#define CLOCK_BOOT_OR_UPTIME CLOCK_MONOTINIC
|
||||
#define CLOCK_BOOT_OR_UPTIME CLOCK_MONOTONIC
|
||||
#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
|
||||
|
||||
496
nfq2/lua.c
496
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;
|
||||
@@ -1053,7 +1054,7 @@ static int luacall_execution_plan(lua_State *L)
|
||||
{
|
||||
for (pl=0 ; pl<L7P_LAST ; pl++)
|
||||
{
|
||||
if (func->payload_type & (1<<pl))
|
||||
if (func->payload_type & (1ULL<<pl))
|
||||
{
|
||||
if ((pls = l7payload_str(pl)))
|
||||
{
|
||||
@@ -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)
|
||||
{
|
||||
@@ -1422,7 +1424,7 @@ void lua_push_icmphdr(lua_State *L, const struct icmp46 *icmp, size_t len)
|
||||
lua_pushf_int(L,"icmp_type",icmp->icmp_type);
|
||||
lua_pushf_int(L,"icmp_code",icmp->icmp_code);
|
||||
lua_pushf_int(L,"icmp_cksum",ntohs(icmp->icmp_cksum));
|
||||
lua_pushf_lint(L,"icmp_data",ntohl(icmp->icmp_data32));
|
||||
lua_pushf_lint(L,"icmp_data",ntohl(icmp->data.data32));
|
||||
}
|
||||
else
|
||||
lua_pushnil(L);
|
||||
@@ -1508,9 +1510,11 @@ void lua_pushf_ip6exthdr(lua_State *L, const struct ip6_hdr *ip6, size_t len)
|
||||
|
||||
// assume ipv6 packet structure was already checked for validity
|
||||
size_t hdrlen;
|
||||
lua_Integer idx = 1;
|
||||
uint8_t HeaderType, *data;
|
||||
uint16_t plen;
|
||||
lua_Integer idx = 1;
|
||||
uint16_t fr_off=0;
|
||||
bool fr=false;
|
||||
|
||||
lua_pushliteral(L, "exthdr");
|
||||
lua_newtable(L);
|
||||
@@ -1521,7 +1525,7 @@ void lua_pushf_ip6exthdr(lua_State *L, const struct ip6_hdr *ip6, size_t len)
|
||||
len-=sizeof(struct ip6_hdr);
|
||||
plen = ntohs(ip6->ip6_ctlun.ip6_un1.ip6_un1_plen);
|
||||
if (plen < len) len = plen;
|
||||
while (len > 0) // need at least one byte for NextHeader field
|
||||
while (len && !(fr && fr_off)) // need at least one byte for NextHeader field. stop after fragment header if not first fragment
|
||||
{
|
||||
switch (HeaderType)
|
||||
{
|
||||
@@ -1536,6 +1540,9 @@ void lua_pushf_ip6exthdr(lua_State *L, const struct ip6_hdr *ip6, size_t len)
|
||||
break;
|
||||
case IPPROTO_FRAGMENT: // fragment. length fixed to 8, hdrlen field defined as reserved
|
||||
hdrlen = 8;
|
||||
if (len < hdrlen) goto end;
|
||||
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
|
||||
@@ -1618,17 +1625,18 @@ void lua_push_dissect(lua_State *L, const struct dissect *dis)
|
||||
|
||||
if (dis)
|
||||
{
|
||||
lua_createtable(L, 0, 10);
|
||||
lua_pushf_iphdr(L,dis->ip, dis->len_l3);
|
||||
lua_pushf_ip6hdr(L,dis->ip6, dis->len_l3);
|
||||
lua_pushf_tcphdr(L,dis->tcp, dis->len_l4);
|
||||
lua_pushf_udphdr(L,dis->udp, dis->len_l4);
|
||||
lua_pushf_icmphdr(L,dis->icmp, dis->len_l4);
|
||||
lua_createtable(L, 0, 10+dis->frag);
|
||||
lua_pushf_int(L,"l4proto",dis->proto);
|
||||
lua_pushf_int(L,"transport_len",dis->transport_len);
|
||||
lua_pushf_int(L,"l3_len",dis->len_l3);
|
||||
lua_pushf_int(L,"l4_len",dis->len_l4);
|
||||
lua_pushf_raw(L,"payload",dis->data_payload,dis->len_payload);
|
||||
if (dis->frag) lua_pushf_int(L,"frag_off",dis->frag_off);
|
||||
lua_pushf_iphdr(L,dis->ip, dis->len_l3);
|
||||
lua_pushf_ip6hdr(L,dis->ip6, dis->len_l3);
|
||||
lua_pushf_tcphdr(L,dis->tcp, dis->len_l4);
|
||||
lua_pushf_udphdr(L,dis->udp, dis->len_l4);
|
||||
lua_pushf_icmphdr(L,dis->icmp, dis->len_l4);
|
||||
}
|
||||
else
|
||||
lua_pushnil(L);
|
||||
@@ -1650,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);
|
||||
@@ -1772,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);
|
||||
@@ -1857,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);
|
||||
@@ -1894,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;
|
||||
@@ -2007,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;
|
||||
|
||||
@@ -2177,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)
|
||||
|
||||
@@ -2252,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)
|
||||
|
||||
@@ -2296,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)
|
||||
|
||||
@@ -2312,7 +2336,7 @@ bool lua_reconstruct_icmphdr(lua_State *L, int idx, struct icmp46 *icmp)
|
||||
|
||||
lua_getfield(L,idx,"icmp_data");
|
||||
if (lua_type(L,-1)!=LUA_TNUMBER) goto err;
|
||||
icmp->icmp_data32 = htonl((uint32_t)lua_tolint(L,-1));
|
||||
icmp->data.data32 = htonl((uint32_t)lua_tolint(L,-1));
|
||||
lua_pop(L, 1);
|
||||
|
||||
lua_getfield(L,idx,"icmp_cksum");
|
||||
@@ -2383,11 +2407,24 @@ bool lua_reconstruct_dissect(lua_State *L, int idx, uint8_t *buf, size_t *len, b
|
||||
struct udphdr *udp=NULL;
|
||||
struct icmp46 *icmp=NULL;
|
||||
const char *p;
|
||||
bool frag;
|
||||
|
||||
LUA_STACK_GUARD_ENTER(L)
|
||||
|
||||
idx = lua_absindex(L, idx);
|
||||
|
||||
lua_getfield(L,idx,"frag_off");
|
||||
if (lua_type(L,-1)!=LUA_TNIL)
|
||||
{
|
||||
luaL_checkinteger(L,-1); // verify type
|
||||
frag = true;
|
||||
}
|
||||
else
|
||||
frag = false;
|
||||
lua_pop(L, 1);
|
||||
|
||||
if (frag) ip6_preserve_next = true; // there's no other source of next. no tcp, no udp, no icmp headers. just raw ip payload
|
||||
|
||||
lua_getfield(L,idx,"ip");
|
||||
l = left;
|
||||
if (lua_type(L,-1)==LUA_TTABLE)
|
||||
@@ -2416,150 +2453,182 @@ bool lua_reconstruct_dissect(lua_State *L, int idx, uint8_t *buf, size_t *len, b
|
||||
data+=l; left-=l;
|
||||
lua_pop(L, 1);
|
||||
|
||||
lua_getfield(L,idx,"tcp");
|
||||
l=0;
|
||||
if (lua_type(L,-1)==LUA_TTABLE)
|
||||
if (frag)
|
||||
{
|
||||
l = left;
|
||||
tcp = (struct tcphdr*)data;
|
||||
if (!lua_reconstruct_tcphdr(L, -1, tcp, &l))
|
||||
lua_getfield(L,idx,"payload");
|
||||
p = lua_tolstring(L,-1,&lpayload);
|
||||
if (p)
|
||||
{
|
||||
DLOG_ERR("reconstruct_dissect: bad tcp\n");
|
||||
goto err;
|
||||
if (lpayload>0xFFFF)
|
||||
{
|
||||
DLOG_ERR("reconstruct_dissect: payload too large : %zu\n",lpayload);
|
||||
goto err;
|
||||
}
|
||||
if (left<lpayload)
|
||||
{
|
||||
DLOG_ERR("reconstruct_dissect: payload does not fit into the buffer : payload %zu buffer_left %zu\n",lpayload,left);
|
||||
goto err;
|
||||
}
|
||||
memcpy(data,p,lpayload);
|
||||
data+=lpayload; left-=lpayload;
|
||||
}
|
||||
else
|
||||
lpayload = 0;
|
||||
lua_pop(L, 1);
|
||||
l = data-buf;
|
||||
}
|
||||
else
|
||||
{
|
||||
lua_pop(L, 1);
|
||||
lua_getfield(L,idx,"udp");
|
||||
lua_getfield(L,idx,"tcp");
|
||||
l=0;
|
||||
if (lua_type(L,-1)==LUA_TTABLE)
|
||||
{
|
||||
l = sizeof(struct udphdr);
|
||||
udp = (struct udphdr*)data;
|
||||
if (!lua_reconstruct_udphdr(L, -1, udp))
|
||||
l = left;
|
||||
tcp = (struct tcphdr*)data;
|
||||
if (!lua_reconstruct_tcphdr(L, -1, tcp, &l))
|
||||
{
|
||||
DLOG_ERR("reconstruct_dissect: bad udp\n");
|
||||
DLOG_ERR("reconstruct_dissect: bad tcp\n");
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
lua_pop(L, 1);
|
||||
lua_getfield(L,idx,"icmp");
|
||||
lua_getfield(L,idx,"udp");
|
||||
if (lua_type(L,-1)==LUA_TTABLE)
|
||||
{
|
||||
l = sizeof(struct icmp46);
|
||||
icmp = (struct icmp46*)data;
|
||||
if (!lua_reconstruct_icmphdr(L, -1, icmp))
|
||||
l = sizeof(struct udphdr);
|
||||
udp = (struct udphdr*)data;
|
||||
if (!lua_reconstruct_udphdr(L, -1, udp))
|
||||
{
|
||||
DLOG_ERR("reconstruct_dissect: bad icmp\n");
|
||||
DLOG_ERR("reconstruct_dissect: bad udp\n");
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
data+=l; left-=l;
|
||||
lua_pop(L, 1);
|
||||
|
||||
lua_getfield(L,idx,"payload");
|
||||
p = lua_tolstring(L,-1,&lpayload);
|
||||
if (p)
|
||||
{
|
||||
if (lpayload>0xFFFF)
|
||||
{
|
||||
DLOG_ERR("reconstruct_dissect: invalid payload length\n");
|
||||
goto err;
|
||||
}
|
||||
if (left<lpayload) goto err;
|
||||
memcpy(data,p,lpayload);
|
||||
data+=lpayload; left-=lpayload;
|
||||
}
|
||||
else
|
||||
lpayload = 0;
|
||||
lua_pop(L, 1);
|
||||
|
||||
l = data-buf;
|
||||
|
||||
if (!keepsum)
|
||||
{
|
||||
if (tcp)
|
||||
{
|
||||
tcp_fix_checksum(tcp,l-l3,ip,ip6);
|
||||
if (badsum) tcp->th_sum ^= 1 + (random() % 0xFFFF);
|
||||
}
|
||||
else if (udp)
|
||||
{
|
||||
sz = (uint16_t)(lpayload+sizeof(struct udphdr));
|
||||
if (sz>0xFFFF)
|
||||
else
|
||||
{
|
||||
DLOG_ERR("reconstruct_dissect: invalid payload length\n");
|
||||
lua_pop(L, 1);
|
||||
lua_getfield(L,idx,"icmp");
|
||||
if (lua_type(L,-1)==LUA_TTABLE)
|
||||
{
|
||||
l = sizeof(struct icmp46);
|
||||
icmp = (struct icmp46*)data;
|
||||
if (!lua_reconstruct_icmphdr(L, -1, icmp))
|
||||
{
|
||||
DLOG_ERR("reconstruct_dissect: bad icmp\n");
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
data+=l; left-=l;
|
||||
lua_pop(L, 1);
|
||||
|
||||
lua_getfield(L,idx,"payload");
|
||||
p = lua_tolstring(L,-1,&lpayload);
|
||||
if (p)
|
||||
{
|
||||
if (lpayload>0xFFFF)
|
||||
{
|
||||
DLOG_ERR("reconstruct_dissect: payload too large : %zu\n",lpayload);
|
||||
goto err;
|
||||
}
|
||||
udp->uh_ulen = htons((uint16_t)sz);
|
||||
udp_fix_checksum(udp,l-l3,ip,ip6);
|
||||
if (badsum) udp->uh_sum ^= 1 + (random() % 0xFFFF);
|
||||
}
|
||||
else if (icmp)
|
||||
{
|
||||
icmp_fix_checksum(icmp,l-l3,ip6);
|
||||
if (badsum) icmp->icmp_cksum ^= 1 + (random() % 0xFFFF);
|
||||
}
|
||||
}
|
||||
|
||||
if (ip)
|
||||
{
|
||||
if (ntohs(ip->ip_off) & (IP_OFFMASK|IP_MF))
|
||||
{
|
||||
// fragmentation. caller should set ip_len, ip_off and IP_MF correctly. C code moves and shrinks constructed ip payload
|
||||
uint16_t iplen = ntohs(ip->ip_len);
|
||||
uint16_t off = (ntohs(ip->ip_off) & IP_OFFMASK)<<3;
|
||||
size_t frag_start = l3 + off;
|
||||
if (iplen<l3 || iplen>l)
|
||||
if (left<lpayload)
|
||||
{
|
||||
DLOG_ERR("ipv4 frag : invalid ip_len\n");
|
||||
DLOG_ERR("reconstruct_dissect: payload does not fit into the buffer : payload %zu buffer_left %zu\n",lpayload,left);
|
||||
goto err;
|
||||
}
|
||||
if (frag_start>l)
|
||||
{
|
||||
DLOG_ERR("ipv4 frag : fragment offset is outside of the packet\n");
|
||||
goto err;
|
||||
}
|
||||
if (off) memmove(buf+l3,buf+l3+off,iplen-l3);
|
||||
l = iplen; // shrink packet to iplen
|
||||
memcpy(data,p,lpayload);
|
||||
data+=lpayload; left-=lpayload;
|
||||
}
|
||||
else
|
||||
ip->ip_len = htons((uint16_t)l);
|
||||
ip4_fix_checksum(ip);
|
||||
}
|
||||
else if (ip6)
|
||||
{
|
||||
// data points to reconstructed packet's end
|
||||
uint8_t *frag = proto_find_ip6_exthdr(ip6, l, IPPROTO_FRAGMENT);
|
||||
if (frag)
|
||||
{
|
||||
uint16_t plen = ntohs(ip6->ip6_ctlun.ip6_un1.ip6_un1_plen); // without ipv6 base header
|
||||
uint16_t off = ntohs(((struct ip6_frag *)frag)->ip6f_offlg) & 0xFFF8;
|
||||
uint8_t *endfrag = frag + 8;
|
||||
size_t size_unfragmentable = endfrag - (uint8_t*)ip6 - sizeof(struct ip6_hdr);
|
||||
lpayload = 0;
|
||||
lua_pop(L, 1);
|
||||
|
||||
if (size_unfragmentable > plen)
|
||||
l = data-buf;
|
||||
|
||||
if (!keepsum)
|
||||
{
|
||||
if (tcp)
|
||||
{
|
||||
DLOG_ERR("ipv6 frag : invalid ip6_plen\n");
|
||||
goto err;
|
||||
tcp_fix_checksum(tcp,l-l3,ip,ip6);
|
||||
if (badsum) tcp->th_sum ^= 1 + (random() % 0xFFFF);
|
||||
}
|
||||
size_t size_fragmentable = plen - size_unfragmentable;
|
||||
if ((endfrag + off + size_fragmentable) > data)
|
||||
else if (udp)
|
||||
{
|
||||
DLOG_ERR("ipv6 frag : fragmentable part is outside of the packet\n");
|
||||
goto err;
|
||||
sz = lpayload+sizeof(struct udphdr);
|
||||
if (sz>0xFFFF)
|
||||
{
|
||||
DLOG_ERR("reconstruct_dissect: invalid payload length\n");
|
||||
goto err;
|
||||
}
|
||||
udp->uh_ulen = htons((uint16_t)sz);
|
||||
udp_fix_checksum(udp,l-l3,ip,ip6);
|
||||
if (badsum) udp->uh_sum ^= 1 + (random() % 0xFFFF);
|
||||
}
|
||||
else if (icmp)
|
||||
{
|
||||
icmp_fix_checksum(icmp,l-l3,ip6);
|
||||
if (badsum) icmp->icmp_cksum ^= 1 + (random() % 0xFFFF);
|
||||
}
|
||||
if (off) memmove(endfrag, endfrag + off, size_fragmentable);
|
||||
l = sizeof(struct ip6_hdr) + plen;
|
||||
}
|
||||
else
|
||||
ip6->ip6_ctlun.ip6_un1.ip6_un1_plen = htons((uint16_t)(l-sizeof(struct ip6_hdr)));
|
||||
|
||||
if (ip)
|
||||
{
|
||||
if (ntohs(ip->ip_off) & (IP_OFFMASK|IP_MF))
|
||||
{
|
||||
// fragmentation. caller should set ip_len, ip_off and IP_MF correctly. C code moves and shrinks constructed ip payload
|
||||
uint16_t iplen = ntohs(ip->ip_len);
|
||||
uint16_t off = (ntohs(ip->ip_off) & IP_OFFMASK)<<3;
|
||||
size_t frag_start = l3 + off;
|
||||
if (iplen<l3 || iplen>l)
|
||||
{
|
||||
DLOG_ERR("ipv4 frag : invalid ip_len\n");
|
||||
goto err;
|
||||
}
|
||||
size_t frag_len = iplen-l3;
|
||||
if ((frag_start+frag_len)>l)
|
||||
{
|
||||
DLOG_ERR("ipv4 frag : fragment end is outside of the packet\n");
|
||||
goto err;
|
||||
}
|
||||
if (off) memmove(buf+l3,buf+frag_start,frag_len);
|
||||
l = iplen; // shrink packet to iplen
|
||||
}
|
||||
else
|
||||
ip->ip_len = htons((uint16_t)l);
|
||||
ip4_fix_checksum(ip);
|
||||
}
|
||||
else if (ip6)
|
||||
{
|
||||
// data points to reconstructed packet's end
|
||||
uint8_t *frag = proto_find_ip6_exthdr(ip6, l, IPPROTO_FRAGMENT);
|
||||
if (frag)
|
||||
{
|
||||
uint16_t plen = ntohs(ip6->ip6_ctlun.ip6_un1.ip6_un1_plen); // without ipv6 base header
|
||||
uint16_t off = ntohs(((struct ip6_frag *)frag)->ip6f_offlg) & 0xFFF8;
|
||||
uint8_t *endfrag = frag + 8;
|
||||
size_t size_unfragmentable = endfrag - (uint8_t*)ip6 - sizeof(struct ip6_hdr);
|
||||
|
||||
if (size_unfragmentable > plen)
|
||||
{
|
||||
DLOG_ERR("ipv6 frag : invalid ip6_plen\n");
|
||||
goto err;
|
||||
}
|
||||
size_t size_fragmentable = plen - size_unfragmentable;
|
||||
if ((endfrag + off + size_fragmentable) > data)
|
||||
{
|
||||
DLOG_ERR("ipv6 frag : fragmentable part is outside of the packet\n");
|
||||
goto err;
|
||||
}
|
||||
if (off) memmove(endfrag, endfrag + off, size_fragmentable);
|
||||
l = sizeof(struct ip6_hdr) + plen;
|
||||
}
|
||||
else
|
||||
ip6->ip6_ctlun.ip6_un1.ip6_un1_plen = htons((uint16_t)(l-sizeof(struct ip6_hdr)));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
*len = l;
|
||||
LUA_STACK_GUARD_LEAVE(L, 0)
|
||||
return true;
|
||||
@@ -2761,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);
|
||||
@@ -2781,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)
|
||||
}
|
||||
@@ -3087,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));
|
||||
|
||||
@@ -3128,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);
|
||||
@@ -3279,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);
|
||||
|
||||
@@ -3299,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);
|
||||
}
|
||||
@@ -3308,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
|
||||
@@ -3416,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)
|
||||
{
|
||||
@@ -3439,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:
|
||||
@@ -3461,12 +3540,12 @@ static void *z_alloc(voidpf opaque, uInt items, uInt size)
|
||||
}
|
||||
static void z_free(voidpf opaque, voidpf address)
|
||||
{
|
||||
return free(address);
|
||||
free(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)
|
||||
|
||||
@@ -3517,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);
|
||||
@@ -3530,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)
|
||||
{
|
||||
@@ -3553,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);
|
||||
@@ -3614,6 +3703,90 @@ static int luacall_stat(lua_State *L)
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void lua_xtime(lua_State *L, struct tm *(*timefunc)(const time_t *,struct tm *))
|
||||
{
|
||||
struct tm t;
|
||||
|
||||
time_t unixtime = (time_t)luaL_checklint(L,1);
|
||||
if (!timefunc(&unixtime, &t))
|
||||
{
|
||||
lua_pushnil(L);
|
||||
}
|
||||
else
|
||||
{
|
||||
lua_createtable(L, 0, 11);
|
||||
lua_pushf_int(L,"sec", t.tm_sec);
|
||||
lua_pushf_int(L,"min", t.tm_min);
|
||||
lua_pushf_int(L,"hour", t.tm_hour);
|
||||
lua_pushf_int(L,"mday", t.tm_mday);
|
||||
lua_pushf_int(L,"mon", t.tm_mon);
|
||||
lua_pushf_int(L,"year", t.tm_year+1900);
|
||||
lua_pushf_int(L,"wday", t.tm_wday);
|
||||
lua_pushf_int(L,"yday", t.tm_yday);
|
||||
lua_pushf_int(L,"isdst", t.tm_isdst);
|
||||
lua_pushf_str(L,"zone", t.tm_zone);
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
static int luacall_localtime(lua_State *L)
|
||||
{
|
||||
// localtime(unixtime)
|
||||
lua_check_argc(L,"localtime",1);
|
||||
lua_xtime(L, localtime_r);
|
||||
return 1;
|
||||
}
|
||||
static int luacall_gmtime(lua_State *L)
|
||||
{
|
||||
// gmtime(unixtime)
|
||||
lua_check_argc(L,"gmtime",1);
|
||||
lua_xtime(L, gmtime_r);
|
||||
return 1;
|
||||
}
|
||||
#define TIMEX_VAL(v) \
|
||||
lua_getfield(L,1,#v); \
|
||||
if (lua_type(L,-1)!=LUA_TNUMBER) luaL_error(L,"invalid tm." #v); \
|
||||
t.tm_##v = lua_tointeger(L,-1); \
|
||||
lua_pop(L,1);
|
||||
static void lua_timex(lua_State *L, time_t (*timefunc)(struct tm *))
|
||||
{
|
||||
if (lua_type(L,1)!=LUA_TTABLE) luaL_error(L,"invalid tm structure");
|
||||
|
||||
struct tm t;
|
||||
TIMEX_VAL(sec)
|
||||
TIMEX_VAL(min)
|
||||
TIMEX_VAL(hour)
|
||||
TIMEX_VAL(mday)
|
||||
TIMEX_VAL(mon)
|
||||
TIMEX_VAL(year)
|
||||
t.tm_year-=1900;
|
||||
TIMEX_VAL(isdst)
|
||||
|
||||
time_t unixtime = timefunc(&t);
|
||||
if (unixtime==(time_t)-1)
|
||||
{
|
||||
lua_pushnil(L);
|
||||
}
|
||||
else
|
||||
lua_pushlint(L,unixtime);
|
||||
}
|
||||
static int luacall_timelocal(lua_State *L)
|
||||
{
|
||||
// timelocal(tm)
|
||||
lua_check_argc(L,"timelocal",1);
|
||||
lua_timex(L, mktime);
|
||||
return 1;
|
||||
}
|
||||
static int luacall_timegm(lua_State *L)
|
||||
{
|
||||
// timegm(tm)
|
||||
lua_check_argc(L,"timegm",1);
|
||||
lua_timex(L, timegm);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// ----------------------------------------
|
||||
|
||||
void lua_cleanup(lua_State *L)
|
||||
@@ -3649,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");
|
||||
@@ -3800,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);
|
||||
@@ -3818,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]=='@')
|
||||
@@ -4258,7 +4432,13 @@ static void lua_init_functions(void)
|
||||
{"gzip_deflate",luacall_gzip_deflate},
|
||||
|
||||
// stat() - file size, mod time
|
||||
{"stat",luacall_stat}
|
||||
{"stat",luacall_stat},
|
||||
|
||||
// time
|
||||
{"localtime",luacall_localtime},
|
||||
{"gmtime",luacall_gmtime},
|
||||
{"timelocal",luacall_timelocal},
|
||||
{"timegm",luacall_timegm}
|
||||
};
|
||||
for(int i=0;i<(sizeof(lfunc)/sizeof(*lfunc));i++)
|
||||
lua_register(params.L,lfunc[i].name,lfunc[i].f);
|
||||
|
||||
286
nfq2/nfqws.c
286
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));
|
||||
@@ -156,6 +162,40 @@ static uint8_t processPacketData(uint32_t *mark, const char *ifin, const char *i
|
||||
return dpi_desync_packet(*mark, ifin, ifout, data_pkt, len_pkt, mod_pkt, len_mod_pkt);
|
||||
}
|
||||
|
||||
#define FUZZ_MAX_PACKET_SIZE (RECONSTRUCT_MAX_SIZE+4096)
|
||||
static void fuzzPacketData(unsigned int count)
|
||||
{
|
||||
uint8_t *packet,mod[RECONSTRUCT_MAX_SIZE+4096];
|
||||
size_t len, modlen;
|
||||
unsigned int k;
|
||||
uint32_t mark=0;
|
||||
uint8_t verdict;
|
||||
|
||||
for(k=0;k<count;k++)
|
||||
{
|
||||
if (bQuit) break;
|
||||
if (!(k%1000)) DLOG_CONDUP("fuzz ct=%u\n",k);
|
||||
len = random()%(FUZZ_MAX_PACKET_SIZE+1);
|
||||
if (!(packet = malloc(len))) return; // alloc every time to catch uninitialized reads
|
||||
fill_random_bytes(packet,len);
|
||||
if (len)
|
||||
{
|
||||
// simulate ipv4 or ipv6 and invalid packet with low probability
|
||||
*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);
|
||||
free(packet);
|
||||
}
|
||||
}
|
||||
static void do_fuzz(void)
|
||||
{
|
||||
if (params.fuzz)
|
||||
{
|
||||
DLOG_CONDUP("fuzz packet data count=%u\n",params.fuzz);
|
||||
fuzzPacketData(params.fuzz);
|
||||
}
|
||||
}
|
||||
|
||||
static bool test_list_files()
|
||||
{
|
||||
@@ -201,48 +241,61 @@ 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)
|
||||
{
|
||||
int id, ilen;
|
||||
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;
|
||||
struct nfq_cb_data *cbdata = (struct nfq_cb_data*)cookie;
|
||||
uint32_t mark;
|
||||
uint8_t mod[RECONSTRUCT_MAX_SIZE] __attribute__((aligned(16)));
|
||||
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)
|
||||
{
|
||||
len = ilen;
|
||||
modlen = sizeof(mod);
|
||||
modlen = RECONSTRUCT_MAX_SIZE;
|
||||
// there's no space to grow packet in recv blob from nfqueue. it can contain multiple packets with no extra buffer length for modifications.
|
||||
// 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);
|
||||
@@ -266,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)
|
||||
static bool nfq_init(struct nfq_handle **h, struct nfq_q_handle **qh, struct nfq_cb_data *cbdata)
|
||||
{
|
||||
nfq_deinit(h, qh);
|
||||
|
||||
@@ -277,26 +330,33 @@ static bool nfq_init(struct nfq_handle **h, struct nfq_q_handle **qh)
|
||||
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, ¶ms);
|
||||
*qh = nfq_create_queue(*h, params.qnum, &nfq_cb, cbdata);
|
||||
if (!*qh) {
|
||||
DLOG_PERROR("nfq_create_queue()");
|
||||
goto exiterr;
|
||||
@@ -315,9 +375,15 @@ static bool nfq_init(struct nfq_handle **h, struct nfq_q_handle **qh)
|
||||
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
|
||||
@@ -340,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;
|
||||
@@ -347,7 +415,8 @@ static int nfq_main(void)
|
||||
int res, fd, e;
|
||||
ssize_t rd;
|
||||
FILE *Fpid = NULL;
|
||||
uint8_t buf[RECONSTRUCT_MAX_SIZE] __attribute__((aligned(16)));
|
||||
uint8_t *buf=NULL, *mod=NULL;
|
||||
struct nfq_cb_data cbdata = { .sock = -1, .mod = NULL };
|
||||
|
||||
if (*params.pidfile && !(Fpid = fopen(params.pidfile, "w")))
|
||||
{
|
||||
@@ -381,13 +450,27 @@ static int nfq_main(void)
|
||||
if (!lua_init())
|
||||
goto err;
|
||||
|
||||
do_fuzz();
|
||||
|
||||
if (!params.intercept)
|
||||
{
|
||||
DLOG("no intercept quit\n");
|
||||
DLOG_CONDUP("no intercept quit\n");
|
||||
goto exok;
|
||||
}
|
||||
|
||||
if (!nfq_init(&h, &qh))
|
||||
if (!(buf = malloc(NFQ_MAX_RECV_SIZE)) || !(cbdata.mod = malloc(RECONSTRUCT_MAX_SIZE)))
|
||||
{
|
||||
DLOG_ERR("out of memory\n");
|
||||
goto err;
|
||||
}
|
||||
|
||||
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
|
||||
@@ -410,9 +493,14 @@ static int nfq_main(void)
|
||||
fd = nfq_fd(h);
|
||||
do
|
||||
{
|
||||
while ((rd = recv(fd, buf, sizeof(buf), 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
|
||||
@@ -420,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;
|
||||
@@ -443,9 +521,19 @@ 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:
|
||||
if (Fpid) fclose(Fpid);
|
||||
if (cbdata.sock>=0) close(cbdata.sock);
|
||||
free(cbdata.mod);
|
||||
free(buf);
|
||||
nfq_deinit(&h, &qh);
|
||||
lua_shutdown();
|
||||
#ifdef HAS_FILTER_SSID
|
||||
@@ -453,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)
|
||||
@@ -548,6 +629,8 @@ static int dvt_main(void)
|
||||
if (!lua_init())
|
||||
goto exiterr;
|
||||
|
||||
do_fuzz();
|
||||
|
||||
if (!params.intercept)
|
||||
{
|
||||
DLOG("no intercept quit\n");
|
||||
@@ -559,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);
|
||||
@@ -578,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)
|
||||
@@ -737,6 +826,8 @@ static int win_main()
|
||||
res=ERROR_INVALID_PARAMETER; goto ex;
|
||||
}
|
||||
|
||||
do_fuzz();
|
||||
|
||||
if (!params.intercept)
|
||||
{
|
||||
DLOG("no intercept quit\n");
|
||||
@@ -756,7 +847,8 @@ static int win_main()
|
||||
}
|
||||
else if (errno == ENODEV)
|
||||
{
|
||||
DLOG_CONDUP("logical network disappeared. deinitializing windivert.\n");
|
||||
DLOG_CONDUP("\nlogical network disappeared. deinitializing windivert.\n");
|
||||
rawsend_cleanup();
|
||||
break;
|
||||
}
|
||||
else if (errno == EINTR)
|
||||
@@ -1057,7 +1149,7 @@ static bool parse_l7_list(char *opt, uint64_t *l7)
|
||||
break;
|
||||
}
|
||||
else
|
||||
*l7 |= 1<<proto;
|
||||
*l7 |= 1ULL<<proto;
|
||||
|
||||
if (e) *e++ = c;
|
||||
p = e;
|
||||
@@ -1085,7 +1177,7 @@ static bool parse_l7p_list(char *opt, uint64_t *l7p)
|
||||
break;
|
||||
}
|
||||
else
|
||||
*l7p |= 1<<payload;
|
||||
*l7p |= 1ULL<<payload;
|
||||
|
||||
if (e) *e++ = c;
|
||||
p = e;
|
||||
@@ -1193,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;
|
||||
@@ -1339,7 +1431,7 @@ static void LuaDesyncDebug(struct desync_profile *dp, const char *entity)
|
||||
if (func->payload_type)
|
||||
{
|
||||
for(i=0;i<L7P_LAST;i++)
|
||||
if (func->payload_type & (1<<i))
|
||||
if (func->payload_type & (1ULL<<i))
|
||||
DLOG(" %s", l7payload_str(i));
|
||||
}
|
||||
else
|
||||
@@ -1608,7 +1700,7 @@ static void exithelp(void)
|
||||
*all_protos=0;
|
||||
for (t_l7proto pr=0 ; pr<L7_LAST; pr++)
|
||||
{
|
||||
if (pr) strncat(all_protos, " ", sizeof(all_protos)-1-1);
|
||||
if (pr) strncat(all_protos, " ", sizeof(all_protos)-strlen(all_protos)-1);
|
||||
strncat(all_protos, l7proto_str(pr), sizeof(all_protos)-strlen(all_protos)-1);
|
||||
}
|
||||
|
||||
@@ -1631,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"
|
||||
@@ -1681,7 +1774,7 @@ static void exithelp(void)
|
||||
" --lua-init=@<filename>|<lua_text>\t\t\t; load LUA program from a file or string. if multiple parameters present order of execution is preserved. gzipped files are supported.\n"
|
||||
" --lua-gc=<int>\t\t\t\t\t\t; forced garbage collection every N sec. default %u sec. triggers only when a packet arrives. 0 = disable.\n"
|
||||
"\nMULTI-STRATEGY:\n"
|
||||
" --new[=<name>]\t\t\t\t\t\t\t; begin new profile. optionally set name\n"
|
||||
" --new[=<name>]\t\t\t\t\t\t; begin new profile. optionally set name\n"
|
||||
" --skip\t\t\t\t\t\t\t; do not use this profile\n"
|
||||
" --name=<name>\t\t\t\t\t\t; set profile name\n"
|
||||
" --template[=<name>]\t\t\t\t\t; use this profile as template (must be named or will be useless)\n"
|
||||
@@ -1783,6 +1876,7 @@ enum opt_indices {
|
||||
IDX_DEBUG,
|
||||
IDX_DRY_RUN,
|
||||
IDX_INTERCEPT,
|
||||
IDX_FUZZ,
|
||||
IDX_VERSION,
|
||||
IDX_COMMENT,
|
||||
#ifdef __linux__
|
||||
@@ -1793,6 +1887,7 @@ enum opt_indices {
|
||||
IDX_PORT,
|
||||
#endif
|
||||
IDX_DAEMON,
|
||||
IDX_CHDIR,
|
||||
IDX_PIDFILE,
|
||||
#ifndef __CYGWIN__
|
||||
IDX_USER,
|
||||
@@ -1886,6 +1981,7 @@ static const struct option long_options[] = {
|
||||
[IDX_DEBUG] = {"debug", optional_argument, 0, 0},
|
||||
[IDX_DRY_RUN] = {"dry-run", no_argument, 0, 0},
|
||||
[IDX_INTERCEPT] = {"intercept", optional_argument, 0, 0},
|
||||
[IDX_FUZZ] = {"fuzz", required_argument, 0, 0},
|
||||
[IDX_VERSION] = {"version", no_argument, 0, 0},
|
||||
[IDX_COMMENT] = {"comment", optional_argument, 0, 0},
|
||||
#ifdef __linux__
|
||||
@@ -1896,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},
|
||||
@@ -2054,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
|
||||
@@ -2113,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)
|
||||
{
|
||||
@@ -2161,6 +2261,10 @@ int main(int argc, char **argv)
|
||||
case IDX_INTERCEPT:
|
||||
params.intercept = !optarg || atoi(optarg);
|
||||
break;
|
||||
case IDX_FUZZ:
|
||||
params.fuzz = atoi(optarg);
|
||||
params.intercept = false;
|
||||
break;
|
||||
case IDX_VERSION:
|
||||
exit_clean(0);
|
||||
break;
|
||||
@@ -2197,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:
|
||||
@@ -2302,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;
|
||||
@@ -2314,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:
|
||||
@@ -2399,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");
|
||||
@@ -2408,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");
|
||||
@@ -2417,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");
|
||||
@@ -2447,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);
|
||||
@@ -532,14 +532,15 @@ bool alloc_windivert_portfilters(struct params_s *params)
|
||||
¶ms->wf_ipf_in, ¶ms->wf_ipf_out};
|
||||
for (int i=0 ; i<(sizeof(wdbufs)/sizeof(*wdbufs)) ; i++)
|
||||
{
|
||||
if (!(*wdbufs[i] = malloc(WINDIVERT_PORTFILTER_MAX)))
|
||||
return false;
|
||||
if (!(*wdbufs[i] = malloc(WINDIVERT_PORTFILTER_MAX))) goto err;
|
||||
**wdbufs[i] = 0;
|
||||
}
|
||||
if (!(params->wf_raw_filter = malloc(WINDIVERT_MAX)))
|
||||
return false;
|
||||
if (!(params->wf_raw_filter = malloc(WINDIVERT_MAX))) goto err;
|
||||
*params->wf_raw_filter = 0;
|
||||
return true;
|
||||
err:
|
||||
cleanup_windivert_portfilters(params);
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
void cleanup_params(struct params_s *params)
|
||||
@@ -593,7 +594,7 @@ void init_params(struct params_s *params)
|
||||
LIST_INIT(¶ms->blobs);
|
||||
LIST_INIT(¶ms->lua_init_scripts);
|
||||
|
||||
params->reasm_payload_disable = params->payload_disable = 1<<L7P_NONE;
|
||||
params->reasm_payload_disable = params->payload_disable = 1ULL<<L7P_NONE;
|
||||
|
||||
#ifdef __CYGWIN__
|
||||
LIST_INIT(¶ms->ssid_filter);
|
||||
@@ -607,5 +608,4 @@ void init_params(struct params_s *params)
|
||||
params->droproot = true;
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
@@ -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
|
||||
@@ -133,6 +134,7 @@ struct params_s
|
||||
bool debug;
|
||||
|
||||
bool daemon, intercept;
|
||||
unsigned int fuzz;
|
||||
|
||||
#ifdef __linux__
|
||||
int qnum;
|
||||
|
||||
45
nfq2/pools.c
45
nfq2/pools.c
@@ -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)
|
||||
{
|
||||
@@ -524,10 +523,15 @@ struct kavl_bit_elem *kavl_bit_get(const struct kavl_bit_elem *hdr, const void *
|
||||
|
||||
static bool ipset_kavl_add(struct kavl_bit_elem **ipset, const void *a, uint8_t preflen)
|
||||
{
|
||||
uint8_t bytelen = (preflen+7)>>3;
|
||||
uint8_t *abuf = malloc(bytelen);
|
||||
if (!abuf) return false;
|
||||
memcpy(abuf,a,bytelen);
|
||||
uint8_t *abuf, bytelen = (preflen+7)>>3;
|
||||
if (bytelen)
|
||||
{
|
||||
abuf = malloc(bytelen);
|
||||
if (!abuf) return false;
|
||||
memcpy(abuf,a,bytelen);
|
||||
}
|
||||
else
|
||||
abuf = NULL;
|
||||
if (!kavl_bit_add(ipset,abuf,preflen,0))
|
||||
{
|
||||
free(abuf);
|
||||
@@ -912,12 +916,15 @@ struct blob_item *blob_collection_add_blob(struct blob_collection_head *head, co
|
||||
{
|
||||
struct blob_item *entry = calloc(1,sizeof(struct blob_item));
|
||||
if (!entry) return NULL;
|
||||
if (!(entry->data = malloc(size+size_reserve)))
|
||||
if (size+size_reserve)
|
||||
{
|
||||
free(entry);
|
||||
return NULL;
|
||||
if (!(entry->data = malloc(size+size_reserve)))
|
||||
{
|
||||
free(entry);
|
||||
return NULL;
|
||||
}
|
||||
if (data) memcpy(entry->data,data,size);
|
||||
}
|
||||
if (data) memcpy(entry->data,data,size);
|
||||
entry->size = size;
|
||||
entry->size_buf = size+size_reserve;
|
||||
|
||||
@@ -1025,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;
|
||||
|
||||
@@ -1083,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;
|
||||
|
||||
@@ -1107,6 +1114,22 @@ void ipcachePrint(ip_cache *ipcache)
|
||||
ipcache6Print(ipcache->ipcache6);
|
||||
}
|
||||
|
||||
ip_cache_item *ipcacheFind(ip_cache *ipcache, const struct in_addr *a4, const struct in6_addr *a6, const char *iface)
|
||||
{
|
||||
ip_cache4 *ipcache4;
|
||||
ip_cache6 *ipcache6;
|
||||
if (a4)
|
||||
{
|
||||
if ((ipcache4 = ipcache4Find(ipcache->ipcache4,a4,iface)))
|
||||
return &ipcache4->data;
|
||||
}
|
||||
else if (a6)
|
||||
{
|
||||
if ((ipcache6 = ipcache6Find(ipcache->ipcache6,a6,iface)))
|
||||
return &ipcache6->data;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
ip_cache_item *ipcacheTouch(ip_cache *ipcache, const struct in_addr *a4, const struct in6_addr *a6, const char *iface)
|
||||
{
|
||||
ip_cache4 *ipcache4;
|
||||
|
||||
@@ -265,6 +265,7 @@ typedef struct ip_cache
|
||||
} ip_cache;
|
||||
|
||||
ip_cache_item *ipcacheTouch(ip_cache *ipcache, const struct in_addr *a4, const struct in6_addr *a6, const char *iface);
|
||||
ip_cache_item *ipcacheFind(ip_cache *ipcache, const struct in_addr *a4, const struct in6_addr *a6, const char *iface);
|
||||
void ipcachePurgeRateLimited(ip_cache *ipcache, time_t lifetime);
|
||||
void ipcacheDestroy(ip_cache *ipcache);
|
||||
void ipcachePrint(ip_cache *ipcache);
|
||||
|
||||
144
nfq2/protocol.c
144
nfq2/protocol.c
@@ -17,12 +17,15 @@ static bool FindNLD(const uint8_t *dom, size_t dlen, int level, const uint8_t **
|
||||
{
|
||||
int i;
|
||||
const uint8_t *p1,*p2;
|
||||
|
||||
if (level<1) return false;
|
||||
for (i=1,p2=dom+dlen;i<level;i++)
|
||||
{
|
||||
for (p2--; p2>dom && *p2!='.'; p2--);
|
||||
if (p2<=dom) return false;
|
||||
}
|
||||
for (p1=p2-1 ; p1>dom && *p1!='.'; p1--);
|
||||
if (p1<dom) return false;
|
||||
if (*p1=='.') p1++;
|
||||
if (p) *p = p1;
|
||||
if (len) *len = p2-p1;
|
||||
@@ -30,7 +33,7 @@ static bool FindNLD(const uint8_t *dom, size_t dlen, int level, const uint8_t **
|
||||
}
|
||||
|
||||
static const char *l7proto_name[] = {
|
||||
"all","unknown","known","http","tls","dtls","quic","wireguard","dht","discord","stun","xmpp","dns","mtproto"
|
||||
"all","unknown","known","http","tls","dtls","quic","wireguard","dht","discord","stun","xmpp","dns","mtproto","bt","utp_bt"
|
||||
};
|
||||
const char *l7proto_str(t_l7proto l7)
|
||||
{
|
||||
@@ -44,7 +47,7 @@ t_l7proto l7proto_from_name(const char *name)
|
||||
}
|
||||
bool l7_proto_match(t_l7proto l7proto, uint64_t filter_l7)
|
||||
{
|
||||
return filter_l7==L7_ALL || (filter_l7 & (1<<l7proto)) || (filter_l7 & (1<<L7_KNOWN)) && l7proto>L7_KNOWN && l7proto<L7_LAST;
|
||||
return filter_l7==L7_ALL || (filter_l7 & (1ULL<<l7proto)) || (filter_l7 & (1ULL<<L7_KNOWN)) && l7proto>L7_KNOWN && l7proto<L7_LAST;
|
||||
}
|
||||
|
||||
static const char *l7payload_name[] = {
|
||||
@@ -58,7 +61,9 @@ static const char *l7payload_name[] = {
|
||||
"dht","discord_ip_discovery","stun",
|
||||
"xmpp_stream", "xmpp_starttls", "xmpp_proceed", "xmpp_features",
|
||||
"dns_query", "dns_response",
|
||||
"mtproto_initial"};
|
||||
"mtproto_initial",
|
||||
"bt_handshake", "utp_bt_handshake"
|
||||
};
|
||||
t_l7payload l7payload_from_name(const char *name)
|
||||
{
|
||||
int idx = str_index(l7payload_name,sizeof(l7payload_name)/sizeof(*l7payload_name),name);
|
||||
@@ -71,7 +76,7 @@ const char *l7payload_str(t_l7payload l7)
|
||||
}
|
||||
bool l7_payload_match(t_l7payload l7payload, uint64_t filter_l7p)
|
||||
{
|
||||
return filter_l7p==L7P_ALL || (filter_l7p & (1<<l7payload)) || (filter_l7p & (1<<L7P_KNOWN)) && l7payload>L7P_KNOWN && l7payload<L7P_LAST;
|
||||
return filter_l7p==L7P_ALL || (filter_l7p & (1ULL<<l7payload)) || (filter_l7p & (1ULL<<L7P_KNOWN)) && l7payload>L7P_KNOWN && l7payload<L7P_LAST;
|
||||
}
|
||||
bool l7_payload_str_list(uint64_t l7p, char *buf, size_t size)
|
||||
{
|
||||
@@ -89,7 +94,7 @@ bool l7_payload_str_list(uint64_t l7p, char *buf, size_t size)
|
||||
}
|
||||
for(pl=0, p=buf, e=p+size, *buf=0 ; pl<L7P_LAST ; pl++)
|
||||
{
|
||||
if (l7p & (1<<pl))
|
||||
if (l7p & (1ULL<<pl))
|
||||
{
|
||||
pstr = l7payload_str(pl);
|
||||
lstr = strlen(pstr);
|
||||
@@ -140,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)
|
||||
{
|
||||
@@ -244,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;
|
||||
@@ -327,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');
|
||||
}
|
||||
@@ -366,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;
|
||||
|
||||
@@ -413,7 +417,7 @@ ssize_t HttpPos(t_marker posmarker, int16_t pos, const uint8_t *data, size_t sz)
|
||||
if (*method=='\n' || *method=='\r') method++;
|
||||
if (*method=='\n' || *method=='\r') method++;
|
||||
// max length is PROPPATCH
|
||||
for (p=method,i=0;i<9;i++) if (*p>='A' && *p<='Z') p++;
|
||||
for (p=method,i=0; i<9 && *p>='A' && *p<='Z'; i++,p++);
|
||||
if (i<3 || *p!=' ') break;
|
||||
return CheckPos(sz,method-data+pos);
|
||||
case PM_HOST:
|
||||
@@ -444,6 +448,7 @@ const char *TLSVersionStr(uint16_t tlsver)
|
||||
{
|
||||
switch(tlsver)
|
||||
{
|
||||
case 0x0300: return "SSL 3.0";
|
||||
case 0x0301: return "TLS 1.0";
|
||||
case 0x0302: return "TLS 1.1";
|
||||
case 0x0303: return "TLS 1.2";
|
||||
@@ -545,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;
|
||||
@@ -556,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;
|
||||
@@ -640,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)
|
||||
{
|
||||
@@ -1185,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;
|
||||
|
||||
@@ -1215,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;
|
||||
@@ -1243,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
|
||||
@@ -1256,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)
|
||||
{
|
||||
@@ -1278,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
|
||||
@@ -1304,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;
|
||||
@@ -1328,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;
|
||||
|
||||
@@ -1343,11 +1375,14 @@ 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];
|
||||
|
||||
// token length
|
||||
if (offset>=len || (offset + tvb_get_size(data[offset])) > len) return false;
|
||||
offset += tvb_get_varint(data + offset, &sz);
|
||||
offset += sz;
|
||||
if (offset >= len) return false;
|
||||
@@ -1437,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")))
|
||||
@@ -1452,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);
|
||||
@@ -1484,3 +1519,14 @@ bool IsDTLSServerHello(const uint8_t *data, size_t len)
|
||||
{
|
||||
return IsDTLS(data,len) && data[0]==0x16 && data[13]==2;
|
||||
}
|
||||
|
||||
bool IsBTHandshake(const uint8_t *data, size_t len)
|
||||
{
|
||||
// len, pstrlen, reserved, sha1, peer id
|
||||
return len>=(1+19+8+20+20) && !memcmp(data,"\x13" "BitTorrent protocol",20);
|
||||
}
|
||||
bool IsUTP_BTHandshake(const uint8_t *data, size_t len)
|
||||
{
|
||||
// len, pstrlen, reserved, sha1, peer id
|
||||
return len>=(20+1+19+8+20+20) && data[0]==0x01 && !memcmp(data+20,"\x13" "BitTorrent protocol",20);;
|
||||
}
|
||||
|
||||
@@ -20,6 +20,8 @@ typedef enum {
|
||||
L7_XMPP,
|
||||
L7_DNS,
|
||||
L7_MTPROTO,
|
||||
L7_BT,
|
||||
L7_UTP_BT,
|
||||
L7_LAST, L7_INVALID=L7_LAST, L7_NONE=L7_LAST
|
||||
} t_l7proto;
|
||||
const char *l7proto_str(t_l7proto l7);
|
||||
@@ -56,6 +58,8 @@ typedef enum {
|
||||
L7P_DNS_QUERY,
|
||||
L7P_DNS_RESPONSE,
|
||||
L7P_MTPROTO_INITIAL,
|
||||
L7P_BT_HANDSHAKE,
|
||||
L7P_UTP_BT_HANDSHAKE,
|
||||
L7P_LAST, L7P_INVALID=L7P_LAST, L7P_NONE=L7P_LAST
|
||||
} t_l7payload;
|
||||
t_l7payload l7payload_from_name(const char *name);
|
||||
@@ -100,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);
|
||||
|
||||
@@ -160,7 +164,8 @@ bool IsMTProto(const uint8_t *data, size_t len);
|
||||
bool IsDTLS(const uint8_t *data, size_t len);
|
||||
bool IsDTLSClientHello(const uint8_t *data, size_t len);
|
||||
bool IsDTLSServerHello(const uint8_t *data, size_t len);
|
||||
|
||||
bool IsBTHandshake(const uint8_t *data, size_t len);
|
||||
bool IsUTP_BTHandshake(const uint8_t *data, size_t len);
|
||||
|
||||
#define QUIC_MAX_CID_LENGTH 20
|
||||
typedef struct quic_cid {
|
||||
|
||||
69
nfq2/sec.c
69
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 ************/
|
||||
|
||||
@@ -210,10 +210,10 @@ int getmaxcap(void)
|
||||
}
|
||||
bool dropcaps(void)
|
||||
{
|
||||
uint64_t caps = (1<<CAP_NET_ADMIN)|(1<<CAP_NET_RAW);
|
||||
uint64_t caps = (1ULL<<CAP_NET_ADMIN)|(1ULL<<CAP_NET_RAW);
|
||||
int maxcap = getmaxcap();
|
||||
|
||||
if (setpcap(caps|(1<<CAP_SETPCAP)))
|
||||
if (setpcap(caps|(1ULL<<CAP_SETPCAP)))
|
||||
{
|
||||
for (int cap = 0; cap <= maxcap; cap++)
|
||||
{
|
||||
@@ -249,7 +249,7 @@ bool can_drop_root(void)
|
||||
{
|
||||
#ifdef __linux__
|
||||
// has some caps
|
||||
return checkpcap((1<<CAP_SETUID)|(1<<CAP_SETGID));
|
||||
return checkpcap((1ULL<<CAP_SETUID)|(1ULL<<CAP_SETGID));
|
||||
#else
|
||||
// effective root
|
||||
return !geteuid();
|
||||
@@ -327,37 +327,66 @@ void daemonize(void)
|
||||
int pid;
|
||||
char cwd[PATH_MAX];
|
||||
|
||||
if (!getcwd(cwd, sizeof(cwd))) *cwd=0;
|
||||
if (!getcwd(cwd, sizeof(cwd)))
|
||||
{
|
||||
DLOG_PERROR("getcwd");
|
||||
*cwd=0;
|
||||
}
|
||||
|
||||
pid = fork();
|
||||
if (pid == -1)
|
||||
{
|
||||
DLOG_PERROR("fork");
|
||||
exit(2);
|
||||
exit(20);
|
||||
}
|
||||
else if (pid != 0)
|
||||
exit(0);
|
||||
|
||||
if (*cwd)
|
||||
{
|
||||
int res = chdir(cwd);
|
||||
}
|
||||
if (*cwd && chdir(cwd)<0)
|
||||
DLOG_PERROR("chdir");
|
||||
|
||||
if (setsid() == -1)
|
||||
exit(2);
|
||||
if (chdir("/") == -1)
|
||||
exit(2);
|
||||
close(STDIN_FILENO);
|
||||
close(STDOUT_FILENO);
|
||||
close(STDERR_FILENO);
|
||||
{
|
||||
DLOG_PERROR("setsid");
|
||||
exit(21);
|
||||
}
|
||||
if (close(STDIN_FILENO)<0 && errno!=EBADF)
|
||||
{
|
||||
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 */
|
||||
open("/dev/null", O_RDWR);
|
||||
int fd;
|
||||
/* stdin */
|
||||
fd = dup(0);
|
||||
if (open("/dev/null", O_RDWR)<0)
|
||||
{
|
||||
// will work only if debug not to console
|
||||
DLOG_PERROR("open(stdin)");
|
||||
exit(23);
|
||||
}
|
||||
/* stdout */
|
||||
fd = dup(0);
|
||||
if (dup(0)<0)
|
||||
{
|
||||
// will work only if debug not to console
|
||||
DLOG_PERROR("dup(stdout)");
|
||||
exit(24);
|
||||
}
|
||||
/* stderror */
|
||||
if (dup(0)<0)
|
||||
{
|
||||
// will work only if debug not to console
|
||||
DLOG_PERROR("dup(stderr)");
|
||||
exit(25);
|
||||
}
|
||||
}
|
||||
|
||||
bool writepid(const char *filename)
|
||||
|
||||
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