Template
1
0
mirror of https://github.com/bol-van/zapret2.git synced 2026-03-14 06:13:09 +00:00

68 Commits

Author SHA1 Message Date
bol-van
3c87be3cba update docs 2026-02-17 14:11:55 +03:00
bol-van
c642fb3845 builder-linux 2026-02-17 14:07:08 +03:00
bol-van
847e689bfb AI fixes 2026-02-17 09:35:09 +03:00
bol-van
287527092a remove debug message 2026-02-17 09:15:53 +03:00
bol-van
a9514f39f5 update docs 2026-02-16 20:54:18 +03:00
bol-van
4b7ff505e4 nfqws2: old kernels compat 2026-02-16 20:51:39 +03:00
bol-van
2120264e0b AI and manual fixes 2026-02-16 19:45:58 +03:00
bol-van
178bced5f3 update docs 2026-02-16 14:55:31 +03:00
bol-van
ff78968807 nfqws2: ensure old toolchains do not break 2026-02-16 12:01:08 +03:00
bol-van
e4535d2646 nfqws2: loongarch64 compile fix 2026-02-16 11:51:43 +03:00
bol-van
7c60ad3a7a AI fixes 2026-02-16 10:47:50 +03:00
bol-van
a621edf898 AI fixes 2026-02-15 09:40:54 +03:00
bol-van
2809f8d7e4 update docs 2026-02-14 18:16:57 +03:00
bol-van
97819327cd nfqws2: remember absolute paths 2026-02-14 18:10:26 +03:00
bol-van
eb9a1e9f6b nfqws2: --chdir 2026-02-14 16:08:01 +03:00
bol-van
6f6850707a zapret-lib: tls_dissect abort 2 loops if data is corrupt 2026-02-14 15:30:59 +03:00
bol-van
f702865311 AI fixes 2026-02-14 13:19:48 +03:00
bol-van
6447081a01 winws2: optimize signal handling in windivert_recv 2026-02-14 11:36:00 +03:00
bol-van
e4e513ec66 github: stronger gz and zip compression 2026-02-13 17:38:22 +03:00
bol-van
47630450bd AI fixes 2026-02-13 16:49:42 +03:00
bol-van
e4129fec63 github: upx 5.1.0 2026-02-13 13:35:55 +03:00
bol-van
f71ba91e7c remove no-unwind from makefiles 2026-02-13 10:59:24 +03:00
bol-van
59e6603b83 dont use no-unwind to prevent crashes 2026-02-13 10:34:16 +03:00
bol-van
14a061859f change toolchain, riscv64 2026-02-13 09:11:51 +03:00
bol-van
9aaa419f68 nfqws2: fix fread inf loop 2026-02-12 11:54:12 +03:00
bol-van
d5231bc4fc nfqws2: allow any size iv_len in aes_gcm 2026-02-11 15:42:23 +03:00
bol-van
35cebfba73 winws2: use -msse only for luajit 2026-02-11 14:09:55 +03:00
bol-van
811d16054b update docs 2026-02-11 14:05:29 +03:00
bol-van
a9ee072a14 github: cygwin lto 2026-02-11 14:01:24 +03:00
bol-van
1dbf5ecfe6 optimize exe size 2026-02-11 13:18:14 +03:00
bol-van
b210db168f nfqws2: bsd compile fixes 2026-02-11 13:05:45 +03:00
bol-van
5306a043d0 AI fixes 2026-02-11 11:26:20 +03:00
bol-van
b375a94036 update docs 2026-02-11 11:22:53 +03:00
bol-van
8b2bff4187 AI fixes 2026-02-11 11:03:27 +03:00
bol-van
827ab7cdcc nfqws2: optimize quit logic 2026-02-10 19:05:14 +03:00
bol-van
bfa1d8c5dd nfqws2: compile mask_from_bitcount only for windows 2026-02-10 15:59:56 +03:00
bol-van
52ea6270f4 nfqws2: update kavl 2026-02-10 15:51:50 +03:00
bol-van
0fb21856c6 nfqws2: update uthash 2026-02-10 15:47:28 +03:00
bol-van
48e4d3a6e7 init.d: optimize ipt dports 2026-02-10 12:34:47 +03:00
bol-van
6204c74993 update docs 2026-02-10 12:07:24 +03:00
bol-van
d981391120 update docs 2026-02-10 12:06:26 +03:00
bol-van
7db676e02c init.d: use bitmap:port ipset for standard dports 2026-02-10 11:33:50 +03:00
bol-van
c91cae0903 nfqws2: quit handling optimize 2026-02-09 21:06:36 +03:00
bol-van
c06712a0d5 nfqws2: optimize 2026-02-09 19:49:47 +03:00
bol-van
2e2f118e10 nfqws2: EINTR safety 2026-02-09 19:44:06 +03:00
bol-van
6638140880 zapret-auto: instances arg in condition, cond_lua 2026-02-09 17:24:11 +03:00
bol-van
41bac1833e nfqws2: remove bind to address in rawsend 2026-02-09 15:59:53 +03:00
bol-van
c3b1cc3eb9 update docs 2026-02-09 13:45:23 +03:00
bol-van
6f52fb08f9 update docs 2026-02-09 13:44:41 +03:00
bol-van
08549b570b update docs 2026-02-09 13:43:46 +03:00
bol-van
13daef5167 update docs 2026-02-09 13:39:26 +03:00
bol-van
1fd6063cd7 update docs 2026-02-09 13:38:25 +03:00
bol-van
5e4f78228e zapret-auto: per_instance_condition not execute if cond arg absent 2026-02-09 13:28:51 +03:00
bol-van
2e255ca59f zapret-auto: per_instance_condition 2026-02-09 13:19:01 +03:00
bol-van
565a8abffc AI fixes 2026-02-09 10:04:13 +03:00
bol-van
69f1576f7e AI fixes 2026-02-08 17:22:39 +03:00
bol-van
0917cb21bb AI fixes 2026-02-08 17:12:36 +03:00
bol-van
8f316ae1a2 nfqws2: AI fixes 2026-02-07 20:07:49 +03:00
bol-van
caaf5e7a2e nfqws2: DLOG_ERR payload too large 2026-02-07 14:50:54 +03:00
bol-van
dbfbd6e6d3 nfqws2: DLOG_ERR if payload does not fit into the buffer 2026-02-07 14:47:31 +03:00
bol-van
397fe60b5f update docs 2026-02-07 13:55:23 +03:00
bol-van
e096ed64bc update docs 2026-02-07 13:54:01 +03:00
bol-van
0f2def9bd5 update docs 2026-02-07 13:52:11 +03:00
bol-van
85721e4b82 update docs 2026-02-07 13:50:55 +03:00
bol-van
0fd9314df9 update docs 2026-02-07 13:49:54 +03:00
bol-van
a9e2bfe49c update docs 2026-02-07 13:48:27 +03:00
bol-van
bd7a40f5a9 nfqws2: handling of incoming frag, AI fixes 2026-02-07 13:36:31 +03:00
bol-van
bcd50f5215 zapret-tests: 64-bit time support checks 2026-02-06 17:16:40 +03:00
46 changed files with 1943 additions and 928 deletions

View File

@@ -26,32 +26,20 @@ jobs:
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
- 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,8 @@ 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
run: |
DEPS_DIR=$GITHUB_WORKSPACE/deps
export CC="$TARGET-gcc"
@@ -107,13 +97,19 @@ jobs:
export STRIP=$TARGET-strip
export PKG_CONFIG_PATH=$DEPS_DIR/lib/pkgconfig
export STAGING_DIR=$RUNNER_TEMP
if [ "$ARCH" = lexra ]; then
OPTIMIZE=-Os
else
OPTIMIZE=-Oz
fi
MINSIZE="$OPTIMIZE $MINSIZE"
if [[ "$ARCH" == lexra ]] || [[ "$ARCH" == ppc ]] || [[ "$ARCH" == x86 ]] ; then
if [[ "$ARCH" == lexra ]] || [[ "$ARCH" == ppc ]] || [[ "$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="$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
@@ -131,7 +127,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 -s -flto=auto $CFLAGS" -j$(nproc)
make BUILDMODE=static XCFLAGS=-DLUAJIT_DISABLE_FFI HOST_CC="$HOSTCC" CROSS= CC="$CC" TARGET_AR="$AR rcus" TARGET_STRIP=$STRIP TARGET_CFLAGS="$MINSIZE $CFLAGS" TARGET_LDFLAGS="$LDMINSIZE $LDFLAGS" -j$(nproc)
make install PREFIX= DESTDIR=$DEPS_DIR
)
LJIT=1
@@ -147,7 +143,8 @@ jobs:
for i in libmnl libnfnetlink libnetfilter_queue ; do
(
cd $i-*
CFLAGS="-Os -flto=auto $CFLAGS" \
CFLAGS="$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 +156,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="$MINSIZE $CFLAGS" \
./configure --prefix= --static
make install -j$(nproc) DESTDIR=$DEPS_DIR
)
@@ -170,6 +167,7 @@ jobs:
install -Dm644 -t $DEPS_DIR/include/sys /usr/include/x86_64-linux-gnu/sys/queue.h /usr/include/sys/capability.h
# zapret2
OPTIMIZE=$OPTIMIZE \
CFLAGS="-DZAPRET_GH_VER=${{ github.ref_name }} -DZAPRET_GH_HASH=${{ github.sha }} -static-libgcc -static -I$DEPS_DIR/include $CFLAGS" \
LDFLAGS="-L$DEPS_DIR/lib $LDFLAGS" \
make -C zapret2 LUA_JIT=$LJIT LUA_CFLAGS="$LCFLAGS" LUA_LIB="$LLIB" -j$(nproc)
@@ -220,6 +218,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
@@ -242,7 +242,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=-DLUAJIT_DISABLE_FFI HOST_CC="$HOSTCC" CROSS= CC="$CC" TARGET_AR="$AR rcus" TARGET_STRIP=$STRIP TARGET_CFLAGS="$MINSIZE $CFLAGS" TARGET_LDFLAGS="$LDMINSIZE $LDFLAGS" -j$(nproc)
make install PREFIX= DESTDIR=$DEPS_DIR
)
LJIT=1
@@ -258,7 +258,8 @@ jobs:
for i in libmnl libnfnetlink libnetfilter_queue ; do
(
cd $i-*
CFLAGS="-Os -flto=auto -Wno-implicit-function-declaration" \
CFLAGS="$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
)
@@ -314,12 +315,14 @@ jobs:
TARGET: ${{ matrix.target }}
ARCH: ${{ matrix.arch }}
CC: ${{ matrix.target }}-freebsd11-clang
MINSIZE: -Oz -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=-DLUAJIT_DISABLE_FFI HOST_CC=gcc CC=$CC TARGET_CFLAGS="$MINSIZE $CFLAGS" TARGET_LDFLAGS="$LDMINSIZE $LDFLAGS"
make install PREFIX= DESTDIR=$DEPS_DIR
)
@@ -390,7 +393,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 +427,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_DISABLE_FFI -ffat-lto-objects" TARGET_CFLAGS="$MINSIZE $CFLAGS" TARGET_LDFLAGS="$LDMINSIZE $LDFLAGS" &&
make -C luajit2-${LUAJIT_RELEASE} install
- name: Build winws
@@ -488,7 +493,7 @@ jobs:
uses: crazy-max/ghaction-upx@v3
with:
install-only: true
version: v4.2.4
version: v5.1.0
- name: Prepare binaries
shell: bash
@@ -532,6 +537,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 +552,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 +561,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

View File

@@ -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

View File

@@ -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()

View File

@@ -3,7 +3,6 @@ nft_connbytes="ct original packets"
# required for : nft -f -
create_dev_stdin
std_ports
nft_create_table()
{

View File

@@ -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,16 +215,40 @@ v0.8.1
* winws2: use windivert bulk mode
* nfqws2: template free import
0.9.1
v0.9.1
* nfqws2: 'stat', 'clock_getfloattime' luacalls
* nfqws2: bcryptorandom normalize behavior when system entropy is low. prevent blocks
* nfqws2: --new[=name]
* winws2: fix not setting signal handlers
0.9.2
v0.9.2
nfqws2: bt and utp_bt protocol detectors
nfqws2: localtime,gmtime,timelocal,timegm luacalls
winws2: load wlanapi.dll dynamically only if needed
winws2: fixed lost windivert deinit on logical network disappear
* nfqws2: bt and utp_bt protocol detectors
* nfqws2: localtime,gmtime,timelocal,timegm luacalls
* winws2: load wlanapi.dll dynamically only if needed
* winws2: fixed lost windivert deinit on logical network disappear
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.5
* builder_linux: simple scripts to build static linux bins for any supported architecture

View File

@@ -3,6 +3,20 @@ 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
linux static :
need any x86_64 classic linux distribution with curl, unzip, make, gcc, gcc-multilib
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
optionally review "common.inc" for Lua and LuaJIT versions
FreeBSD :
pkg install pkgconf

View File

@@ -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.

View File

@@ -0,0 +1,100 @@
#!/bin/bash
EXEDIR="$(dirname "$0")"
EXEDIR="$(cd "$EXEDIR"; pwd)"
. "$EXEDIR/common.inc"
dl_deps()
{
if [ -d "$DEPS" ]; then
dir_is_not_empty "$DEPS" && {
echo "deps dir is not empty. if you want to redownload - delete it."
return
}
else
mkdir "$DEPS"
fi
pushd "$DEPS"
curl -Lo - https://www.netfilter.org/pub/libnfnetlink/libnfnetlink-1.0.2.tar.bz2 | tar -xj
curl -Lo - https://www.netfilter.org/pub/libmnl/libmnl-1.0.5.tar.bz2 | tar -xj
curl -Lo - https://www.netfilter.org/pub/libnetfilter_queue/libnetfilter_queue-1.0.5.tar.bz2 | tar -xj
curl -Lo - https://zlib.net/zlib-1.3.1.tar.gz | tar -xz
curl -Lo - https://github.com/openresty/luajit2/archive/refs/tags/v${LUAJIT_RELEASE}.tar.gz | tar -xz
curl -Lo - https://www.lua.org/ftp/lua-${LUA_RELEASE}.tar.gz | tar -xz
popd
}
build_netlink()
{
for i in libmnl libnfnetlink libnetfilter_queue ; do
(
cd $i-*
[ -f "Makefile" ] && make clean
CFLAGS="$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="$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="$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()
{
(
cd luajit2-*
make clean
make BUILDMODE=static XCFLAGS=-DLUAJIT_DISABLE_FFI HOST_CC="$HOST_CC" CROSS= CC="$CC" TARGET_AR="$AR rcus" TARGET_STRIP=$STRIP TARGET_CFLAGS="$MINSIZE $CFLAGS" TARGET_LDFLAGS="$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
}
}
dl_deps
check_toolchains
ask_target
for t in $TGT; do
buildenv $t
pushd "$DEPS"
bsd_files
build_netlink
build_zlib
build_lua
build_luajit_for_target $t
popd
buildenv_clear
done

View File

@@ -0,0 +1,107 @@
#!/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
pushd "$ZBASE"
curl -Lo /tmp/zapret2.zip "$ZURL"
unzip /tmp/zapret2.zip
rm /tmp/zapret2.zip
mv zapret2-${BRANCH} $ZDIR
popd
}
translate_target()
{
case $1 in
aarch64-unknown-linux-musl)
ZBINTARGET=linux-arm64
;;
arm-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
}
dl_zapret2
check_toolchains
ask_target
[ -d "$ZBIN" ] || mkdir -p "$ZBIN"
for t in $TGT; do
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_LUAVER}"
}
OPTIMIZE=-Oz \
CFLAGS="-static-libgcc -static -I$STAGING_DIR/include $CFLAGS" \
LDFLAGS="-L$DEPS_DIR/lib $LDFLAGS" \
make 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

View File

@@ -0,0 +1,170 @@
EXEDIR="$(dirname "$0")"
EXEDIR="$(cd "$EXEDIR"; pwd)"
TOOLCHAINS="$EXEDIR/toolchain"
DEPS="$EXEDIR/deps"
STAGE="$EXEDIR/staging"
MINSIZE="-Oz -flto=auto -ffunction-sections -fdata-sections"
LDMINSIZE="-Wl,--gc-sections -flto=auto"
CFLAGS=""
LDFLAGS="-lgcc_eh"
HOSTCC=cc
LUA_VER="5.5"
LUA_RELEASE="5.5.0"
LUAJIT_VER="2.1"
LUAJIT_RELEASE="2.1-20250826"
LUAJIT_LUAVER="5.1"
nproc=$(nproc)
TARGETS="\
aarch64-unknown-linux-musl \
arm-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| \
arm-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
}
bsd_files()
{
install -Dm644 -t $STAGING_DIR/include/sys /usr/include/x86_64-linux-gnu/sys/queue.h /usr/include/sys/capability.h
}
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"
}
buildenv_clear()
{
export PATH="$OLDPATH" TARGET= CC= LD= AR= NM= STRIP= STAGING_DIR= PKG_CONFIG_PATH=
OLDPATH=
}
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
}
}

View File

@@ -0,0 +1,19 @@
#!/bin/bash
EXEDIR="$(dirname "$0")"
EXEDIR="$(cd "$EXEDIR"; pwd)"
. "$EXEDIR/common.inc"
BASEURL=https://github.com/bol-van/musl-cross/releases/download/latest
[ -d "$TOOLCHAINS" ] || mkdir -p "$TOOLCHAINS"
ask_target 1
pushd "$TOOLCHAINS"
for t in $TGT; do
[ -d "$t" ] && rm -r "$t"
curl -Lo - "${BASEURL}/${t}.tar.xz" | tar -Jx
done
popd

View File

@@ -59,21 +59,21 @@
- [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)
@@ -82,23 +82,23 @@
- [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)
@@ -106,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)
@@ -123,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)
@@ -143,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)
@@ -175,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)
@@ -198,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)
@@ -247,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)
@@ -634,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
@@ -1390,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 |
@@ -2098,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.
@@ -2327,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**
@@ -3562,10 +3570,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
@@ -3579,10 +3587,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
@@ -4380,13 +4388,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)
@@ -4438,6 +4459,22 @@ 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 "code" argument. The code returns condition value. Direct addressing of the desync table is possible within the code.
# Auxiliary programs
@@ -5167,6 +5204,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
```

View File

@@ -56,21 +56,21 @@
- [Генерация случайных данных](#генерация-случайных-данных)
- [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)
@@ -79,23 +79,23 @@
- [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)
@@ -103,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)
@@ -120,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)
- [Операции с именами файлов и путями](#операции-с-именами-файлов-и-путями)
- [Чтение и запись файлов](#чтение-и-запись-файлов)
- [Компрессия данных](#компрессия-данных)
@@ -140,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)
@@ -172,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)
@@ -195,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)
@@ -244,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)
@@ -693,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
@@ -1530,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 |
@@ -2246,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 С код определяет размер фрагментированной части.
@@ -2481,6 +2488,7 @@ function execution_plan(ctx)
| range | table | эффективный диапазон [счетчиков](#внутрипрофильные-фильтры) `--in-range` или `--out-range` в зависимости от текущего направления |
| payload | table | эффективный фильтр payload . таблица с индексами - названиями типа пейлоада |
| payload_filter | string | эффективный фильтр payload . список названий пейлоадов через запятую (иное представление payload) |
| arg | table | аргументы инстанса |
**range**
@@ -3741,10 +3749,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
@@ -3758,10 +3766,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
@@ -4560,13 +4568,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-функции)
@@ -4618,6 +4638,22 @@ 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 код из аргумента "code". Код возвращает значение условия через return. Возможна прямая адресация таблицы desync.
# Вспомогательные программы
## ip2net
@@ -5347,6 +5383,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
```

View File

@@ -48,7 +48,7 @@ zapret2 является дальнейшим развитием проекта
Lua код получает от C кода структурированное представление приходящих пакетов в виде дерева (диссекты), подобного тем, что вы видите в wireshark.
Туда же приходят результаты сборки или дешифровки частей некоторых протоколов (tls, quic).
С код предоставляет функции-хелперы, позволяющие отсылать пакеты, работать с двоичными данными, разбирать TLS, искать маркер-позции и т.д.
С код предоставляет функции-хелперы, позволяющие отсылать пакеты, работать с двоичными данными, разбирать TLS, искать маркер-позиции и т.д.
Имеется библиотека хелперов, написанных на Lua, а так же готовая библиотека программ атаки на DPI (стратегий), реализующая функции *nfqws1* в расширенном варианте
и с большей гибкостью.

View File

@@ -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-mipsel linux-mips linux-lexra linux-ppc linux-riscv64"
PKTWS=nfqws2
;;
FreeBSD)

View File

@@ -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 :

View File

@@ -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.code then
error("cond_lua: no 'code' parameter")
end
local fname = desync.func_instance.."_cond_code"
if not _G[fname] then
local err
_G[fname], err = load(desync.arg.code, fname)
if not _G[fname] then
error(err)
return
end
end
-- allow dynamic 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,55 @@ 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
if logical_xor(_G[instance.arg.cond](desync), instance.arg.cond_neg) then
verdict = plan_instance_execute(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)

View File

@@ -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
@@ -206,8 +209,13 @@ 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 +238,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
@@ -321,22 +334,24 @@ end
-- convert array a to packed string using 'packer' function. only numeric indexes starting from 1, order preserved
function barray(a, packer)
local sa={}
if a then
local s=""
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)
local sa={}
if a then
local s=""
for k,v in pairs(a) do
s = s .. packer(v)
sa[k] = packer(v)
end
return s
return table.concat(sa)
end
end
@@ -419,7 +434,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
@@ -790,9 +805,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
@@ -932,11 +947,11 @@ function apply_fooling(desync, dis, fooling_options)
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 +1109,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 +1161,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
@@ -2110,7 +2124,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 +2163,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)
@@ -2433,6 +2447,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 +2467,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 +2477,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)

View File

@@ -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

View File

@@ -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
@@ -420,26 +418,35 @@ function test_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,10000000000);
unixtime = math.random(0,0x7FFFFFFF);
tm = localtime(unixtime);
local t = timelocal(tm)
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,10000000000);
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()

View File

@@ -1,7 +1,9 @@
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
CFLAGS += -std=gnu99 -s $(OPTIMIZE) $(MINSIZE) -Wno-address-of-packed-member
LDFLAGS += -flto=auto -Wl,--gc-sections
LIBS = -lz -lm
SRC_FILES = *.c crypto/*.c

View File

@@ -1,12 +1,15 @@
CC ?= cc
PKG_CONFIG ?= pkg-config
OPTIMIZE ?= -Os
CFLAGS += -std=gnu99 $(OPTIMIZE) -flto=auto
MINSIZE ?= -flto=auto -ffunction-sections -fdata-sections
CFLAGS += -std=gnu99 $(OPTIMIZE) $(MINSIZE)
CFLAGS_LINUX = -Wno-alloc-size-larger-than
CFLAGS_SYSTEMD = -DUSE_SYSTEMD
CFLAGS_BSD = -Wno-address-of-packed-member
CFLAGS_CYGWIN = -Wno-address-of-packed-member -static
CFLAGS_CYGWIN32 =
CFLAGS_UBSAN = -fsanitize=undefined,alignment -fno-sanitize-recover=undefined,alignment
LDFLAGS += -flto=auto -Wl,--gc-sections
LDFLAGS_ANDROID = -llog
LIBS =
LIBS_LINUX = -lz -lnetfilter_queue -lnfnetlink -lmnl -lm
@@ -27,6 +30,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))
@@ -149,9 +153,9 @@ bsd: $(SRC_FILES)
$(CC) -s $(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) -s $(CFLAGS) $(LUA_CFL) $(CFLAGS_CYGWIN) -o winws2 $(SRC_FILES) $(RES_CYGWIN64) $(LIBS) $(LUA_LIB) $(LIBS_CYGWIN) $(LIBS_CYGWIN64) $(LDFLAGS)
cygwin32:
$(CC) -s $(CFLAGS) $(LUA_CFL) $(CFLAGS_CYGWIN) -o winws2 $(SRC_FILES) $(LIBS) $(LUA_LIB) $(LIBS_CYGWIN) $(LIBS_CYGWIN32) $(RES_CYGWIN32) $(LDFLAGS)
$(CC) -s $(CFLAGS) $(LUA_CFL) $(CFLAGS_CYGWIN) $(CFLAGS_CYGWIN32) -o winws2 $(SRC_FILES) $(RES_CYGWIN32) $(LIBS) $(LUA_LIB) $(LIBS_CYGWIN) $(LIBS_CYGWIN32) $(LDFLAGS)
cygwin: cygwin64
clean:

View File

@@ -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);

View File

@@ -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 if (direct->scale != SCALE_NONE)
// 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;
@@ -347,13 +352,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] : "-",

View File

@@ -258,8 +258,6 @@ int gcm_start(gcm_context *ctx, // pointer to user-provided GCM context
size_t use_len; // byte count to process, up to 16 bytes
size_t i; // local loop iterator
if (iv_len!=12) return -1;
// since the context might be reused under the same key
// we zero the working buffers for this next new process
memset(ctx->y, 0x00, sizeof(ctx->y));
@@ -447,7 +445,7 @@ int gcm_crypt_and_tag(
prepare the gcm context with the keying material, we simply
invoke each of the three GCM sub-functions in turn...
*/
if (iv_len!=12 || tag_len>16) return -1;
if (tag_len>16) return -1;
int ret;
if ((ret=gcm_start(ctx, mode, iv, iv_len, add, add_len))) return ret;
@@ -483,26 +481,28 @@ int gcm_auth_decrypt(
uchar check_tag[16]; // the tag generated and returned by decryption
int diff; // an ORed flag to detect authentication errors
size_t i; // our local iterator
int ret;
if (iv_len!=12 || tag_len>16) return -1;
if (tag_len>16) return -1;
/*
we use GCM_DECRYPT_AND_TAG (above) to perform our decryption
(which is an identical XORing to reverse the previous one)
and also to re-generate the matching authentication tag
*/
gcm_crypt_and_tag(ctx, AES_DECRYPT, iv, iv_len, add, add_len,
input, output, length, check_tag, tag_len);
if ((ret = gcm_crypt_and_tag(ctx, AES_DECRYPT, iv, iv_len, add, add_len, input, output, length, check_tag, tag_len))) return ret;
// now we verify the authentication tag in 'constant time'
for (diff = 0, i = 0; i < tag_len; i++)
diff |= tag[i] ^ check_tag[i];
if (diff != 0) { // see whether any bits differed?
if (diff)
{
// see whether any bits differed?
memset(output, 0, length); // if so... wipe the output data
return(GCM_AUTH_FAILURE); // return GCM_AUTH_FAILURE
}
return(0);
return 0;
}
/******************************************************************************

View File

@@ -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;
}

View File

@@ -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;

View File

@@ -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);

View File

@@ -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);
}
@@ -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)
{
@@ -383,9 +383,11 @@ 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;
}
@@ -434,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)
{
@@ -463,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
@@ -488,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)
@@ -508,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:
@@ -524,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;
}
@@ -546,14 +562,14 @@ void proto_dissect_l3l4(const uint8_t *data, size_t len, struct dissect *dis, bo
dis->ip = (const struct ip *) data;
dis->proto = dis->ip->ip_p;
p = data;
proto_skip_ipv4(&data, &len);
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);
proto_skip_ipv6(&data, &len, &dis->proto, &dis->frag, &dis->frag_off);
dis->len_l3 = data-p;
}
else
@@ -562,31 +578,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;
@@ -1541,7 +1557,6 @@ void rawsend_cleanup(void)
{
if (w_filter)
{
CancelIoEx(w_filter,&ovl);
WinDivertClose(w_filter);
w_filter=NULL;
}
@@ -1569,71 +1584,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)
@@ -1753,6 +1768,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
@@ -1774,7 +1790,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
@@ -1855,8 +1880,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)
{
@@ -1906,47 +1932,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;

View File

@@ -175,10 +175,10 @@ 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);
bool proto_check_ipv4_payload(const uint8_t *data, size_t len);
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);
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);
@@ -203,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);

View File

@@ -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 : "");
@@ -734,7 +737,7 @@ static bool ipcache_get_hostname(const struct in_addr *a4, const struct in6_addr
}
if (params.debug)
{
char s[40];
char s[INET6_ADDRSTRLEN];
ntopa46(a4, a6, s, sizeof(s));
DLOG("ipcache hostname search for %s\n", s);
}
@@ -743,7 +746,7 @@ static bool ipcache_get_hostname(const struct in_addr *a4, const struct in6_addr
{
if (params.debug)
{
char s[40];
char s[INET6_ADDRSTRLEN];
ntopa46(a4, a6, s, sizeof(s));
DLOG("got cached hostname for %s : %s (is_ip=%u)\n", s, ipc->hostname, ipc->hostname_is_ip);
}
@@ -1134,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);
}
@@ -1571,8 +1574,9 @@ 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))
@@ -1598,6 +1602,7 @@ static uint8_t dpi_desync_tcp_packet_play(
}
}
rediscover:
if (!dp_rediscovery(&ps))
goto pass_reasm_cancel;
@@ -1658,7 +1663,8 @@ 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;
// do not support mixed ptr+real
if ((*p & 0xC0) || (p+*p+1)>=e || (*p+1)>=(name_size-nl)) return NULL;
if (nl) name[nl++] = '.';
memcpy(name + nl, p + 1, *p);
nl += *p;
@@ -1673,7 +1679,7 @@ static bool feed_dns_response(const uint8_t *a, size_t len)
// 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];
char s_ip[INET6_ADDRSTRLEN];
const uint8_t *b = a, *p;
const uint8_t *e = b + len;
size_t nl;
@@ -2099,36 +2105,27 @@ 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");

View File

@@ -173,7 +173,7 @@ 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);
@@ -186,14 +186,14 @@ void print_cidr4(const struct cidr4 *cidr)
}
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[INET_ADDRSTRLEN+4];
str_cidr6(s,sizeof(s),cidr);
printf("%s",s);
}

View File

@@ -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);

View File

@@ -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,14 @@ 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 +66,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 +94,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 +126,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 +148,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 +157,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 +184,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 +240,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 +270,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 +314,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 +324,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 +335,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 +348,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 +376,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 +417,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,95 +458,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;
if (sz)
{
// alignment
if ((size_t)p & 1) { *p=(uint8_t)random(); sz--; p++; }
if ((size_t)p & 1) { *p = (uint8_t)random(); sz--; p++; }
// random has only 31 bits of entropy. not 32 bits
for (k=0 ; (k+1)<sz ; k+=2) *(uint16_t*)(p+k) = (uint16_t)random();
if (sz & 1) p[sz-1]=(uint8_t)random();
for (k = 0; (k + 1) < sz; k += 2) *(uint16_t*)(p + k) = (uint16_t)random();
if (sz & 1) p[sz - 1] = (uint8_t)random();
}
}
void fill_random_az(uint8_t *p,size_t sz)
void fill_random_az(uint8_t *p, size_t sz)
{
size_t k;
for(k=0;k<sz;k++) p[k] = 'a'+(random() % ('z'-'a'+1));
for (k = 0; k < sz; k++) p[k] = 'a' + (random() % ('z' - 'a' + 1));
}
void fill_random_az09(uint8_t *p,size_t sz)
void fill_random_az09(uint8_t *p, size_t sz)
{
size_t k;
uint8_t rnd;
for(k=0;k<sz;k++)
for (k = 0; k < sz; k++)
{
rnd = random() % (10 + 'z'-'a'+1);
p[k] = rnd<10 ? rnd+'0' : 'a'+rnd-10;
rnd = random() % (10 + 'z' - 'a' + 1);
p[k] = rnd < 10 ? rnd + '0' : 'a' + rnd - 10;
}
}
#if defined(__FreeBSD__) && __FreeBSD_version <= 1200000
#include <sys/sysctl.h>
int getentropy(void *buf, size_t len)
{
int mib[2];
size_t size = len;
int mib[2];
size_t size = len;
// Check for reasonable length (getentropy limits to 256)
if (len > 256) {
errno = EIO;
return -1;
}
// Check for reasonable length (getentropy limits to 256)
if (len > 256) {
errno = EIO;
return -1;
}
mib[0] = CTL_KERN;
mib[1] = KERN_ARND;
mib[0] = CTL_KERN;
mib[1] = KERN_ARND;
if (sysctl(mib, 2, buf, &size, NULL, 0) == -1) {
return -1;
}
if (sysctl(mib, 2, buf, &size, NULL, 0) == -1) {
return -1;
}
return (size == len) ? 0 : -1;
return (size == len) ? 0 : -1;
}
#endif
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);
}
}
@@ -549,33 +609,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;
}
@@ -600,17 +660,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')
@@ -622,34 +734,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

View File

@@ -33,6 +33,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 +106,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

View File

@@ -60,7 +60,7 @@ 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);
@@ -87,7 +87,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 +97,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 +280,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 +304,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_(
&params.hostlists,
bExclude ? &dp->hl_collection_exclude : &dp->hl_collection,

View File

@@ -77,7 +77,7 @@ 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);
@@ -114,6 +114,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 +182,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 +278,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;
}

View File

@@ -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

View File

@@ -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;
@@ -1422,7 +1423,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 +1509,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 +1524,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 +1539,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 +1624,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);
@@ -1894,7 +1901,7 @@ 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;
if (l<6 || (l+2)>left || (type==IPPROTO_AH ? (l>=1024 || ((l+2) & 3)) : (l>=2048 || ((l+2) & 7)))) goto err;
memcpy(data+2,p,l);
l+=2;
data[0] = next; // may be overwritten later
@@ -2312,7 +2319,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 +2390,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 +2436,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 +2813,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 +2833,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 +3140,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 +3181,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);
@@ -3416,7 +3470,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 +3493,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 +3524,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 +3580,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 +3593,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 +3617,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);
@@ -3733,7 +3806,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");
@@ -3884,7 +3957,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);
@@ -3902,6 +3975,7 @@ static bool lua_init_scripts(void)
LIST_FOREACH(str, &params.lua_init_scripts, next)
{
if (bQuit) return false;
if (params.debug)
{
if (str->str[0]=='@')

View File

@@ -56,6 +56,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 +71,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 +85,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 +94,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 +111,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 +120,7 @@ static void onint(int sig)
}
static void onterm(int sig)
{
// theoretically lua_sethook is not async-safe. but it's one-time signal
if (bQuit) return;
const char *msg = "TERM received !\n";
size_t wr = write(1, msg, strlen(msg));
@@ -178,7 +183,7 @@ static void fuzzPacketData(unsigned int count)
*packet = *packet ? (*packet & 1) ? 0x40 : 0x60 | (*packet & 0x0F) : (uint8_t)random();
}
modlen = random()%(sizeof(mod)+1);
verdict = processPacketData(&mark,random()%1 ? "ifin" : NULL,random()%1 ? "ifout" : NULL,packet,len,mod,&modlen);
verdict = processPacketData(&mark,(random() & 1) ? "ifin" : NULL,(random() & 1) ? "ifout" : NULL,packet,len,mod,&modlen);
free(packet);
}
}
@@ -235,6 +240,7 @@ static int write_pidfile(FILE **Fpid)
#ifdef __linux__
// 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;
@@ -244,8 +250,8 @@ static int nfq_cb(struct nfq_q_handle *qh, struct nfgenmsg *nfmsg, struct nfq_da
uint32_t ifidx_out, ifidx_in;
char ifout[IFNAMSIZ], ifin[IFNAMSIZ];
size_t modlen;
uint8_t *mod = (uint8_t*)cookie;
uint32_t mark;
uint8_t mod[RECONSTRUCT_MAX_SIZE] __attribute__((aligned(16)));
ph = nfq_get_msg_packet_hdr(nfa);
id = ph ? ntohl(ph->packet_id) : 0;
@@ -266,7 +272,7 @@ static int nfq_cb(struct nfq_q_handle *qh, struct nfgenmsg *nfmsg, struct nfq_da
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)
@@ -300,7 +306,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, uint8_t *mod_buffer)
{
nfq_deinit(h, qh);
@@ -311,26 +317,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, &params);
*qh = nfq_create_queue(*h, params.qnum, &nfq_cb, mod_buffer);
if (!*qh) {
DLOG_PERROR("nfq_create_queue()");
goto exiterr;
@@ -349,7 +362,7 @@ 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
}
int yes = 1, fd = nfq_fd(*h);
@@ -381,7 +394,7 @@ 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;
if (*params.pidfile && !(Fpid = fopen(params.pidfile, "w")))
{
@@ -423,7 +436,13 @@ static int nfq_main(void)
goto exok;
}
if (!nfq_init(&h, &qh))
if (!(buf = malloc(RECONSTRUCT_MAX_SIZE)) || !(mod = malloc(RECONSTRUCT_MAX_SIZE)))
{
DLOG_ERR("out of memory\n");
goto err;
}
if (!nfq_init(&h, &qh, mod))
goto err;
#ifdef HAS_FILTER_SSID
@@ -446,9 +465,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, RECONSTRUCT_MAX_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
@@ -456,22 +480,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) DLOG_ERR("nfq_handle_packet error %d\n", r);
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;
@@ -482,6 +496,8 @@ static int nfq_main(void)
exok:
res=0;
ex:
free(mod);
free(buf);
nfq_deinit(&h, &qh);
lua_shutdown();
#ifdef HAS_FILTER_SSID
@@ -597,6 +613,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);
@@ -616,7 +637,7 @@ 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");
@@ -1649,7 +1670,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);
}
@@ -1672,6 +1693,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"
@@ -1722,7 +1744,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"
@@ -1835,6 +1857,7 @@ enum opt_indices {
IDX_PORT,
#endif
IDX_DAEMON,
IDX_CHDIR,
IDX_PIDFILE,
#ifndef __CYGWIN__
IDX_USER,
@@ -1939,6 +1962,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},
@@ -2097,10 +2121,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
@@ -2156,8 +2180,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)
{
@@ -2244,8 +2271,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:
@@ -2349,8 +2396,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;
@@ -2361,10 +2411,22 @@ int main(int argc, char **argv)
break;
case IDX_LUA_INIT:
if (!strlist_add_tail(&params.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(&params.lua_init_scripts, p))
{
DLOG_ERR("out of memory\n");
exit_clean(1);
}
}
break;
case IDX_LUA_GC:
@@ -2494,15 +2556,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;

View File

@@ -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

View File

@@ -1033,7 +1033,7 @@ static ip_cache4 *ipcache4Add(ip_cache4 **ipcache, const struct in_addr *a, cons
}
static void ipcache4Print(ip_cache4 *ipcache)
{
char s_ip[16];
char s_ip[INET_ADDRSTRLEN];
time_t now;
ip_cache4 *ipc, *tmp;
@@ -1091,7 +1091,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;

View File

@@ -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;
@@ -142,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)
{
@@ -548,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;
@@ -1188,16 +1194,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;
@@ -1218,17 +1224,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;

View File

@@ -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 ************/
@@ -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)

View File

@@ -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,10 @@ bool dropcaps(void);
# define ARCH_NR AUDIT_ARCH_RISCV64
#elif defined(__loongarch__) && __loongarch_grlen == 64
# define ARCH_NR AUDIT_ARCH_LOONGARCH64
#else
# error "Platform does not support seccomp filter yet"

View File

@@ -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; \