Compare commits

...

9 Commits

Author SHA1 Message Date
bol-van
78ea379e0f quick_start: light release notice 2024-11-24 18:00:01 +03:00
bol-van
007cbe600b update docs 2024-11-24 17:10:01 +03:00
bol-van
d1a8e276b5 update docs 2024-11-24 17:06:23 +03:00
bol-van
eb2f5b5f45 nfqws,tpws: ip->subnet in help text 2024-11-24 17:06:04 +03:00
bol-van
a623cef95d nfqws: fixed lists 2024-11-24 16:48:14 +03:00
bol-van
f00b45a28e tpws: fixed list fixes 2024-11-24 16:47:51 +03:00
bol-van
422faaa29c tpws: fixed ipset and hostlist 2024-11-24 16:03:13 +03:00
bol-van
16a9e3f9c9 github: sha256sum, remove tpws_wsl.tgz in openwrt ver 2024-11-24 13:27:57 +03:00
bol-van
7c5869bc29 display versions 2024-11-24 11:51:49 +03:00
19 changed files with 685 additions and 244 deletions

View File

@ -82,9 +82,7 @@ jobs:
export STRIP=$TARGET-strip export STRIP=$TARGET-strip
export PKG_CONFIG_PATH=$DEPS_DIR/lib/pkgconfig export PKG_CONFIG_PATH=$DEPS_DIR/lib/pkgconfig
# optimize for size export CFLAGS="-DZAPRET_GH_VER=${{ github.ref_name }} -DZAPRET_GH_HASH=${{ github.sha }}"
export CFLAGS="-Os -flto=auto"
export LDFLAGS="-Os"
# netfilter libs # netfilter libs
wget -qO- https://www.netfilter.org/pub/libnfnetlink/libnfnetlink-1.0.2.tar.bz2 | tar -xj wget -qO- https://www.netfilter.org/pub/libnfnetlink/libnfnetlink-1.0.2.tar.bz2 | tar -xj
@ -136,6 +134,7 @@ jobs:
- name: Build zapret - name: Build zapret
run: | run: |
export CFLAGS="-DZAPRET_GH_VER=${{ github.ref_name }} -DZAPRET_GH_HASH=${{ github.sha }}"
make mac -j$(sysctl -n hw.logicalcpu) make mac -j$(sysctl -n hw.logicalcpu)
tar -C binaries/my -cJf zapret-mac-x64.tar.xz . tar -C binaries/my -cJf zapret-mac-x64.tar.xz .
@ -170,6 +169,7 @@ jobs:
TARGET: ${{ matrix.target }} TARGET: ${{ matrix.target }}
ARCH: ${{ matrix.arch }} ARCH: ${{ matrix.arch }}
run: | run: |
export CFLAGS="-DZAPRET_GH_VER=${{ github.ref_name }} -DZAPRET_GH_HASH=${{ github.sha }}"
settarget $TARGET-freebsd11 make bsd -j$(nproc) || exit 1 settarget $TARGET-freebsd11 make bsd -j$(nproc) || exit 1
tar -C binaries/my -cJf zapret-freebsd-$ARCH.tar.xz . tar -C binaries/my -cJf zapret-freebsd-$ARCH.tar.xz .
@ -205,6 +205,7 @@ jobs:
run: | run: |
mkdir -p output mkdir -p output
cd zapret cd zapret
export CFLAGS="-DZAPRET_GH_VER=${{ github.ref_name }} -DZAPRET_GH_HASH=${{ github.sha }}"
mingw32-make -C ip2net win mingw32-make -C ip2net win
mingw32-make -C mdig win mingw32-make -C mdig win
cp -a {ip2net/ip2net,mdig/mdig}.exe ../output cp -a {ip2net/ip2net,mdig/mdig}.exe ../output
@ -259,6 +260,7 @@ jobs:
shell: C:\cygwin\bin\bash.exe -eo pipefail '{0}' shell: C:\cygwin\bin\bash.exe -eo pipefail '{0}'
run: >- run: >-
export MAKEFLAGS=-j$(nproc) && export MAKEFLAGS=-j$(nproc) &&
export CFLAGS="-DZAPRET_GH_VER=${{ github.ref_name }} -DZAPRET_GH_HASH=${{ github.sha }}" &&
cd zapret && cd zapret &&
make -C nfq ${TARGET} && make -C nfq ${TARGET} &&
cp -a nfq/winws.exe ../output cp -a nfq/winws.exe ../output
@ -317,9 +319,7 @@ jobs:
export STRIP=$TOOLCHAIN/bin/llvm-strip export STRIP=$TOOLCHAIN/bin/llvm-strip
export PKG_CONFIG_PATH=$DEPS_DIR/lib/pkgconfig export PKG_CONFIG_PATH=$DEPS_DIR/lib/pkgconfig
# optimize for size export CFLAGS="-DZAPRET_GH_VER=${{ github.ref_name }} -DZAPRET_GH_HASH=${{ github.sha }}"
export CFLAGS="-Os -flto=auto"
export LDFLAGS="-Os"
# netfilter libs # netfilter libs
wget -qO- https://www.netfilter.org/pub/libnfnetlink/libnfnetlink-1.0.2.tar.bz2 | tar -xj wget -qO- https://www.netfilter.org/pub/libnfnetlink/libnfnetlink-1.0.2.tar.bz2 | tar -xj
@ -434,11 +434,13 @@ jobs:
- name: Create release bundles - name: Create release bundles
run: | run: |
rm -rf ${{ env.repo_dir }}/.git* 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 }} tar --owner=0 --group=0 -czf ${{ env.repo_dir }}.tar.gz ${{ env.repo_dir }}
zip -qr ${{ env.repo_dir }}.zip ${{ env.repo_dir }} zip -qr ${{ env.repo_dir }}.zip ${{ env.repo_dir }}
rm -rf ${{ env.repo_dir }}/Makefile ${{ env.repo_dir }}/tpws ${{ env.repo_dir }}/nfq ${{ env.repo_dir }}/ip2net ${{ env.repo_dir }}/mdig ${{ env.repo_dir }}/docs ${{ env.repo_dir }}/files/huawei rm -rf ${{ env.repo_dir }}/tpws ${{ env.repo_dir }}/nfq ${{ env.repo_dir }}/ip2net ${{ env.repo_dir }}/mdig ${{ env.repo_dir }}/docs ${{ env.repo_dir }}/files/huawei
rm -rf ${{ env.repo_dir }}/init.d/openrc ${{ env.repo_dir }}/init.d/macos ${{ env.repo_dir }}/init.d/pfsense ${{ env.repo_dir }}/init.d/runit ${{ env.repo_dir }}/init.d/s6 ${{ env.repo_dir }}/init.d/systemd rm -rf ${{ env.repo_dir }}/init.d/openrc ${{ env.repo_dir }}/init.d/macos ${{ env.repo_dir }}/init.d/pfsense ${{ env.repo_dir }}/init.d/runit ${{ env.repo_dir }}/init.d/s6 ${{ env.repo_dir }}/init.d/systemd
rm -rf ${{ env.repo_dir }}/binaries/android* -rf ${{ env.repo_dir }}/binaries/win* ${{ env.repo_dir }}/binaries/mac* ${{ env.repo_dir }}/binaries/freebsd* rm -rf ${{ env.repo_dir }}/binaries/android* -rf ${{ env.repo_dir }}/binaries/win* ${{ env.repo_dir }}/binaries/mac* ${{ env.repo_dir }}/binaries/freebsd*
rm -f ${{ env.repo_dir }}/Makefile ${{ env.repo_dir }}/binaries/x86_64/tpws_wsl.tgz
tar --owner=0 --group=0 -czf ${{ env.repo_dir }}-openwrt-embedded.tar.gz ${{ env.repo_dir }} tar --owner=0 --group=0 -czf ${{ env.repo_dir }}-openwrt-embedded.tar.gz ${{ env.repo_dir }}
- name: Upload release assets - name: Upload release assets
@ -452,3 +454,4 @@ jobs:
files: | files: |
zapret*.tar.gz zapret*.tar.gz
zapret*.zip zapret*.zip
sha256sum.txt

View File

@ -400,3 +400,10 @@ v69.2:
nfqws,tpws: --skip nfqws,tpws: --skip
nfqws: --methodeol nfqws: --methodeol
init.d: do not use pgrep in sysv for busybox compat init.d: do not use pgrep in sysv for busybox compat
v69.3
nfqws,tpws: fixed ipsets and hostlists
all progs: version numbers for github, build date/time for self built
repo: light release for openwrt and embedded systems
repo: sha256sum

View File

@ -50,6 +50,8 @@
> образ `squashfs` с помощью `image builder` и перешить этим вариантом роутер. > образ `squashfs` с помощью `image builder` и перешить этим вариантом роутер.
1. Скачайте последний [tar.gz релиз](https://github.com/bol-van/zapret/releases) в /tmp, распакуйте его, затем удалите архив. 1. Скачайте последний [tar.gz релиз](https://github.com/bol-van/zapret/releases) в /tmp, распакуйте его, затем удалите архив.
Для openwrt и прошивок используйте вариант `openwrt-embedded`.
Для экономия места в /tmp можно качать через curl в stdout и сразу распаковывать.
2. Убедитесь, что у вас отключены все средства обхода блокировок, в том числе и 2. Убедитесь, что у вас отключены все средства обхода блокировок, в том числе и
сам zapret. Гарантированно уберет zapret скрипт `uninstall_easy.sh`. сам zapret. Гарантированно уберет zapret скрипт `uninstall_easy.sh`.

View File

@ -1,4 +1,4 @@
# zapret v.69 # zapret v69.3
# SCAMMER WARNING # SCAMMER WARNING
@ -180,7 +180,9 @@ nfqws takes the following parameters:
--dpi-desync-start=[n|d|s]N ; apply dpi desync only to packet numbers (n, default), data packet numbers (d), relative sequence (s) greater or equal than N --dpi-desync-start=[n|d|s]N ; apply dpi desync only to packet numbers (n, default), data packet numbers (d), relative sequence (s) greater or equal than N
--dpi-desync-cutoff=[n|d|s]N ; apply dpi desync only to packet numbers (n, default), data packet numbers (d), relative sequence (s) less than N --dpi-desync-cutoff=[n|d|s]N ; apply dpi desync only to packet numbers (n, default), data packet numbers (d), relative sequence (s) less than N
--hostlist=<filename> ; apply dpi desync only to the listed hosts (one host per line, subdomains auto apply, gzip supported, multiple hostlists allowed) --hostlist=<filename> ; apply dpi desync only to the listed hosts (one host per line, subdomains auto apply, gzip supported, multiple hostlists allowed)
--hostlist-domains=<domain_list> ; comma separated fixed domain list
--hostlist-exclude=<filename> ; do not apply dpi desync to the listed hosts (one host per line, subdomains auto apply, gzip supported, multiple hostlists allowed) --hostlist-exclude=<filename> ; do not apply dpi desync to the listed hosts (one host per line, subdomains auto apply, gzip supported, multiple hostlists allowed)
--hostlist-exclude-domains=<domain_list> ; comma separated fixed domain list
--hostlist-auto=<filename> ; detect DPI blocks and build hostlist automatically --hostlist-auto=<filename> ; detect DPI blocks and build hostlist automatically
--hostlist-auto-fail-threshold=<int> ; how many failed attempts cause hostname to be added to auto hostlist (default : 3) --hostlist-auto-fail-threshold=<int> ; how many failed attempts cause hostname to be added to auto hostlist (default : 3)
--hostlist-auto-fail-time=<int> ; all failed attemps must be within these seconds (default : 60) --hostlist-auto-fail-time=<int> ; all failed attemps must be within these seconds (default : 60)
@ -193,7 +195,9 @@ nfqws takes the following parameters:
--filter-udp=[~]port1[-port2]|* ; UDP port filter. ~ means negation. setting udp and not setting tcp filter denies tcp. comma separated list supported. --filter-udp=[~]port1[-port2]|* ; UDP port filter. ~ means negation. setting udp and not setting tcp filter denies tcp. comma separated list supported.
--filter-l7=[http|tls|quic|wireguard|dht|unknown] ; L6-L7 protocol filter. multiple comma separated values allowed. --filter-l7=[http|tls|quic|wireguard|dht|unknown] ; L6-L7 protocol filter. multiple comma separated values allowed.
--ipset=<filename> ; ipset include filter (one ip/CIDR per line, ipv4 and ipv6 accepted, gzip supported, multiple ipsets allowed) --ipset=<filename> ; ipset include filter (one ip/CIDR per line, ipv4 and ipv6 accepted, gzip supported, multiple ipsets allowed)
--ipset-ip=<ip_list> ; comma separated fixed subnet list
--ipset-exclude=<filename> ; ipset exclude filter (one ip/CIDR per line, ipv4 and ipv6 accepted, gzip supported, multiple ipsets allowed) --ipset-exclude=<filename> ; ipset exclude filter (one ip/CIDR per line, ipv4 and ipv6 accepted, gzip supported, multiple ipsets allowed)
--ipset-exclude-ip=<ip_list> ; comma separated fixed subnet list
``` ```
### DPI desync attack ### DPI desync attack
@ -671,10 +675,14 @@ tpws is transparent proxy.
--filter-tcp=[~]port1[-port2]|* ; TCP port filter. ~ means negation. comma separated list supported. --filter-tcp=[~]port1[-port2]|* ; TCP port filter. ~ means negation. comma separated list supported.
--filter-l7=[http|tls|unknown] ; L6-L7 protocol filter. multiple comma separated values allowed. --filter-l7=[http|tls|unknown] ; L6-L7 protocol filter. multiple comma separated values allowed.
--ipset=<filename> ; ipset include filter (one ip/CIDR per line, ipv4 and ipv6 accepted, gzip supported, multiple ipsets allowed) --ipset=<filename> ; ipset include filter (one ip/CIDR per line, ipv4 and ipv6 accepted, gzip supported, multiple ipsets allowed)
--ipset-ip=<ip_list> ; comma separated fixed subnet list
--ipset-exclude=<filename> ; ipset exclude filter (one ip/CIDR per line, ipv4 and ipv6 accepted, gzip supported, multiple ipsets allowed) --ipset-exclude=<filename> ; ipset exclude filter (one ip/CIDR per line, ipv4 and ipv6 accepted, gzip supported, multiple ipsets allowed)
--ipset-exclude-ip=<ip_list> ; comma separated fixed subnet list
--hostlist=<filename> ; only act on hosts in the list (one host per line, subdomains auto apply, gzip supported, multiple hostlists allowed) --hostlist=<filename> ; only act on hosts in the list (one host per line, subdomains auto apply, gzip supported, multiple hostlists allowed)
--hostlist-domains=<domain_list> ; comma separated fixed domain list
--hostlist-exclude=<filename> ; do not act on hosts in the list (one host per line, subdomains auto apply, gzip supported, multiple hostlists allowed) --hostlist-exclude=<filename> ; do not act on hosts in the list (one host per line, subdomains auto apply, gzip supported, multiple hostlists allowed)
--hostlist-exclude-domains=<domain_list> ; comma separated fixed domain list
--hostlist-auto=<filename> ; detect DPI blocks and build hostlist automatically --hostlist-auto=<filename> ; detect DPI blocks and build hostlist automatically
--hostlist-auto-fail-threshold=<int> ; how many failed attempts cause hostname to be added to auto hostlist (default : 3) --hostlist-auto-fail-threshold=<int> ; how many failed attempts cause hostname to be added to auto hostlist (default : 3)
--hostlist-auto-fail-time=<int> ; all failed attemps must be within these seconds (default : 60) --hostlist-auto-fail-time=<int> ; all failed attemps must be within these seconds (default : 60)
@ -704,7 +712,7 @@ tpws is transparent proxy.
--daemon ; daemonize --daemon ; daemonize
--pidfile=<filename> ; write pid to file --pidfile=<filename> ; write pid to file
--user=<username> ; drop root privs --user=<username> ; drop root privs
--uid=uid[:gid] ; drop root privs --uid=uid[:gid] ; drop root privs
``` ```
### TCP segmentation in tpws ### TCP segmentation in tpws

View File

@ -1,4 +1,4 @@
# zapret v.69 # zapret v69.3
# ВНИМАНИЕ, остерегайтесь мошенников # ВНИМАНИЕ, остерегайтесь мошенников
@ -211,7 +211,9 @@ dvtws, собираемый из тех же исходников (см. [док
; список может быть запакован в gzip. формат автоматически распознается и разжимается ; список может быть запакован в gzip. формат автоматически распознается и разжимается
; списков может быть множество. пустой общий лист = его отсутствие ; списков может быть множество. пустой общий лист = его отсутствие
; хосты извлекаются из Host: хедера обычных http запросов и из SNI в TLS ClientHello. ; хосты извлекаются из Host: хедера обычных http запросов и из SNI в TLS ClientHello.
--hostlist-domains=<domain_list> ; фиксированный список доменов через зяпятую. можно использовать # в начале для комментирования отдельных доменов.
--hostlist-exclude=<filename> ; не применять дурение к доменам из листа. может быть множество листов. схема аналогична include листам. --hostlist-exclude=<filename> ; не применять дурение к доменам из листа. может быть множество листов. схема аналогична include листам.
--hostlist-exclude-domains=<domain_list> ; фиксированный список доменов через зяпятую. можно использовать # в начале для комментирования отдельных доменов.
--hostlist-auto=<filename> ; обнаруживать автоматически блокировки и заполнять автоматический hostlist (требует перенаправления входящего трафика) --hostlist-auto=<filename> ; обнаруживать автоматически блокировки и заполнять автоматический hostlist (требует перенаправления входящего трафика)
--hostlist-auto-fail-threshold=<int> ; сколько раз нужно обнаружить ситуацию, похожую на блокировку, чтобы добавить хост в лист (по умолчанию: 3) --hostlist-auto-fail-threshold=<int> ; сколько раз нужно обнаружить ситуацию, похожую на блокировку, чтобы добавить хост в лист (по умолчанию: 3)
--hostlist-auto-fail-time=<int> ; все эти ситуации должны быть в пределах указанного количества секунд (по умолчанию: 60) --hostlist-auto-fail-time=<int> ; все эти ситуации должны быть в пределах указанного количества секунд (по умолчанию: 60)
@ -224,7 +226,9 @@ dvtws, собираемый из тех же исходников (см. [док
--filter-udp=[~]port1[-port2]|* ; фильтр портов udp для текущей стратегии. ~ означает инверсию. установка фильтра udp и неустановка фильтра tcp запрещает tcp. поддерживается список через запятую. --filter-udp=[~]port1[-port2]|* ; фильтр портов udp для текущей стратегии. ~ означает инверсию. установка фильтра udp и неустановка фильтра tcp запрещает tcp. поддерживается список через запятую.
--filter-l7=[http|tls|quic|wireguard|dht|unknown] ; фильтр протокола L6-L7. поддерживается несколько значений через запятую. --filter-l7=[http|tls|quic|wireguard|dht|unknown] ; фильтр протокола L6-L7. поддерживается несколько значений через запятую.
--ipset=<filename> ; включающий ip list. на каждой строчке ip или cidr ipv4 или ipv6. поддерживается множество листов и gzip. перечитка автоматическая. --ipset=<filename> ; включающий ip list. на каждой строчке ip или cidr ipv4 или ipv6. поддерживается множество листов и gzip. перечитка автоматическая.
--ipset-ip=<ip_list> ; фиксированный список подсетей через запятую. можно использовать # в начале для комментирования отдельных подсетей.
--ipset-exclude=<filename> ; исключающий ip list. на каждой строчке ip или cidr ipv4 или ipv6. поддерживается множество листов и gzip. перечитка автоматическая. --ipset-exclude=<filename> ; исключающий ip list. на каждой строчке ip или cidr ipv4 или ipv6. поддерживается множество листов и gzip. перечитка автоматическая.
--ipset-exclude-ip=<ip_list> ; фиксированный список подсетей через запятую. можно использовать # в начале для комментирования отдельных подсетей.
``` ```
`--debug` позволяет выводить подробный лог действий на консоль, в syslog или в файл. Может быть важен порядок следования `--debug` позволяет выводить подробный лог действий на консоль, в syslog или в файл. Может быть важен порядок следования
@ -822,7 +826,9 @@ tpws - это transparent proxy.
; список может быть запакован в gzip. формат автоматически распознается и разжимается ; список может быть запакован в gzip. формат автоматически распознается и разжимается
; списков может быть множество. пустой общий лист = его отсутствие ; списков может быть множество. пустой общий лист = его отсутствие
; хосты извлекаются из Host: хедера обычных http запросов и из SNI в TLS ClientHello. ; хосты извлекаются из Host: хедера обычных http запросов и из SNI в TLS ClientHello.
--hostlist-domains=<domain_list> ; фиксированный список доменов через зяпятую. можно использовать # в начале для комментирования отдельных доменов.
--hostlist-exclude=<filename> ; не применять дурение к доменам из листа. может быть множество листов. схема аналогична include листам. --hostlist-exclude=<filename> ; не применять дурение к доменам из листа. может быть множество листов. схема аналогична include листам.
--hostlist-exclude-domains=<domain_list>; фиксированный список доменов через зяпятую. можно использовать # в начале для комментирования отдельных доменов.
--hostlist-auto=<filename> ; обнаруживать автоматически блокировки и заполнять автоматический hostlist (требует перенаправления входящего трафика) --hostlist-auto=<filename> ; обнаруживать автоматически блокировки и заполнять автоматический hostlist (требует перенаправления входящего трафика)
--hostlist-auto-fail-threshold=<int> ; сколько раз нужно обнаружить ситуацию, похожую на блокировку, чтобы добавить хост в лист (по умолчанию: 3) --hostlist-auto-fail-threshold=<int> ; сколько раз нужно обнаружить ситуацию, похожую на блокировку, чтобы добавить хост в лист (по умолчанию: 3)
--hostlist-auto-fail-time=<int> ; все эти ситуации должны быть в пределах указанного количества секунд (по умолчанию: 60) --hostlist-auto-fail-time=<int> ; все эти ситуации должны быть в пределах указанного количества секунд (по умолчанию: 60)
@ -833,7 +839,9 @@ tpws - это transparent proxy.
--filter-tcp=[~]port1[-port2]|* ; фильтр портов tcp для текущей стратегии. ~ означает инверсию. поддерживается список через запятую. --filter-tcp=[~]port1[-port2]|* ; фильтр портов tcp для текущей стратегии. ~ означает инверсию. поддерживается список через запятую.
--filter-l7=[http|tls|quic|wireguard|dht|unknown] ; фильтр протокола L6-L7. поддерживается несколько значений через запятую. --filter-l7=[http|tls|quic|wireguard|dht|unknown] ; фильтр протокола L6-L7. поддерживается несколько значений через запятую.
--ipset=<filename> ; включающий ip list. на каждой строчке ip или cidr ipv4 или ipv6. поддерживается множество листов и gzip. перечитка автоматическая. --ipset=<filename> ; включающий ip list. на каждой строчке ip или cidr ipv4 или ipv6. поддерживается множество листов и gzip. перечитка автоматическая.
--ipset-ip=<ip_list> ; фиксированный список подсетей через запятую. можно использовать # в начале для комментирования отдельных подсетей.
--ipset-exclude=<filename> ; исключающий ip list. на каждой строчке ip или cidr ipv4 или ipv6. поддерживается множество листов и gzip. перечитка автоматическая. --ipset-exclude=<filename> ; исключающий ip list. на каждой строчке ip или cidr ipv4 или ipv6. поддерживается множество листов и gzip. перечитка автоматическая.
--ipset-exclude-ip=<ip_list> ; фиксированный список подсетей через запятую. можно использовать # в начале для комментирования отдельных подсетей.
``` ```
### TCP СЕГМЕНТАЦИЯ В TPWS ### TCP СЕГМЕНТАЦИЯ В TPWS

View File

@ -192,7 +192,7 @@ static void ip6_and(const struct in6_addr * restrict a, const struct in6_addr *
static void rtrim(char *s) static void rtrim(char *s)
{ {
if (s) if (s)
for (char *p = s + strlen(s) - 1; p >= s && (*p == '\n' || *p == '\r'); p--) *p = '\0'; for (char *p = s + strlen(s) - 1; p >= s && (*p == '\n' || *p == '\r' || *p == ' ' || *p == '\t'); p--) *p = '\0';
} }
@ -217,6 +217,14 @@ static void exithelp(void)
exit(1); exit(1);
} }
#define STRINGIFY(x) #x
#define TOSTRING(x) STRINGIFY(x)
#if defined(ZAPRET_GH_VER) || defined (ZAPRET_GH_HASH)
#define PRINT_VER printf("github version %s (%s)\n\n", TOSTRING(ZAPRET_GH_VER), TOSTRING(ZAPRET_GH_HASH))
#else
#define PRINT_VER printf("self-built version %s %s\n\n", __DATE__, __TIME__)
#endif
static void parse_params(int argc, char *argv[]) static void parse_params(int argc, char *argv[])
{ {
int option_index = 0; int option_index = 0;
@ -245,6 +253,7 @@ static void parse_params(int argc, char *argv[])
{ {
case 0: case 0:
case 1: case 1:
PRINT_VER;
exithelp(); exithelp();
break; break;
case 2: case 2:

View File

@ -35,7 +35,7 @@
static void trimstr(char *s) static void trimstr(char *s)
{ {
char *p; char *p;
for (p = s + strlen(s) - 1; p >= s && (*p == '\n' || *p == '\r'); p--) *p = '\0'; for (p = s + strlen(s) - 1; p >= s && (*p == '\n' || *p == '\r' || *p == ' ' || *p == '\t'); p--) *p = '\0';
} }
static const char* eai_str(int r) static const char* eai_str(int r)
@ -458,6 +458,15 @@ static void exithelp(void)
); );
exit(1); exit(1);
} }
#define STRINGIFY(x) #x
#define TOSTRING(x) STRINGIFY(x)
#if defined(ZAPRET_GH_VER) || defined (ZAPRET_GH_HASH)
#define PRINT_VER printf("github version %s (%s)\n\n", TOSTRING(ZAPRET_GH_VER), TOSTRING(ZAPRET_GH_HASH))
#else
#define PRINT_VER printf("self-built version %s %s\n\n", __DATE__, __TIME__)
#endif
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
int r, v, option_index = 0; int r, v, option_index = 0;
@ -487,6 +496,7 @@ int main(int argc, char **argv)
switch (option_index) switch (option_index)
{ {
case 0: /* help */ case 0: /* help */
PRINT_VER;
exithelp(); exithelp();
break; break;
case 1: /* threads */ case 1: /* threads */

View File

@ -24,7 +24,7 @@ static bool addpool(strpool **hostlist, char **s, const char *end, int *ct)
*hostlist = NULL; *hostlist = NULL;
return false; return false;
} }
(*ct)++; if (ct) (*ct)++;
} }
// advance to the next line // advance to the next line
for (; p<end && (!*p || *p=='\r' || *p=='\n') ; p++); for (; p<end && (!*p || *p=='\r' || *p=='\n') ; p++);
@ -32,6 +32,11 @@ static bool addpool(strpool **hostlist, char **s, const char *end, int *ct)
return true; return true;
} }
bool AppendHostlistItem(strpool **hostlist, char *s)
{
return addpool(hostlist,&s,s+strlen(s),NULL);
}
bool AppendHostList(strpool **hostlist, const char *filename) bool AppendHostList(strpool **hostlist, const char *filename)
{ {
char *p, *e, s[256], *zbuf; char *p, *e, s[256], *zbuf;
@ -98,21 +103,24 @@ bool AppendHostList(strpool **hostlist, const char *filename)
static bool LoadHostList(struct hostlist_file *hfile) static bool LoadHostList(struct hostlist_file *hfile)
{ {
time_t t = file_mod_time(hfile->filename); if (hfile->filename)
if (!t)
{
// stat() error
DLOG_ERR("cannot access hostlist file '%s'. in-memory content remains unchanged.\n",hfile->filename);
return true;
}
if (t==hfile->mod_time) return true; // up to date
StrPoolDestroy(&hfile->hostlist);
if (!AppendHostList(&hfile->hostlist, hfile->filename))
{ {
time_t t = file_mod_time(hfile->filename);
if (!t)
{
// stat() error
DLOG_ERR("cannot access hostlist file '%s'. in-memory content remains unchanged.\n",hfile->filename);
return true;
}
if (t==hfile->mod_time) return true; // up to date
StrPoolDestroy(&hfile->hostlist); StrPoolDestroy(&hfile->hostlist);
return false; if (!AppendHostList(&hfile->hostlist, hfile->filename))
{
StrPoolDestroy(&hfile->hostlist);
return false;
}
hfile->mod_time=t;
} }
hfile->mod_time=t;
return true; return true;
} }
static bool LoadHostLists(struct hostlist_files_head *list) static bool LoadHostLists(struct hostlist_files_head *list)
@ -202,7 +210,7 @@ static bool HostlistCheck_(const struct hostlist_collection_head *hostlists, con
LIST_FOREACH(item, hostlists_exclude, next) LIST_FOREACH(item, hostlists_exclude, next)
{ {
DLOG("[%s] exclude ", item->hfile->filename); DLOG("[%s] exclude ", item->hfile->filename ? item->hfile->filename : "fixed");
if (SearchHostList(item->hfile->hostlist, host)) if (SearchHostList(item->hfile->hostlist, host))
{ {
if (excluded) *excluded = true; if (excluded) *excluded = true;
@ -214,7 +222,7 @@ static bool HostlistCheck_(const struct hostlist_collection_head *hostlists, con
{ {
LIST_FOREACH(item, hostlists, next) LIST_FOREACH(item, hostlists, next)
{ {
DLOG("[%s] include ", item->hfile->filename); DLOG("[%s] include ", item->hfile->filename ? item->hfile->filename : "fixed");
if (SearchHostList(item->hfile->hostlist, host)) if (SearchHostList(item->hfile->hostlist, host))
return true; return true;
} }
@ -235,17 +243,29 @@ bool HostlistCheck(const struct desync_profile *dp, const char *host, bool *excl
static struct hostlist_file *RegisterHostlist_(struct hostlist_files_head *hostlists, struct hostlist_collection_head *hl_collection, const char *filename) static struct hostlist_file *RegisterHostlist_(struct hostlist_files_head *hostlists, struct hostlist_collection_head *hl_collection, const char *filename)
{ {
struct hostlist_file *hfile; struct hostlist_file *hfile;
if (!(hfile=hostlist_files_search(hostlists, filename)))
if (!(hfile=hostlist_files_add(hostlists, filename))) if (filename)
{
if (!(hfile=hostlist_files_search(hostlists, filename)))
if (!(hfile=hostlist_files_add(hostlists, filename)))
return NULL;
if (!hostlist_collection_search(hl_collection, filename))
if (!hostlist_collection_add(hl_collection, hfile))
return NULL;
}
else
{
if (!(hfile=hostlist_files_add(hostlists, NULL)))
return NULL; return NULL;
if (!hostlist_collection_search(hl_collection, filename))
if (!hostlist_collection_add(hl_collection, hfile)) if (!hostlist_collection_add(hl_collection, hfile))
return NULL; return NULL;
}
return hfile; return hfile;
} }
struct hostlist_file *RegisterHostlist(struct desync_profile *dp, bool bExclude, const char *filename) struct hostlist_file *RegisterHostlist(struct desync_profile *dp, bool bExclude, const char *filename)
{ {
if (!file_mod_time(filename)) if (filename && !file_mod_time(filename))
{ {
DLOG_ERR("cannot access hostlist file '%s'\n",filename); DLOG_ERR("cannot access hostlist file '%s'\n",filename);
return NULL; return NULL;
@ -265,15 +285,30 @@ void HostlistsDebug()
struct hostlist_item *hl_item; struct hostlist_item *hl_item;
LIST_FOREACH(hfile, &params.hostlists, next) LIST_FOREACH(hfile, &params.hostlists, next)
DLOG("hostlist file %s%s\n",hfile->filename,hfile->hostlist ? "" : " (empty)"); {
if (hfile->filename)
DLOG("hostlist file %s%s\n",hfile->filename,hfile->hostlist ? "" : " (empty)");
else
DLOG("hostlist fixed%s\n",hfile->hostlist ? "" : " (empty)");
}
LIST_FOREACH(dpl, &params.desync_profiles, next) LIST_FOREACH(dpl, &params.desync_profiles, next)
{ {
LIST_FOREACH(hl_item, &dpl->dp.hl_collection, next) LIST_FOREACH(hl_item, &dpl->dp.hl_collection, next)
if (hl_item->hfile!=dpl->dp.hostlist_auto) if (hl_item->hfile!=dpl->dp.hostlist_auto)
DLOG("profile %d include hostlist %s%s\n",dpl->dp.n, hl_item->hfile->filename,hl_item->hfile->hostlist ? "" : " (empty)"); {
if (hl_item->hfile->filename)
DLOG("profile %d include hostlist %s%s\n",dpl->dp.n, hl_item->hfile->filename,hl_item->hfile->hostlist ? "" : " (empty)");
else
DLOG("profile %d include fixed hostlist%s\n",dpl->dp.n, hl_item->hfile->hostlist ? "" : " (empty)");
}
LIST_FOREACH(hl_item, &dpl->dp.hl_collection_exclude, next) LIST_FOREACH(hl_item, &dpl->dp.hl_collection_exclude, next)
DLOG("profile %d exclude hostlist %s%s\n",dpl->dp.n,hl_item->hfile->filename,hl_item->hfile->hostlist ? "" : " (empty)"); {
if (hl_item->hfile->filename)
DLOG("profile %d exclude hostlist %s%s\n",dpl->dp.n,hl_item->hfile->filename,hl_item->hfile->hostlist ? "" : " (empty)");
else
DLOG("profile %d exclude fixed hostlist%s\n",dpl->dp.n,hl_item->hfile->hostlist ? "" : " (empty)");
}
if (dpl->dp.hostlist_auto) if (dpl->dp.hostlist_auto)
DLOG("profile %d auto hostlist %s%s\n",dpl->dp.n,dpl->dp.hostlist_auto->filename,dpl->dp.hostlist_auto->hostlist ? "" : " (empty)"); DLOG("profile %d auto hostlist %s%s\n",dpl->dp.n,dpl->dp.hostlist_auto->filename,dpl->dp.hostlist_auto->hostlist ? "" : " (empty)");
} }

View File

@ -4,6 +4,7 @@
#include "pools.h" #include "pools.h"
#include "params.h" #include "params.h"
bool AppendHostlistItem(strpool **hostlist, char *s);
bool AppendHostList(strpool **hostlist, const char *filename); bool AppendHostList(strpool **hostlist, const char *filename);
bool LoadAllHostLists(); bool LoadAllHostLists();
bool NonEmptyHostlist(strpool **hostlist); bool NonEmptyHostlist(strpool **hostlist);

View File

@ -31,7 +31,7 @@ static bool addpool(ipset *ips, char **s, const char *end, int *ct)
ipsetDestroy(ips); ipsetDestroy(ips);
return false; return false;
} }
(*ct)++; if (ct) (*ct)++;
} }
else if (parse_cidr6(cidr,&c6)) else if (parse_cidr6(cidr,&c6))
{ {
@ -40,7 +40,7 @@ static bool addpool(ipset *ips, char **s, const char *end, int *ct)
ipsetDestroy(ips); ipsetDestroy(ips);
return false; return false;
} }
(*ct)++; if (ct) (*ct)++;
} }
else else
DLOG_ERR("bad ip or subnet : %s\n",cidr); DLOG_ERR("bad ip or subnet : %s\n",cidr);
@ -53,6 +53,11 @@ static bool addpool(ipset *ips, char **s, const char *end, int *ct)
} }
bool AppendIpsetItem(ipset *ips, char *ip)
{
return addpool(ips,&ip,ip+strlen(ip),NULL);
}
static bool AppendIpset(ipset *ips, const char *filename) static bool AppendIpset(ipset *ips, const char *filename)
{ {
char *p, *e, s[256], *zbuf; char *p, *e, s[256], *zbuf;
@ -119,21 +124,24 @@ static bool AppendIpset(ipset *ips, const char *filename)
static bool LoadIpset(struct ipset_file *hfile) static bool LoadIpset(struct ipset_file *hfile)
{ {
time_t t = file_mod_time(hfile->filename); if (hfile->filename)
if (!t)
{
// stat() error
DLOG_ERR("cannot access ipset file '%s'. in-memory content remains unchanged.\n",hfile->filename);
return true;
}
if (t==hfile->mod_time) return true; // up to date
ipsetDestroy(&hfile->ipset);
if (!AppendIpset(&hfile->ipset, hfile->filename))
{ {
time_t t = file_mod_time(hfile->filename);
if (!t)
{
// stat() error
DLOG_ERR("cannot access ipset file '%s'. in-memory content remains unchanged.\n",hfile->filename);
return true;
}
if (t==hfile->mod_time) return true; // up to date
ipsetDestroy(&hfile->ipset); ipsetDestroy(&hfile->ipset);
return false; if (!AppendIpset(&hfile->ipset, hfile->filename))
{
ipsetDestroy(&hfile->ipset);
return false;
}
hfile->mod_time=t;
} }
hfile->mod_time=t;
return true; return true;
} }
static bool LoadIpsets(struct ipset_files_head *list) static bool LoadIpsets(struct ipset_files_head *list)
@ -205,7 +213,7 @@ static bool IpsetCheck_(const struct ipset_collection_head *ips, const struct ip
LIST_FOREACH(item, ips_exclude, next) LIST_FOREACH(item, ips_exclude, next)
{ {
DLOG("[%s] exclude ",item->hfile->filename); DLOG("[%s] exclude ",item->hfile->filename ? item->hfile->filename : "fixed");
if (SearchIpset(&item->hfile->ipset, ipv4, ipv6)) if (SearchIpset(&item->hfile->ipset, ipv4, ipv6))
return false; return false;
} }
@ -214,7 +222,7 @@ static bool IpsetCheck_(const struct ipset_collection_head *ips, const struct ip
{ {
LIST_FOREACH(item, ips, next) LIST_FOREACH(item, ips, next)
{ {
DLOG("[%s] include ",item->hfile->filename); DLOG("[%s] include ",item->hfile->filename ? item->hfile->filename : "fixed");
if (SearchIpset(&item->hfile->ipset, ipv4, ipv6)) if (SearchIpset(&item->hfile->ipset, ipv4, ipv6))
return true; return true;
} }
@ -234,17 +242,27 @@ bool IpsetCheck(const struct desync_profile *dp, const struct in_addr *ipv4, con
static struct ipset_file *RegisterIpset_(struct ipset_files_head *ipsets, struct ipset_collection_head *ips_collection, const char *filename) static struct ipset_file *RegisterIpset_(struct ipset_files_head *ipsets, struct ipset_collection_head *ips_collection, const char *filename)
{ {
struct ipset_file *hfile; struct ipset_file *hfile;
if (!(hfile=ipset_files_search(ipsets, filename))) if (filename)
if (!(hfile=ipset_files_add(ipsets, filename))) {
if (!(hfile=ipset_files_search(ipsets, filename)))
if (!(hfile=ipset_files_add(ipsets, filename)))
return NULL;
if (!ipset_collection_search(ips_collection, filename))
if (!ipset_collection_add(ips_collection, hfile))
return NULL;
}
else
{
if (!(hfile=ipset_files_add(ipsets, NULL)))
return NULL; return NULL;
if (!ipset_collection_search(ips_collection, filename))
if (!ipset_collection_add(ips_collection, hfile)) if (!ipset_collection_add(ips_collection, hfile))
return NULL; return NULL;
}
return hfile; return hfile;
} }
struct ipset_file *RegisterIpset(struct desync_profile *dp, bool bExclude, const char *filename) struct ipset_file *RegisterIpset(struct desync_profile *dp, bool bExclude, const char *filename)
{ {
if (!file_mod_time(filename)) if (filename && !file_mod_time(filename))
{ {
DLOG_ERR("cannot access ipset file '%s'\n",filename); DLOG_ERR("cannot access ipset file '%s'\n",filename);
return NULL; return NULL;
@ -277,13 +295,24 @@ void IpsetsDebug()
struct ipset_item *ips_item; struct ipset_item *ips_item;
LIST_FOREACH(hfile, &params.ipsets, next) LIST_FOREACH(hfile, &params.ipsets, next)
DLOG("ipset file %s (%s)\n",hfile->filename,dbg_ipset_fill(&hfile->ipset)); {
if (hfile->filename)
DLOG("ipset file %s (%s)\n",hfile->filename,dbg_ipset_fill(&hfile->ipset));
else
DLOG("ipset fixed (%s)\n",dbg_ipset_fill(&hfile->ipset));
}
LIST_FOREACH(dpl, &params.desync_profiles, next) LIST_FOREACH(dpl, &params.desync_profiles, next)
{ {
LIST_FOREACH(ips_item, &dpl->dp.ips_collection, next) LIST_FOREACH(ips_item, &dpl->dp.ips_collection, next)
DLOG("profile %d include ipset %s (%s)\n",dpl->dp.n,ips_item->hfile->filename,dbg_ipset_fill(&ips_item->hfile->ipset)); if (ips_item->hfile->filename)
DLOG("profile %d include ipset %s (%s)\n",dpl->dp.n,ips_item->hfile->filename,dbg_ipset_fill(&ips_item->hfile->ipset));
else
DLOG("profile %d include fixed ipset (%s)\n",dpl->dp.n,dbg_ipset_fill(&ips_item->hfile->ipset));
LIST_FOREACH(ips_item, &dpl->dp.ips_collection_exclude, next) LIST_FOREACH(ips_item, &dpl->dp.ips_collection_exclude, next)
DLOG("profile %d exclude ipset %s (%s)\n",dpl->dp.n,ips_item->hfile->filename,dbg_ipset_fill(&ips_item->hfile->ipset)); if (ips_item->hfile->filename)
DLOG("profile %d exclude ipset %s (%s)\n",dpl->dp.n,ips_item->hfile->filename,dbg_ipset_fill(&ips_item->hfile->ipset));
else
DLOG("profile %d exclude fixed ipset (%s)\n",dpl->dp.n,dbg_ipset_fill(&ips_item->hfile->ipset));
} }
} }

View File

@ -9,3 +9,4 @@ bool LoadAllIpsets();
bool IpsetCheck(const struct desync_profile *dp, const struct in_addr *ipv4, const struct in6_addr *ipv6); bool IpsetCheck(const struct desync_profile *dp, const struct in_addr *ipv4, const struct in6_addr *ipv6);
struct ipset_file *RegisterIpset(struct desync_profile *dp, bool bExclude, const char *filename); struct ipset_file *RegisterIpset(struct desync_profile *dp, bool bExclude, const char *filename);
void IpsetsDebug(); void IpsetsDebug();
bool AppendIpsetItem(ipset *ips, char *ip);

View File

@ -836,6 +836,47 @@ static bool parse_split_pos_list(char *opt, struct proto_pos *splits, int splits
if (p) return false; // too much splits if (p) return false; // too much splits
return true; return true;
} }
static bool parse_domain_list(char *opt, strpool **pp)
{
char *e,*p,c;
for (p=opt ; p ; )
{
if ((e = strchr(p,',')))
{
c=*e;
*e=0;
}
if (*p && !AppendHostlistItem(pp,p)) return false;
if (e) *e++=c;
p = e;
}
return true;
}
static bool parse_ip_list(char *opt, ipset *pp)
{
char *e,*p,c;
for (p=opt ; p ; )
{
if ((e = strchr(p,',')))
{
c=*e;
*e=0;
}
if (*p && !AppendIpsetItem(pp,p)) return false;
if (e) *e++=c;
p = e;
}
return true;
}
static void split_compat(struct desync_profile *dp) static void split_compat(struct desync_profile *dp)
{ {
if (!dp->split_count) if (!dp->split_count)
@ -1026,10 +1067,14 @@ static void exithelp(void)
" --filter-udp=[~]port1[-port2]|*\t\t; UDP port filter. ~ means negation. setting udp and not setting tcp filter denies tcp. comma separated list allowed.\n" " --filter-udp=[~]port1[-port2]|*\t\t; UDP port filter. ~ means negation. setting udp and not setting tcp filter denies tcp. comma separated list allowed.\n"
" --filter-l7=[http|tls|quic|wireguard|dht|unknown] ; L6-L7 protocol filter. multiple comma separated values allowed.\n" " --filter-l7=[http|tls|quic|wireguard|dht|unknown] ; L6-L7 protocol filter. multiple comma separated values allowed.\n"
" --ipset=<filename>\t\t\t\t; ipset include filter (one ip/CIDR per line, ipv4 and ipv6 accepted, gzip supported, multiple ipsets allowed)\n" " --ipset=<filename>\t\t\t\t; ipset include filter (one ip/CIDR per line, ipv4 and ipv6 accepted, gzip supported, multiple ipsets allowed)\n"
" --ipset-ip=<ip_list>\t\t\t\t; comma separated fixed subnet list\n"
" --ipset-exclude=<filename>\t\t\t; ipset exclude filter (one ip/CIDR per line, ipv4 and ipv6 accepted, gzip supported, multiple ipsets allowed)\n" " --ipset-exclude=<filename>\t\t\t; ipset exclude filter (one ip/CIDR per line, ipv4 and ipv6 accepted, gzip supported, multiple ipsets allowed)\n"
" --ipset-exclude-ip=<ip_list>\t\t\t; comma separated fixed subnet list\n"
"\nHOSTLIST FILTER:\n" "\nHOSTLIST FILTER:\n"
" --hostlist=<filename>\t\t\t\t; apply dpi desync only to the listed hosts (one host per line, subdomains auto apply, gzip supported, multiple hostlists allowed)\n" " --hostlist=<filename>\t\t\t\t; apply dpi desync only to the listed hosts (one host per line, subdomains auto apply, gzip supported, multiple hostlists allowed)\n"
" --hostlist-domains=<domain_list>\t\t; comma separated fixed domain list\n"
" --hostlist-exclude=<filename>\t\t\t; do not apply dpi desync to the listed hosts (one host per line, subdomains auto apply, gzip supported, multiple hostlists allowed)\n" " --hostlist-exclude=<filename>\t\t\t; do not apply dpi desync to the listed hosts (one host per line, subdomains auto apply, gzip supported, multiple hostlists allowed)\n"
" --hostlist-exclude-domains=<domain_list>\t; comma separated fixed domain list\n"
" --hostlist-auto=<filename>\t\t\t; detect DPI blocks and build hostlist automatically\n" " --hostlist-auto=<filename>\t\t\t; detect DPI blocks and build hostlist automatically\n"
" --hostlist-auto-fail-threshold=<int>\t\t; how many failed attempts cause hostname to be added to auto hostlist (default : %d)\n" " --hostlist-auto-fail-threshold=<int>\t\t; how many failed attempts cause hostname to be added to auto hostlist (default : %d)\n"
" --hostlist-auto-fail-time=<int>\t\t; all failed attemps must be within these seconds (default : %d)\n" " --hostlist-auto-fail-time=<int>\t\t; all failed attemps must be within these seconds (default : %d)\n"
@ -1128,6 +1173,14 @@ void config_from_file(const char *filename)
} }
#endif #endif
#define STRINGIFY(x) #x
#define TOSTRING(x) STRINGIFY(x)
#if defined(ZAPRET_GH_VER) || defined (ZAPRET_GH_HASH)
#define PRINT_VER printf("github version %s (%s)\n\n", TOSTRING(ZAPRET_GH_VER), TOSTRING(ZAPRET_GH_HASH))
#else
#define PRINT_VER printf("self-built version %s %s\n\n", __DATE__, __TIME__)
#endif
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
set_env_exedir(argv[0]); set_env_exedir(argv[0]);
@ -1143,6 +1196,8 @@ int main(int argc, char **argv)
int option_index = 0; int option_index = 0;
bool daemon = false, bSkip = false; bool daemon = false, bSkip = false;
char pidfile[256]; char pidfile[256];
struct hostlist_file *anon_hl = NULL, *anon_hl_exclude = NULL;
struct ipset_file *anon_ips = NULL, *anon_ips_exclude = NULL;
#ifdef __CYGWIN__ #ifdef __CYGWIN__
char windivert_filter[8192], wf_pf_tcp_src[256], wf_pf_tcp_dst[256], wf_pf_udp_src[256], wf_pf_udp_dst[256], wf_save_file[256]; char windivert_filter[8192], wf_pf_tcp_src[256], wf_pf_tcp_dst[256], wf_pf_udp_src[256], wf_pf_udp_dst[256], wf_save_file[256];
bool wf_ipv4=true, wf_ipv6=true; bool wf_ipv4=true, wf_ipv6=true;
@ -1154,6 +1209,8 @@ int main(int argc, char **argv)
srandom(time(NULL)); srandom(time(NULL));
mask_from_preflen6_prepare(); mask_from_preflen6_prepare();
PRINT_VER;
memset(&params, 0, sizeof(params)); memset(&params, 0, sizeof(params));
*pidfile = 0; *pidfile = 0;
@ -1268,33 +1325,37 @@ int main(int argc, char **argv)
{"dpi-desync-cutoff",required_argument,0,0},// optidx=44 {"dpi-desync-cutoff",required_argument,0,0},// optidx=44
{"dpi-desync-start",required_argument,0,0},// optidx=45 {"dpi-desync-start",required_argument,0,0},// optidx=45
{"hostlist",required_argument,0,0}, // optidx=46 {"hostlist",required_argument,0,0}, // optidx=46
{"hostlist-exclude",required_argument,0,0}, // optidx=47 {"hostlist-domains",required_argument,0,0},// optidx=47
{"hostlist-auto",required_argument,0,0}, // optidx=48 {"hostlist-exclude",required_argument,0,0}, // optidx=48
{"hostlist-auto-fail-threshold",required_argument,0,0}, // optidx=49 {"hostlist-exclude-domains",required_argument,0,0},// optidx=49
{"hostlist-auto-fail-time",required_argument,0,0}, // optidx=50 {"hostlist-auto",required_argument,0,0}, // optidx=50
{"hostlist-auto-retrans-threshold",required_argument,0,0}, // optidx=51 {"hostlist-auto-fail-threshold",required_argument,0,0}, // optidx=51
{"hostlist-auto-debug",required_argument,0,0}, // optidx=52 {"hostlist-auto-fail-time",required_argument,0,0}, // optidx=52
{"new",no_argument,0,0}, // optidx=53 {"hostlist-auto-retrans-threshold",required_argument,0,0}, // optidx=53
{"skip",no_argument,0,0}, // optidx=54 {"hostlist-auto-debug",required_argument,0,0}, // optidx=54
{"filter-l3",required_argument,0,0}, // optidx=55 {"new",no_argument,0,0}, // optidx=55
{"filter-tcp",required_argument,0,0}, // optidx=56 {"skip",no_argument,0,0}, // optidx=56
{"filter-udp",required_argument,0,0}, // optidx=57 {"filter-l3",required_argument,0,0}, // optidx=57
{"filter-l7",required_argument,0,0}, // optidx=58 {"filter-tcp",required_argument,0,0}, // optidx=58
{"ipset",required_argument,0,0}, // optidx=59 {"filter-udp",required_argument,0,0}, // optidx=59
{"ipset-exclude",required_argument,0,0},// optidx=60 {"filter-l7",required_argument,0,0}, // optidx=60
{"ipset",required_argument,0,0}, // optidx=61
{"ipset-ip",required_argument,0,0}, // optidx=62
{"ipset-exclude",required_argument,0,0},// optidx=63
{"ipset-exclude-ip",required_argument,0,0}, // optidx=64
#ifdef __linux__ #ifdef __linux__
{"bind-fix4",no_argument,0,0}, // optidx=61 {"bind-fix4",no_argument,0,0}, // optidx=65
{"bind-fix6",no_argument,0,0}, // optidx=62 {"bind-fix6",no_argument,0,0}, // optidx=66
#elif defined(__CYGWIN__) #elif defined(__CYGWIN__)
{"wf-iface",required_argument,0,0}, // optidx=61 {"wf-iface",required_argument,0,0}, // optidx=65
{"wf-l3",required_argument,0,0}, // optidx=62 {"wf-l3",required_argument,0,0}, // optidx=66
{"wf-tcp",required_argument,0,0}, // optidx=63 {"wf-tcp",required_argument,0,0}, // optidx=67
{"wf-udp",required_argument,0,0}, // optidx=64 {"wf-udp",required_argument,0,0}, // optidx=68
{"wf-raw",required_argument,0,0}, // optidx=65 {"wf-raw",required_argument,0,0}, // optidx=69
{"wf-save",required_argument,0,0}, // optidx=66 {"wf-save",required_argument,0,0}, // optidx=70
{"ssid-filter",required_argument,0,0}, // optidx=67 {"ssid-filter",required_argument,0,0}, // optidx=71
{"nlm-filter",required_argument,0,0}, // optidx=68 {"nlm-filter",required_argument,0,0}, // optidx=72
{"nlm-list",optional_argument,0,0}, // optidx=69 {"nlm-list",optional_argument,0,0}, // optidx=73
#endif #endif
{NULL,0,NULL,0} {NULL,0,NULL,0}
}; };
@ -1735,20 +1796,49 @@ int main(int argc, char **argv)
} }
break; break;
case 46: /* hostlist */ case 46: /* hostlist */
if (bSkip) break;
if (!RegisterHostlist(dp, false, optarg)) if (!RegisterHostlist(dp, false, optarg))
{ {
DLOG_ERR("failed to register hostlist '%s'\n", optarg); DLOG_ERR("failed to register hostlist '%s'\n", optarg);
exit_clean(1); exit_clean(1);
} }
break; break;
case 47: /* hostlist-exclude */ case 47: /* hostlist-domains */
if (bSkip) break;
if (!anon_hl && !(anon_hl=RegisterHostlist(dp, false, NULL)))
{
DLOG_ERR("failed to register anonymous hostlist\n");
exit_clean(1);
}
if (!parse_domain_list(optarg, &anon_hl->hostlist))
{
DLOG_ERR("failed to add domains to anonymous hostlist\n");
exit_clean(1);
}
break;
case 48: /* hostlist-exclude */
if (bSkip) break;
if (!RegisterHostlist(dp, true, optarg)) if (!RegisterHostlist(dp, true, optarg))
{ {
DLOG_ERR("failed to register hostlist '%s'\n", optarg); DLOG_ERR("failed to register hostlist '%s'\n", optarg);
exit_clean(1); exit_clean(1);
} }
break; break;
case 48: /* hostlist-auto */ case 49: /* hostlist-exclude-domains */
if (bSkip) break;
if (!anon_hl_exclude && !(anon_hl_exclude=RegisterHostlist(dp, true, NULL)))
{
DLOG_ERR("failed to register anonymous hostlist\n");
exit_clean(1);
}
if (!parse_domain_list(optarg, &anon_hl_exclude->hostlist))
{
DLOG_ERR("failed to add domains to anonymous hostlist\n");
exit_clean(1);
}
break;
case 50: /* hostlist-auto */
if (bSkip) break;
if (dp->hostlist_auto) if (dp->hostlist_auto)
{ {
DLOG_ERR("only one auto hostlist per profile is supported\n"); DLOG_ERR("only one auto hostlist per profile is supported\n");
@ -1775,7 +1865,7 @@ int main(int argc, char **argv)
exit_clean(1); exit_clean(1);
} }
break; break;
case 49: /* hostlist-auto-fail-threshold */ case 51: /* hostlist-auto-fail-threshold */
dp->hostlist_auto_fail_threshold = (uint8_t)atoi(optarg); dp->hostlist_auto_fail_threshold = (uint8_t)atoi(optarg);
if (dp->hostlist_auto_fail_threshold<1 || dp->hostlist_auto_fail_threshold>20) if (dp->hostlist_auto_fail_threshold<1 || dp->hostlist_auto_fail_threshold>20)
{ {
@ -1783,7 +1873,7 @@ int main(int argc, char **argv)
exit_clean(1); exit_clean(1);
} }
break; break;
case 50: /* hostlist-auto-fail-time */ case 52: /* hostlist-auto-fail-time */
dp->hostlist_auto_fail_time = (uint8_t)atoi(optarg); dp->hostlist_auto_fail_time = (uint8_t)atoi(optarg);
if (dp->hostlist_auto_fail_time<1) if (dp->hostlist_auto_fail_time<1)
{ {
@ -1791,7 +1881,7 @@ int main(int argc, char **argv)
exit_clean(1); exit_clean(1);
} }
break; break;
case 51: /* hostlist-auto-retrans-threshold */ case 53: /* hostlist-auto-retrans-threshold */
dp->hostlist_auto_retrans_threshold = (uint8_t)atoi(optarg); dp->hostlist_auto_retrans_threshold = (uint8_t)atoi(optarg);
if (dp->hostlist_auto_retrans_threshold<2 || dp->hostlist_auto_retrans_threshold>10) if (dp->hostlist_auto_retrans_threshold<2 || dp->hostlist_auto_retrans_threshold>10)
{ {
@ -1799,7 +1889,7 @@ int main(int argc, char **argv)
exit_clean(1); exit_clean(1);
} }
break; break;
case 52: /* hostlist-auto-debug */ case 54: /* hostlist-auto-debug */
{ {
FILE *F = fopen(optarg,"a+t"); FILE *F = fopen(optarg,"a+t");
if (!F) if (!F)
@ -1813,7 +1903,7 @@ int main(int argc, char **argv)
} }
break; break;
case 53: /* new */ case 55: /* new */
if (bSkip) if (bSkip)
{ {
dp_clear(dp); dp_clear(dp);
@ -1831,19 +1921,21 @@ int main(int argc, char **argv)
dp = &dpl->dp; dp = &dpl->dp;
dp->n = ++desync_profile_count; dp->n = ++desync_profile_count;
} }
anon_hl = anon_hl_exclude = NULL;
anon_ips = anon_ips_exclude = NULL;
break; break;
case 54: /* skip */ case 56: /* skip */
bSkip = true; bSkip = true;
break; break;
case 55: /* filter-l3 */ case 57: /* filter-l3 */
if (!wf_make_l3(optarg,&dp->filter_ipv4,&dp->filter_ipv6)) if (!wf_make_l3(optarg,&dp->filter_ipv4,&dp->filter_ipv6))
{ {
DLOG_ERR("bad value for --filter-l3\n"); DLOG_ERR("bad value for --filter-l3\n");
exit_clean(1); exit_clean(1);
} }
break; break;
case 56: /* filter-tcp */ case 58: /* filter-tcp */
if (!parse_pf_list(optarg,&dp->pf_tcp)) if (!parse_pf_list(optarg,&dp->pf_tcp))
{ {
DLOG_ERR("Invalid port filter : %s\n",optarg); DLOG_ERR("Invalid port filter : %s\n",optarg);
@ -1853,7 +1945,7 @@ int main(int argc, char **argv)
if (!port_filters_deny_if_empty(&dp->pf_udp)) if (!port_filters_deny_if_empty(&dp->pf_udp))
exit_clean(1); exit_clean(1);
break; break;
case 57: /* filter-udp */ case 59: /* filter-udp */
if (!parse_pf_list(optarg,&dp->pf_udp)) if (!parse_pf_list(optarg,&dp->pf_udp))
{ {
DLOG_ERR("Invalid port filter : %s\n",optarg); DLOG_ERR("Invalid port filter : %s\n",optarg);
@ -1863,53 +1955,80 @@ int main(int argc, char **argv)
if (!port_filters_deny_if_empty(&dp->pf_tcp)) if (!port_filters_deny_if_empty(&dp->pf_tcp))
exit_clean(1); exit_clean(1);
break; break;
case 58: /* filter-l7 */ case 60: /* filter-l7 */
if (!parse_l7_list(optarg,&dp->filter_l7)) if (!parse_l7_list(optarg,&dp->filter_l7))
{ {
DLOG_ERR("Invalid l7 filter : %s\n",optarg); DLOG_ERR("Invalid l7 filter : %s\n",optarg);
exit_clean(1); exit_clean(1);
} }
break; break;
case 59: /* ipset */ case 61: /* ipset */
if (bSkip) break;
if (!RegisterIpset(dp, false, optarg)) if (!RegisterIpset(dp, false, optarg))
{ {
DLOG_ERR("failed to register ipset '%s'\n", optarg); DLOG_ERR("failed to register ipset '%s'\n", optarg);
exit_clean(1); exit_clean(1);
} }
break; break;
case 60: /* ipset-exclude */ case 62: /* ipset-ip */
if (bSkip) break;
if (!anon_ips && !(anon_ips=RegisterIpset(dp, false, NULL)))
{
DLOG_ERR("failed to register anonymous ipset\n");
exit_clean(1);
}
if (!parse_ip_list(optarg, &anon_ips->ipset))
{
DLOG_ERR("failed to add subnets to anonymous ipset\n");
exit_clean(1);
}
break;
case 63: /* ipset-exclude */
if (bSkip) break;
if (!RegisterIpset(dp, true, optarg)) if (!RegisterIpset(dp, true, optarg))
{ {
DLOG_ERR("failed to register ipset '%s'\n", optarg); DLOG_ERR("failed to register ipset '%s'\n", optarg);
exit_clean(1); exit_clean(1);
} }
break; break;
case 64: /* ipset-exclude-ip */
if (bSkip) break;
if (!anon_ips_exclude && !(anon_ips_exclude=RegisterIpset(dp, true, NULL)))
{
DLOG_ERR("failed to register anonymous ipset\n");
exit_clean(1);
}
if (!parse_ip_list(optarg, &anon_ips_exclude->ipset))
{
DLOG_ERR("failed to add subnets to anonymous ipset\n");
exit_clean(1);
}
break;
#ifdef __linux__ #ifdef __linux__
case 61: /* bind-fix4 */ case 65: /* bind-fix4 */
params.bind_fix4 = true; params.bind_fix4 = true;
break; break;
case 62: /* bind-fix6 */ case 66: /* bind-fix6 */
params.bind_fix6 = true; params.bind_fix6 = true;
break; break;
#elif defined(__CYGWIN__) #elif defined(__CYGWIN__)
case 61: /* wf-iface */ case 65: /* wf-iface */
if (!sscanf(optarg,"%u.%u",&IfIdx,&SubIfIdx)) if (!sscanf(optarg,"%u.%u",&IfIdx,&SubIfIdx))
{ {
DLOG_ERR("bad value for --wf-iface\n"); DLOG_ERR("bad value for --wf-iface\n");
exit_clean(1); exit_clean(1);
} }
break; break;
case 62: /* wf-l3 */ case 66: /* wf-l3 */
if (!wf_make_l3(optarg,&wf_ipv4,&wf_ipv6)) if (!wf_make_l3(optarg,&wf_ipv4,&wf_ipv6))
{ {
DLOG_ERR("bad value for --wf-l3\n"); DLOG_ERR("bad value for --wf-l3\n");
exit_clean(1); exit_clean(1);
} }
break; break;
case 63: /* wf-tcp */ case 67: /* wf-tcp */
hash_wf_tcp=hash_jen(optarg,strlen(optarg)); hash_wf_tcp=hash_jen(optarg,strlen(optarg));
if (!wf_make_pf(optarg,"tcp","SrcPort",wf_pf_tcp_src,sizeof(wf_pf_tcp_src)) || if (!wf_make_pf(optarg,"tcp","SrcPort",wf_pf_tcp_src,sizeof(wf_pf_tcp_src)) ||
!wf_make_pf(optarg,"tcp","DstPort",wf_pf_tcp_dst,sizeof(wf_pf_tcp_dst))) !wf_make_pf(optarg,"tcp","DstPort",wf_pf_tcp_dst,sizeof(wf_pf_tcp_dst)))
@ -1918,7 +2037,7 @@ int main(int argc, char **argv)
exit_clean(1); exit_clean(1);
} }
break; break;
case 64: /* wf-udp */ case 68: /* wf-udp */
hash_wf_udp=hash_jen(optarg,strlen(optarg)); hash_wf_udp=hash_jen(optarg,strlen(optarg));
if (!wf_make_pf(optarg,"udp","SrcPort",wf_pf_udp_src,sizeof(wf_pf_udp_src)) || if (!wf_make_pf(optarg,"udp","SrcPort",wf_pf_udp_src,sizeof(wf_pf_udp_src)) ||
!wf_make_pf(optarg,"udp","DstPort",wf_pf_udp_dst,sizeof(wf_pf_udp_dst))) !wf_make_pf(optarg,"udp","DstPort",wf_pf_udp_dst,sizeof(wf_pf_udp_dst)))
@ -1927,7 +2046,7 @@ int main(int argc, char **argv)
exit_clean(1); exit_clean(1);
} }
break; break;
case 65: /* wf-raw */ case 69: /* wf-raw */
hash_wf_raw=hash_jen(optarg,strlen(optarg)); hash_wf_raw=hash_jen(optarg,strlen(optarg));
if (optarg[0]=='@') if (optarg[0]=='@')
{ {
@ -1941,11 +2060,11 @@ int main(int argc, char **argv)
windivert_filter[sizeof(windivert_filter) - 1] = '\0'; windivert_filter[sizeof(windivert_filter) - 1] = '\0';
} }
break; break;
case 66: /* wf-save */ case 70: /* wf-save */
strncpy(wf_save_file, optarg, sizeof(wf_save_file)); strncpy(wf_save_file, optarg, sizeof(wf_save_file));
wf_save_file[sizeof(wf_save_file) - 1] = '\0'; wf_save_file[sizeof(wf_save_file) - 1] = '\0';
break; break;
case 67: /* ssid-filter */ case 71: /* ssid-filter */
hash_ssid_filter=hash_jen(optarg,strlen(optarg)); hash_ssid_filter=hash_jen(optarg,strlen(optarg));
{ {
char *e,*p = optarg; char *e,*p = optarg;
@ -1963,7 +2082,7 @@ int main(int argc, char **argv)
} }
} }
break; break;
case 68: /* nlm-filter */ case 72: /* nlm-filter */
hash_nlm_filter=hash_jen(optarg,strlen(optarg)); hash_nlm_filter=hash_jen(optarg,strlen(optarg));
{ {
char *e,*p = optarg; char *e,*p = optarg;
@ -1981,7 +2100,7 @@ int main(int argc, char **argv)
} }
} }
break; break;
case 69: /* nlm-list */ case 73: /* nlm-list */
if (!nlm_list(optarg && !strcmp(optarg,"all"))) if (!nlm_list(optarg && !strcmp(optarg,"all")))
{ {
DLOG_ERR("could not get list of NLM networks\n"); DLOG_ERR("could not get list of NLM networks\n");

View File

@ -160,12 +160,17 @@ struct hostlist_file *hostlist_files_add(struct hostlist_files_head *head, const
struct hostlist_file *entry = malloc(sizeof(struct hostlist_file)); struct hostlist_file *entry = malloc(sizeof(struct hostlist_file));
if (entry) if (entry)
{ {
if (!(entry->filename = strdup(filename))) if (filename)
{ {
free(entry); if (!(entry->filename = strdup(filename)))
return false; {
free(entry);
return false;
}
} }
entry->mod_time=0; else
entry->filename = NULL;
entry->mod_time = 0;
entry->hostlist = NULL; entry->hostlist = NULL;
LIST_INSERT_HEAD(head, entry, next); LIST_INSERT_HEAD(head, entry, next);
} }
@ -192,7 +197,7 @@ struct hostlist_file *hostlist_files_search(struct hostlist_files_head *head, co
LIST_FOREACH(hfile, head, next) LIST_FOREACH(hfile, head, next)
{ {
if (!strcmp(hfile->filename,filename)) if (hfile->filename && !strcmp(hfile->filename,filename))
return hfile; return hfile;
} }
return NULL; return NULL;
@ -223,7 +228,7 @@ struct hostlist_item *hostlist_collection_search(struct hostlist_collection_head
LIST_FOREACH(item, head, next) LIST_FOREACH(item, head, next)
{ {
if (!strcmp(item->hfile->filename,filename)) if (item->hfile->filename && !strcmp(item->hfile->filename,filename))
return item; return item;
} }
return NULL; return NULL;
@ -369,12 +374,17 @@ struct ipset_file *ipset_files_add(struct ipset_files_head *head, const char *fi
struct ipset_file *entry = malloc(sizeof(struct ipset_file)); struct ipset_file *entry = malloc(sizeof(struct ipset_file));
if (entry) if (entry)
{ {
if (!(entry->filename = strdup(filename))) if (filename)
{ {
free(entry); if (!(entry->filename = strdup(filename)))
return false; {
free(entry);
return false;
}
} }
entry->mod_time=0; else
entry->filename = NULL;
entry->mod_time = 0;
memset(&entry->ipset,0,sizeof(entry->ipset)); memset(&entry->ipset,0,sizeof(entry->ipset));
LIST_INSERT_HEAD(head, entry, next); LIST_INSERT_HEAD(head, entry, next);
} }
@ -401,7 +411,7 @@ struct ipset_file *ipset_files_search(struct ipset_files_head *head, const char
LIST_FOREACH(hfile, head, next) LIST_FOREACH(hfile, head, next)
{ {
if (!strcmp(hfile->filename,filename)) if (hfile->filename && !strcmp(hfile->filename,filename))
return hfile; return hfile;
} }
return NULL; return NULL;
@ -432,7 +442,7 @@ struct ipset_item *ipset_collection_search(struct ipset_collection_head *head, c
LIST_FOREACH(item, head, next) LIST_FOREACH(item, head, next)
{ {
if (!strcmp(item->hfile->filename,filename)) if (item->hfile->filename && !strcmp(item->hfile->filename,filename))
return item; return item;
} }
return NULL; return NULL;

View File

@ -24,7 +24,7 @@ static bool addpool(strpool **hostlist, char **s, const char *end, int *ct)
*hostlist = NULL; *hostlist = NULL;
return false; return false;
} }
(*ct)++; if (ct) (*ct)++;
} }
// advance to the next line // advance to the next line
for (; p<end && (!*p || *p=='\r' || *p=='\n') ; p++); for (; p<end && (!*p || *p=='\r' || *p=='\n') ; p++);
@ -32,6 +32,11 @@ static bool addpool(strpool **hostlist, char **s, const char *end, int *ct)
return true; return true;
} }
bool AppendHostlistItem(strpool **hostlist, char *s)
{
return addpool(hostlist,&s,s+strlen(s),NULL);
}
bool AppendHostList(strpool **hostlist, const char *filename) bool AppendHostList(strpool **hostlist, const char *filename)
{ {
char *p, *e, s[256], *zbuf; char *p, *e, s[256], *zbuf;
@ -98,21 +103,24 @@ bool AppendHostList(strpool **hostlist, const char *filename)
static bool LoadHostList(struct hostlist_file *hfile) static bool LoadHostList(struct hostlist_file *hfile)
{ {
time_t t = file_mod_time(hfile->filename); if (hfile->filename)
if (!t)
{
// stat() error
DLOG_ERR("cannot access hostlist file '%s'. in-memory content remains unchanged.\n",hfile->filename);
return true;
}
if (t==hfile->mod_time) return true; // up to date
StrPoolDestroy(&hfile->hostlist);
if (!AppendHostList(&hfile->hostlist, hfile->filename))
{ {
time_t t = file_mod_time(hfile->filename);
if (!t)
{
// stat() error
DLOG_ERR("cannot access hostlist file '%s'. in-memory content remains unchanged.\n",hfile->filename);
return true;
}
if (t==hfile->mod_time) return true; // up to date
StrPoolDestroy(&hfile->hostlist); StrPoolDestroy(&hfile->hostlist);
return false; if (!AppendHostList(&hfile->hostlist, hfile->filename))
{
StrPoolDestroy(&hfile->hostlist);
return false;
}
hfile->mod_time=t;
} }
hfile->mod_time=t;
return true; return true;
} }
static bool LoadHostLists(struct hostlist_files_head *list) static bool LoadHostLists(struct hostlist_files_head *list)
@ -202,7 +210,7 @@ static bool HostlistCheck_(const struct hostlist_collection_head *hostlists, con
LIST_FOREACH(item, hostlists_exclude, next) LIST_FOREACH(item, hostlists_exclude, next)
{ {
VPRINT("[%s] exclude ", item->hfile->filename); VPRINT("[%s] exclude ", item->hfile->filename ? item->hfile->filename : "fixed");
if (SearchHostList(item->hfile->hostlist, host)) if (SearchHostList(item->hfile->hostlist, host))
{ {
if (excluded) *excluded = true; if (excluded) *excluded = true;
@ -214,7 +222,7 @@ static bool HostlistCheck_(const struct hostlist_collection_head *hostlists, con
{ {
LIST_FOREACH(item, hostlists, next) LIST_FOREACH(item, hostlists, next)
{ {
VPRINT("[%s] include ", item->hfile->filename); VPRINT("[%s] include ", item->hfile->filename ? item->hfile->filename : "fixed");
if (SearchHostList(item->hfile->hostlist, host)) if (SearchHostList(item->hfile->hostlist, host))
return true; return true;
} }
@ -235,17 +243,29 @@ bool HostlistCheck(const struct desync_profile *dp, const char *host, bool *excl
static struct hostlist_file *RegisterHostlist_(struct hostlist_files_head *hostlists, struct hostlist_collection_head *hl_collection, const char *filename) static struct hostlist_file *RegisterHostlist_(struct hostlist_files_head *hostlists, struct hostlist_collection_head *hl_collection, const char *filename)
{ {
struct hostlist_file *hfile; struct hostlist_file *hfile;
if (!(hfile=hostlist_files_search(hostlists, filename)))
if (!(hfile=hostlist_files_add(hostlists, filename))) if (filename)
{
if (!(hfile=hostlist_files_search(hostlists, filename)))
if (!(hfile=hostlist_files_add(hostlists, filename)))
return NULL;
if (!hostlist_collection_search(hl_collection, filename))
if (!hostlist_collection_add(hl_collection, hfile))
return NULL;
}
else
{
if (!(hfile=hostlist_files_add(hostlists, NULL)))
return NULL; return NULL;
if (!hostlist_collection_search(hl_collection, filename))
if (!hostlist_collection_add(hl_collection, hfile)) if (!hostlist_collection_add(hl_collection, hfile))
return NULL; return NULL;
}
return hfile; return hfile;
} }
struct hostlist_file *RegisterHostlist(struct desync_profile *dp, bool bExclude, const char *filename) struct hostlist_file *RegisterHostlist(struct desync_profile *dp, bool bExclude, const char *filename)
{ {
if (!file_mod_time(filename)) if (filename && !file_mod_time(filename))
{ {
DLOG_ERR("cannot access hostlist file '%s'\n",filename); DLOG_ERR("cannot access hostlist file '%s'\n",filename);
return NULL; return NULL;
@ -265,15 +285,30 @@ void HostlistsDebug()
struct hostlist_item *hl_item; struct hostlist_item *hl_item;
LIST_FOREACH(hfile, &params.hostlists, next) LIST_FOREACH(hfile, &params.hostlists, next)
VPRINT("hostlist file %s%s\n",hfile->filename,hfile->hostlist ? "" : " (empty)"); {
if (hfile->filename)
VPRINT("hostlist file %s%s\n",hfile->filename,hfile->hostlist ? "" : " (empty)");
else
VPRINT("hostlist fixed%s\n",hfile->hostlist ? "" : " (empty)");
}
LIST_FOREACH(dpl, &params.desync_profiles, next) LIST_FOREACH(dpl, &params.desync_profiles, next)
{ {
LIST_FOREACH(hl_item, &dpl->dp.hl_collection, next) LIST_FOREACH(hl_item, &dpl->dp.hl_collection, next)
if (hl_item->hfile!=dpl->dp.hostlist_auto) if (hl_item->hfile!=dpl->dp.hostlist_auto)
VPRINT("profile %d include hostlist %s%s\n",dpl->dp.n, hl_item->hfile->filename,hl_item->hfile->hostlist ? "" : " (empty)"); {
if (hl_item->hfile->filename)
VPRINT("profile %d include hostlist %s%s\n",dpl->dp.n, hl_item->hfile->filename,hl_item->hfile->hostlist ? "" : " (empty)");
else
VPRINT("profile %d include fixed hostlist%s\n",dpl->dp.n, hl_item->hfile->hostlist ? "" : " (empty)");
}
LIST_FOREACH(hl_item, &dpl->dp.hl_collection_exclude, next) LIST_FOREACH(hl_item, &dpl->dp.hl_collection_exclude, next)
VPRINT("profile %d exclude hostlist %s%s\n",dpl->dp.n,hl_item->hfile->filename,hl_item->hfile->hostlist ? "" : " (empty)"); {
if (hl_item->hfile->filename)
VPRINT("profile %d exclude hostlist %s%s\n",dpl->dp.n,hl_item->hfile->filename,hl_item->hfile->hostlist ? "" : " (empty)");
else
VPRINT("profile %d exclude fixed hostlist%s\n",dpl->dp.n,hl_item->hfile->hostlist ? "" : " (empty)");
}
if (dpl->dp.hostlist_auto) if (dpl->dp.hostlist_auto)
VPRINT("profile %d auto hostlist %s%s\n",dpl->dp.n,dpl->dp.hostlist_auto->filename,dpl->dp.hostlist_auto->hostlist ? "" : " (empty)"); VPRINT("profile %d auto hostlist %s%s\n",dpl->dp.n,dpl->dp.hostlist_auto->filename,dpl->dp.hostlist_auto->hostlist ? "" : " (empty)");
} }

View File

@ -4,6 +4,7 @@
#include "pools.h" #include "pools.h"
#include "params.h" #include "params.h"
bool AppendHostlistItem(strpool **hostlist, char *s);
bool AppendHostList(strpool **hostlist, const char *filename); bool AppendHostList(strpool **hostlist, const char *filename);
bool LoadAllHostLists(); bool LoadAllHostLists();
bool NonEmptyHostlist(strpool **hostlist); bool NonEmptyHostlist(strpool **hostlist);

View File

@ -31,7 +31,7 @@ static bool addpool(ipset *ips, char **s, const char *end, int *ct)
ipsetDestroy(ips); ipsetDestroy(ips);
return false; return false;
} }
(*ct)++; if (ct) (*ct)++;
} }
else if (parse_cidr6(cidr,&c6)) else if (parse_cidr6(cidr,&c6))
{ {
@ -40,7 +40,7 @@ static bool addpool(ipset *ips, char **s, const char *end, int *ct)
ipsetDestroy(ips); ipsetDestroy(ips);
return false; return false;
} }
(*ct)++; if (ct) (*ct)++;
} }
else else
DLOG_ERR("bad ip or subnet : %s\n",cidr); DLOG_ERR("bad ip or subnet : %s\n",cidr);
@ -53,6 +53,11 @@ static bool addpool(ipset *ips, char **s, const char *end, int *ct)
} }
bool AppendIpsetItem(ipset *ips, char *ip)
{
return addpool(ips,&ip,ip+strlen(ip),NULL);
}
static bool AppendIpset(ipset *ips, const char *filename) static bool AppendIpset(ipset *ips, const char *filename)
{ {
char *p, *e, s[256], *zbuf; char *p, *e, s[256], *zbuf;
@ -119,21 +124,24 @@ static bool AppendIpset(ipset *ips, const char *filename)
static bool LoadIpset(struct ipset_file *hfile) static bool LoadIpset(struct ipset_file *hfile)
{ {
time_t t = file_mod_time(hfile->filename); if (hfile->filename)
if (!t)
{
// stat() error
DLOG_ERR("cannot access ipset file '%s'. in-memory content remains unchanged.\n",hfile->filename);
return true;
}
if (t==hfile->mod_time) return true; // up to date
ipsetDestroy(&hfile->ipset);
if (!AppendIpset(&hfile->ipset, hfile->filename))
{ {
time_t t = file_mod_time(hfile->filename);
if (!t)
{
// stat() error
DLOG_ERR("cannot access ipset file '%s'. in-memory content remains unchanged.\n",hfile->filename);
return true;
}
if (t==hfile->mod_time) return true; // up to date
ipsetDestroy(&hfile->ipset); ipsetDestroy(&hfile->ipset);
return false; if (!AppendIpset(&hfile->ipset, hfile->filename))
{
ipsetDestroy(&hfile->ipset);
return false;
}
hfile->mod_time=t;
} }
hfile->mod_time=t;
return true; return true;
} }
static bool LoadIpsets(struct ipset_files_head *list) static bool LoadIpsets(struct ipset_files_head *list)
@ -205,7 +213,7 @@ static bool IpsetCheck_(const struct ipset_collection_head *ips, const struct ip
LIST_FOREACH(item, ips_exclude, next) LIST_FOREACH(item, ips_exclude, next)
{ {
VPRINT("[%s] exclude ",item->hfile->filename); VPRINT("[%s] exclude ",item->hfile->filename ? item->hfile->filename : "fixed");
if (SearchIpset(&item->hfile->ipset, ipv4, ipv6)) if (SearchIpset(&item->hfile->ipset, ipv4, ipv6))
return false; return false;
} }
@ -214,7 +222,7 @@ static bool IpsetCheck_(const struct ipset_collection_head *ips, const struct ip
{ {
LIST_FOREACH(item, ips, next) LIST_FOREACH(item, ips, next)
{ {
VPRINT("[%s] include ",item->hfile->filename); VPRINT("[%s] include ",item->hfile->filename ? item->hfile->filename : "fixed");
if (SearchIpset(&item->hfile->ipset, ipv4, ipv6)) if (SearchIpset(&item->hfile->ipset, ipv4, ipv6))
return true; return true;
} }
@ -234,17 +242,27 @@ bool IpsetCheck(const struct desync_profile *dp, const struct in_addr *ipv4, con
static struct ipset_file *RegisterIpset_(struct ipset_files_head *ipsets, struct ipset_collection_head *ips_collection, const char *filename) static struct ipset_file *RegisterIpset_(struct ipset_files_head *ipsets, struct ipset_collection_head *ips_collection, const char *filename)
{ {
struct ipset_file *hfile; struct ipset_file *hfile;
if (!(hfile=ipset_files_search(ipsets, filename))) if (filename)
if (!(hfile=ipset_files_add(ipsets, filename))) {
if (!(hfile=ipset_files_search(ipsets, filename)))
if (!(hfile=ipset_files_add(ipsets, filename)))
return NULL;
if (!ipset_collection_search(ips_collection, filename))
if (!ipset_collection_add(ips_collection, hfile))
return NULL;
}
else
{
if (!(hfile=ipset_files_add(ipsets, NULL)))
return NULL; return NULL;
if (!ipset_collection_search(ips_collection, filename))
if (!ipset_collection_add(ips_collection, hfile)) if (!ipset_collection_add(ips_collection, hfile))
return NULL; return NULL;
}
return hfile; return hfile;
} }
struct ipset_file *RegisterIpset(struct desync_profile *dp, bool bExclude, const char *filename) struct ipset_file *RegisterIpset(struct desync_profile *dp, bool bExclude, const char *filename)
{ {
if (!file_mod_time(filename)) if (filename && !file_mod_time(filename))
{ {
DLOG_ERR("cannot access ipset file '%s'\n",filename); DLOG_ERR("cannot access ipset file '%s'\n",filename);
return NULL; return NULL;
@ -277,13 +295,24 @@ void IpsetsDebug()
struct ipset_item *ips_item; struct ipset_item *ips_item;
LIST_FOREACH(hfile, &params.ipsets, next) LIST_FOREACH(hfile, &params.ipsets, next)
VPRINT("ipset file %s (%s)\n",hfile->filename,dbg_ipset_fill(&hfile->ipset)); {
if (hfile->filename)
VPRINT("ipset file %s (%s)\n",hfile->filename,dbg_ipset_fill(&hfile->ipset));
else
VPRINT("ipset fixed (%s)\n",dbg_ipset_fill(&hfile->ipset));
}
LIST_FOREACH(dpl, &params.desync_profiles, next) LIST_FOREACH(dpl, &params.desync_profiles, next)
{ {
LIST_FOREACH(ips_item, &dpl->dp.ips_collection, next) LIST_FOREACH(ips_item, &dpl->dp.ips_collection, next)
VPRINT("profile %d include ipset %s (%s)\n",dpl->dp.n,ips_item->hfile->filename,dbg_ipset_fill(&ips_item->hfile->ipset)); if (ips_item->hfile->filename)
VPRINT("profile %d include ipset %s (%s)\n",dpl->dp.n,ips_item->hfile->filename,dbg_ipset_fill(&ips_item->hfile->ipset));
else
VPRINT("profile %d include fixed ipset (%s)\n",dpl->dp.n,dbg_ipset_fill(&ips_item->hfile->ipset));
LIST_FOREACH(ips_item, &dpl->dp.ips_collection_exclude, next) LIST_FOREACH(ips_item, &dpl->dp.ips_collection_exclude, next)
VPRINT("profile %d exclude ipset %s (%s)\n",dpl->dp.n,ips_item->hfile->filename,dbg_ipset_fill(&ips_item->hfile->ipset)); if (ips_item->hfile->filename)
VPRINT("profile %d exclude ipset %s (%s)\n",dpl->dp.n,ips_item->hfile->filename,dbg_ipset_fill(&ips_item->hfile->ipset));
else
VPRINT("profile %d exclude fixed ipset (%s)\n",dpl->dp.n,dbg_ipset_fill(&ips_item->hfile->ipset));
} }
} }

View File

@ -9,3 +9,4 @@ bool LoadAllIpsets();
bool IpsetCheck(const struct desync_profile *dp, const struct in_addr *ipv4, const struct in6_addr *ipv6); bool IpsetCheck(const struct desync_profile *dp, const struct in_addr *ipv4, const struct in6_addr *ipv6);
struct ipset_file *RegisterIpset(struct desync_profile *dp, bool bExclude, const char *filename); struct ipset_file *RegisterIpset(struct desync_profile *dp, bool bExclude, const char *filename);
void IpsetsDebug(); void IpsetsDebug();
bool AppendIpsetItem(ipset *ips, char *ip);

View File

@ -154,18 +154,22 @@ void strlist_destroy(struct str_list_head *head)
struct hostlist_file *hostlist_files_add(struct hostlist_files_head *head, const char *filename) struct hostlist_file *hostlist_files_add(struct hostlist_files_head *head, const char *filename)
{ {
struct hostlist_file *entry = malloc(sizeof(struct hostlist_file)); struct hostlist_file *entry = malloc(sizeof(struct hostlist_file));
if (entry) if (entry)
{ {
if (!(entry->filename = strdup(filename))) if (filename)
{ {
free(entry); if (!(entry->filename = strdup(filename)))
return false; {
free(entry);
return false;
}
} }
entry->mod_time=0; else
entry->filename = NULL;
entry->mod_time = 0;
entry->hostlist = NULL; entry->hostlist = NULL;
LIST_INSERT_HEAD(head, entry, next); LIST_INSERT_HEAD(head, entry, next);
} }
@ -192,7 +196,7 @@ struct hostlist_file *hostlist_files_search(struct hostlist_files_head *head, co
LIST_FOREACH(hfile, head, next) LIST_FOREACH(hfile, head, next)
{ {
if (!strcmp(hfile->filename,filename)) if (hfile->filename && !strcmp(hfile->filename,filename))
return hfile; return hfile;
} }
return NULL; return NULL;
@ -223,7 +227,7 @@ struct hostlist_item *hostlist_collection_search(struct hostlist_collection_head
LIST_FOREACH(item, head, next) LIST_FOREACH(item, head, next)
{ {
if (!strcmp(item->hfile->filename,filename)) if (item->hfile->filename && !strcmp(item->hfile->filename,filename))
return item; return item;
} }
return NULL; return NULL;
@ -369,12 +373,17 @@ struct ipset_file *ipset_files_add(struct ipset_files_head *head, const char *fi
struct ipset_file *entry = malloc(sizeof(struct ipset_file)); struct ipset_file *entry = malloc(sizeof(struct ipset_file));
if (entry) if (entry)
{ {
if (!(entry->filename = strdup(filename))) if (filename)
{ {
free(entry); if (!(entry->filename = strdup(filename)))
return false; {
free(entry);
return false;
}
} }
entry->mod_time=0; else
entry->filename = NULL;
entry->mod_time = 0;
memset(&entry->ipset,0,sizeof(entry->ipset)); memset(&entry->ipset,0,sizeof(entry->ipset));
LIST_INSERT_HEAD(head, entry, next); LIST_INSERT_HEAD(head, entry, next);
} }
@ -401,7 +410,7 @@ struct ipset_file *ipset_files_search(struct ipset_files_head *head, const char
LIST_FOREACH(hfile, head, next) LIST_FOREACH(hfile, head, next)
{ {
if (!strcmp(hfile->filename,filename)) if (hfile->filename && !strcmp(hfile->filename,filename))
return hfile; return hfile;
} }
return NULL; return NULL;
@ -432,7 +441,7 @@ struct ipset_item *ipset_collection_search(struct ipset_collection_head *head, c
LIST_FOREACH(item, head, next) LIST_FOREACH(item, head, next)
{ {
if (!strcmp(item->hfile->filename,filename)) if (item->hfile->filename && !strcmp(item->hfile->filename,filename))
return item; return item;
} }
return NULL; return NULL;

View File

@ -182,10 +182,14 @@ static void exithelp(void)
" --filter-tcp=[~]port1[-port2]|*\t; TCP port filter. ~ means negation. multiple comma separated values allowed.\n" " --filter-tcp=[~]port1[-port2]|*\t; TCP port filter. ~ means negation. multiple comma separated values allowed.\n"
" --filter-l7=[http|tls|unknown]\t\t; L6-L7 protocol filter. multiple comma separated values allowed.\n" " --filter-l7=[http|tls|unknown]\t\t; L6-L7 protocol filter. multiple comma separated values allowed.\n"
" --ipset=<filename>\t\t\t; ipset include filter (one ip/CIDR per line, ipv4 and ipv6 accepted, gzip supported, multiple ipsets allowed)\n" " --ipset=<filename>\t\t\t; ipset include filter (one ip/CIDR per line, ipv4 and ipv6 accepted, gzip supported, multiple ipsets allowed)\n"
" --ipset-ip=<ip_list>\t\t\t; comma separated fixed subnet list\n"
" --ipset-exclude=<filename>\t\t; ipset exclude filter (one ip/CIDR per line, ipv4 and ipv6 accepted, gzip supported, multiple ipsets allowed)\n" " --ipset-exclude=<filename>\t\t; ipset exclude filter (one ip/CIDR per line, ipv4 and ipv6 accepted, gzip supported, multiple ipsets allowed)\n"
" --ipset-exclude-ip=<ip_list>\t\t; comma separated fixed subnet list\n"
"\nHOSTLIST FILTER:\n" "\nHOSTLIST FILTER:\n"
" --hostlist=<filename>\t\t\t; only act on hosts in the list (one host per line, subdomains auto apply, gzip supported, multiple hostlists allowed)\n" " --hostlist=<filename>\t\t\t; only act on hosts in the list (one host per line, subdomains auto apply, gzip supported, multiple hostlists allowed)\n"
" --hostlist-domains=<domain_list>\t; comma separated fixed domain list\n"
" --hostlist-exclude=<filename>\t\t; do not act on hosts in the list (one host per line, subdomains auto apply, gzip supported, multiple hostlists allowed)\n" " --hostlist-exclude=<filename>\t\t; do not act on hosts in the list (one host per line, subdomains auto apply, gzip supported, multiple hostlists allowed)\n"
" --hostlist-exclude-domains=<domain_list> ; comma separated fixed domain list\n"
" --hostlist-auto=<filename>\t\t; detect DPI blocks and build hostlist automatically\n" " --hostlist-auto=<filename>\t\t; detect DPI blocks and build hostlist automatically\n"
" --hostlist-auto-fail-threshold=<int>\t; how many failed attempts cause hostname to be added to auto hostlist (default : %d)\n" " --hostlist-auto-fail-threshold=<int>\t; how many failed attempts cause hostname to be added to auto hostlist (default : %d)\n"
" --hostlist-auto-fail-time=<int>\t; all failed attemps must be within these seconds (default : %d)\n" " --hostlist-auto-fail-time=<int>\t; all failed attemps must be within these seconds (default : %d)\n"
@ -484,6 +488,46 @@ static bool parse_pf_list(char *opt, struct port_filters_head *pfl)
return true; return true;
} }
static bool parse_domain_list(char *opt, strpool **pp)
{
char *e,*p,c;
for (p=opt ; p ; )
{
if ((e = strchr(p,',')))
{
c=*e;
*e=0;
}
if (*p && !AppendHostlistItem(pp,p)) return false;
if (e) *e++=c;
p = e;
}
return true;
}
static bool parse_ip_list(char *opt, ipset *pp)
{
char *e,*p,c;
for (p=opt ; p ; )
{
if ((e = strchr(p,',')))
{
c=*e;
*e=0;
}
if (*p && !AppendIpsetItem(pp,p)) return false;
if (e) *e++=c;
p = e;
}
return true;
}
#if !defined( __OpenBSD__) && !defined(__ANDROID__) #if !defined( __OpenBSD__) && !defined(__ANDROID__)
// no static to not allow optimizer to inline this func (save stack) // no static to not allow optimizer to inline this func (save stack)
void config_from_file(const char *filename) void config_from_file(const char *filename)
@ -526,6 +570,8 @@ void parse_params(int argc, char *argv[])
int option_index = 0; int option_index = 0;
int v, i; int v, i;
bool bSkip=false; bool bSkip=false;
struct hostlist_file *anon_hl = NULL, *anon_hl_exclude = NULL;
struct ipset_file *anon_ips = NULL, *anon_ips_exclude = NULL;
memset(&params, 0, sizeof(params)); memset(&params, 0, sizeof(params));
params.maxconn = DEFAULT_MAX_CONN; params.maxconn = DEFAULT_MAX_CONN;
@ -611,46 +657,50 @@ void parse_params(int argc, char *argv[])
{ "tlsrec",required_argument,0,0 },// optidx=34 { "tlsrec",required_argument,0,0 },// optidx=34
{ "tlsrec-pos",required_argument,0,0 },// optidx=35 { "tlsrec-pos",required_argument,0,0 },// optidx=35
{ "hostlist",required_argument,0,0 },// optidx=36 { "hostlist",required_argument,0,0 },// optidx=36
{ "hostlist-exclude",required_argument,0,0 },// optidx=37 { "hostlist-domains",required_argument,0,0 },// optidx=37
{ "hostlist-auto",required_argument,0,0}, // optidx=38 { "hostlist-exclude",required_argument,0,0 },// optidx=38
{ "hostlist-auto-fail-threshold",required_argument,0,0}, // optidx=39 { "hostlist-exclude-domains",required_argument,0,0 },// optidx=39
{ "hostlist-auto-fail-time",required_argument,0,0}, // optidx=40 { "hostlist-auto",required_argument,0,0}, // optidx=40
{ "hostlist-auto-debug",required_argument,0,0}, // optidx=41 { "hostlist-auto-fail-threshold",required_argument,0,0}, // optidx=41
{ "pidfile",required_argument,0,0 },// optidx=42 { "hostlist-auto-fail-time",required_argument,0,0}, // optidx=42
{ "debug",optional_argument,0,0 },// optidx=43 { "hostlist-auto-debug",required_argument,0,0}, // optidx=43
{ "debug-level",required_argument,0,0 },// optidx=44 { "pidfile",required_argument,0,0 },// optidx=44
{ "local-rcvbuf",required_argument,0,0 },// optidx=45 { "debug",optional_argument,0,0 },// optidx=45
{ "local-sndbuf",required_argument,0,0 },// optidx=46 { "debug-level",required_argument,0,0 },// optidx=46
{ "remote-rcvbuf",required_argument,0,0 },// optidx=47 { "local-rcvbuf",required_argument,0,0 },// optidx=47
{ "remote-sndbuf",required_argument,0,0 },// optidx=48 { "local-sndbuf",required_argument,0,0 },// optidx=48
{ "socks",no_argument,0,0 },// optidx=40 { "remote-rcvbuf",required_argument,0,0 },// optidx=49
{ "no-resolve",no_argument,0,0 },// optidx=50 { "remote-sndbuf",required_argument,0,0 },// optidx=50
{ "resolver-threads",required_argument,0,0 },// optidx=51 { "socks",no_argument,0,0 },// optidx=51
{ "skip-nodelay",no_argument,0,0 },// optidx=52 { "no-resolve",no_argument,0,0 },// optidx=52
{ "tamper-start",required_argument,0,0 },// optidx=53 { "resolver-threads",required_argument,0,0 },// optidx=53
{ "tamper-cutoff",required_argument,0,0 },// optidx=54 { "skip-nodelay",no_argument,0,0 },// optidx=54
{ "connect-bind-addr",required_argument,0,0 },// optidx=55 { "tamper-start",required_argument,0,0 },// optidx=55
{ "tamper-cutoff",required_argument,0,0 },// optidx=56
{ "connect-bind-addr",required_argument,0,0 },// optidx=57
{ "new",no_argument,0,0 }, // optidx=56 { "new",no_argument,0,0 }, // optidx=58
{ "skip",no_argument,0,0 }, // optidx=57 { "skip",no_argument,0,0 }, // optidx=59
{ "filter-l3",required_argument,0,0 }, // optidx=58 { "filter-l3",required_argument,0,0 }, // optidx=60
{ "filter-tcp",required_argument,0,0 }, // optidx=59 { "filter-tcp",required_argument,0,0 }, // optidx=61
{ "filter-l7",required_argument,0,0 }, // optidx=60 { "filter-l7",required_argument,0,0 }, // optidx=62
{ "ipset",required_argument,0,0 }, // optidx=61 { "ipset",required_argument,0,0 }, // optidx=63
{ "ipset-exclude",required_argument,0,0 }, // optidx=62 { "ipset-ip",required_argument,0,0 }, // optidx=64
{ "ipset-exclude",required_argument,0,0 }, // optidx=65
{ "ipset-exclude-ip",required_argument,0,0 }, // optidx=66
#if defined(__FreeBSD__) #if defined(__FreeBSD__)
{ "enable-pf",no_argument,0,0 },// optidx=62 { "enable-pf",no_argument,0,0 },// optidx=67
#elif defined(__APPLE__) #elif defined(__APPLE__)
{ "local-tcp-user-timeout",required_argument,0,0 }, // optidx=63 { "local-tcp-user-timeout",required_argument,0,0 }, // optidx=67
{ "remote-tcp-user-timeout",required_argument,0,0 }, // optidx=64 { "remote-tcp-user-timeout",required_argument,0,0 }, // optidx=68
#elif defined(__linux__) #elif defined(__linux__)
{ "local-tcp-user-timeout",required_argument,0,0 }, // optidx=63 { "local-tcp-user-timeout",required_argument,0,0 }, // optidx=67
{ "remote-tcp-user-timeout",required_argument,0,0 }, // optidx=64 { "remote-tcp-user-timeout",required_argument,0,0 }, // optidx=68
{ "mss",required_argument,0,0 }, // optidx=65 { "mss",required_argument,0,0 }, // optidx=69
{ "fix-seg",optional_argument,0,0 }, // optidx=66 { "fix-seg",optional_argument,0,0 }, // optidx=70
#ifdef SPLICE_PRESENT #ifdef SPLICE_PRESENT
{ "nosplice",no_argument,0,0 }, // optidx=67 { "nosplice",no_argument,0,0 }, // optidx=71
#endif #endif
#endif #endif
{ "hostlist-auto-retrans-threshold",optional_argument,0,0}, // ignored. for nfqws command line compatibility { "hostlist-auto-retrans-threshold",optional_argument,0,0}, // ignored. for nfqws command line compatibility
@ -948,6 +998,7 @@ void parse_params(int argc, char *argv[])
params.tamper = true; params.tamper = true;
break; break;
case 36: /* hostlist */ case 36: /* hostlist */
if (bSkip) break;
if (!RegisterHostlist(dp, false, optarg)) if (!RegisterHostlist(dp, false, optarg))
{ {
DLOG_ERR("failed to register hostlist '%s'\n", optarg); DLOG_ERR("failed to register hostlist '%s'\n", optarg);
@ -955,7 +1006,22 @@ void parse_params(int argc, char *argv[])
} }
params.tamper = true; params.tamper = true;
break; break;
case 37: /* hostlist-exclude */ case 37: /* hostlist-domains */
if (bSkip) break;
if (!anon_hl && !(anon_hl=RegisterHostlist(dp, false, NULL)))
{
DLOG_ERR("failed to register anonymous hostlist\n");
exit_clean(1);
}
if (!parse_domain_list(optarg, &anon_hl->hostlist))
{
DLOG_ERR("failed to add domains to anonymous hostlist\n");
exit_clean(1);
}
params.tamper = true;
break;
case 38: /* hostlist-exclude */
if (bSkip) break;
if (!RegisterHostlist(dp, true, optarg)) if (!RegisterHostlist(dp, true, optarg))
{ {
DLOG_ERR("failed to register hostlist '%s'\n", optarg); DLOG_ERR("failed to register hostlist '%s'\n", optarg);
@ -963,7 +1029,22 @@ void parse_params(int argc, char *argv[])
} }
params.tamper = true; params.tamper = true;
break; break;
case 38: /* hostlist-auto */ case 39: /* hostlist-exclude-domains */
if (bSkip) break;
if (!anon_hl_exclude && !(anon_hl_exclude=RegisterHostlist(dp, true, NULL)))
{
DLOG_ERR("failed to register anonymous hostlist\n");
exit_clean(1);
}
if (!parse_domain_list(optarg, &anon_hl_exclude->hostlist))
{
DLOG_ERR("failed to add domains to anonymous hostlist\n");
exit_clean(1);
}
params.tamper = true;
break;
case 40: /* hostlist-auto */
if (bSkip) break;
if (dp->hostlist_auto) if (dp->hostlist_auto)
{ {
DLOG_ERR("only one auto hostlist per profile is supported\n"); DLOG_ERR("only one auto hostlist per profile is supported\n");
@ -991,7 +1072,7 @@ void parse_params(int argc, char *argv[])
} }
params.tamper = true; // need to detect blocks and update autohostlist. cannot just slice. params.tamper = true; // need to detect blocks and update autohostlist. cannot just slice.
break; break;
case 39: /* hostlist-auto-fail-threshold */ case 41: /* hostlist-auto-fail-threshold */
dp->hostlist_auto_fail_threshold = (uint8_t)atoi(optarg); dp->hostlist_auto_fail_threshold = (uint8_t)atoi(optarg);
if (dp->hostlist_auto_fail_threshold<1 || dp->hostlist_auto_fail_threshold>20) if (dp->hostlist_auto_fail_threshold<1 || dp->hostlist_auto_fail_threshold>20)
{ {
@ -999,7 +1080,7 @@ void parse_params(int argc, char *argv[])
exit_clean(1); exit_clean(1);
} }
break; break;
case 40: /* hostlist-auto-fail-time */ case 42: /* hostlist-auto-fail-time */
dp->hostlist_auto_fail_time = (uint8_t)atoi(optarg); dp->hostlist_auto_fail_time = (uint8_t)atoi(optarg);
if (dp->hostlist_auto_fail_time<1) if (dp->hostlist_auto_fail_time<1)
{ {
@ -1007,7 +1088,7 @@ void parse_params(int argc, char *argv[])
exit_clean(1); exit_clean(1);
} }
break; break;
case 41: /* hostlist-auto-debug */ case 43: /* hostlist-auto-debug */
{ {
FILE *F = fopen(optarg,"a+t"); FILE *F = fopen(optarg,"a+t");
if (!F) if (!F)
@ -1020,11 +1101,11 @@ void parse_params(int argc, char *argv[])
params.hostlist_auto_debuglog[sizeof(params.hostlist_auto_debuglog) - 1] = '\0'; params.hostlist_auto_debuglog[sizeof(params.hostlist_auto_debuglog) - 1] = '\0';
} }
break; break;
case 42: /* pidfile */ case 44: /* pidfile */
strncpy(params.pidfile,optarg,sizeof(params.pidfile)); strncpy(params.pidfile,optarg,sizeof(params.pidfile));
params.pidfile[sizeof(params.pidfile)-1]='\0'; params.pidfile[sizeof(params.pidfile)-1]='\0';
break; break;
case 43: /* debug */ case 45: /* debug */
if (optarg) if (optarg)
{ {
if (*optarg=='@') if (*optarg=='@')
@ -1058,44 +1139,44 @@ void parse_params(int argc, char *argv[])
params.debug_target = LOG_TARGET_CONSOLE; params.debug_target = LOG_TARGET_CONSOLE;
} }
break; break;
case 44: /* debug-level */ case 46: /* debug-level */
params.debug = atoi(optarg); params.debug = atoi(optarg);
break; break;
case 45: /* local-rcvbuf */ case 47: /* local-rcvbuf */
#ifdef __linux__ #ifdef __linux__
params.local_rcvbuf = atoi(optarg)/2; params.local_rcvbuf = atoi(optarg)/2;
#else #else
params.local_rcvbuf = atoi(optarg); params.local_rcvbuf = atoi(optarg);
#endif #endif
break; break;
case 46: /* local-sndbuf */ case 48: /* local-sndbuf */
#ifdef __linux__ #ifdef __linux__
params.local_sndbuf = atoi(optarg)/2; params.local_sndbuf = atoi(optarg)/2;
#else #else
params.local_sndbuf = atoi(optarg); params.local_sndbuf = atoi(optarg);
#endif #endif
break; break;
case 47: /* remote-rcvbuf */ case 49: /* remote-rcvbuf */
#ifdef __linux__ #ifdef __linux__
params.remote_rcvbuf = atoi(optarg)/2; params.remote_rcvbuf = atoi(optarg)/2;
#else #else
params.remote_rcvbuf = atoi(optarg); params.remote_rcvbuf = atoi(optarg);
#endif #endif
break; break;
case 48: /* remote-sndbuf */ case 50: /* remote-sndbuf */
#ifdef __linux__ #ifdef __linux__
params.remote_sndbuf = atoi(optarg)/2; params.remote_sndbuf = atoi(optarg)/2;
#else #else
params.remote_sndbuf = atoi(optarg); params.remote_sndbuf = atoi(optarg);
#endif #endif
break; break;
case 49: /* socks */ case 51: /* socks */
params.proxy_type = CONN_TYPE_SOCKS; params.proxy_type = CONN_TYPE_SOCKS;
break; break;
case 50: /* no-resolve */ case 52: /* no-resolve */
params.no_resolve = true; params.no_resolve = true;
break; break;
case 51: /* resolver-threads */ case 53: /* resolver-threads */
params.resolver_threads = atoi(optarg); params.resolver_threads = atoi(optarg);
if (params.resolver_threads<1 || params.resolver_threads>300) if (params.resolver_threads<1 || params.resolver_threads>300)
{ {
@ -1103,10 +1184,10 @@ void parse_params(int argc, char *argv[])
exit_clean(1); exit_clean(1);
} }
break; break;
case 52: /* skip-nodelay */ case 54: /* skip-nodelay */
params.skip_nodelay = true; params.skip_nodelay = true;
break; break;
case 53: /* tamper-start */ case 55: /* tamper-start */
{ {
const char *p=optarg; const char *p=optarg;
if (*p=='n') if (*p=='n')
@ -1120,7 +1201,7 @@ void parse_params(int argc, char *argv[])
} }
params.tamper_lim = true; params.tamper_lim = true;
break; break;
case 54: /* tamper-cutoff */ case 56: /* tamper-cutoff */
{ {
const char *p=optarg; const char *p=optarg;
if (*p=='n') if (*p=='n')
@ -1134,7 +1215,7 @@ void parse_params(int argc, char *argv[])
} }
params.tamper_lim = true; params.tamper_lim = true;
break; break;
case 55: /* connect-bind-addr */ case 57: /* connect-bind-addr */
{ {
char *p = strchr(optarg,'%'); char *p = strchr(optarg,'%');
if (p) *p++=0; if (p) *p++=0;
@ -1162,7 +1243,7 @@ void parse_params(int argc, char *argv[])
break; break;
case 56: /* new */ case 58: /* new */
if (bSkip) if (bSkip)
{ {
dp_clear(dp); dp_clear(dp);
@ -1180,32 +1261,35 @@ void parse_params(int argc, char *argv[])
dp = &dpl->dp; dp = &dpl->dp;
dp->n = ++desync_profile_count; dp->n = ++desync_profile_count;
} }
anon_hl = anon_hl_exclude = NULL;
anon_ips = anon_ips_exclude = NULL;
break; break;
case 57: /* skip */ case 59: /* skip */
bSkip = true; bSkip = true;
break; break;
case 58: /* filter-l3 */ case 60: /* filter-l3 */
if (!wf_make_l3(optarg,&dp->filter_ipv4,&dp->filter_ipv6)) if (!wf_make_l3(optarg,&dp->filter_ipv4,&dp->filter_ipv6))
{ {
DLOG_ERR("bad value for --filter-l3\n"); DLOG_ERR("bad value for --filter-l3\n");
exit_clean(1); exit_clean(1);
} }
break; break;
case 59: /* filter-tcp */ case 61: /* filter-tcp */
if (!parse_pf_list(optarg,&dp->pf_tcp)) if (!parse_pf_list(optarg,&dp->pf_tcp))
{ {
DLOG_ERR("Invalid port filter : %s\n",optarg); DLOG_ERR("Invalid port filter : %s\n",optarg);
exit_clean(1); exit_clean(1);
} }
break; break;
case 60: /* filter-l7 */ case 62: /* filter-l7 */
if (!parse_l7_list(optarg,&dp->filter_l7)) if (!parse_l7_list(optarg,&dp->filter_l7))
{ {
DLOG_ERR("Invalid l7 filter : %s\n",optarg); DLOG_ERR("Invalid l7 filter : %s\n",optarg);
exit_clean(1); exit_clean(1);
} }
break; break;
case 61: /* ipset */ case 63: /* ipset */
if (bSkip) break;
if (!RegisterIpset(dp, false, optarg)) if (!RegisterIpset(dp, false, optarg))
{ {
DLOG_ERR("failed to register ipset '%s'\n", optarg); DLOG_ERR("failed to register ipset '%s'\n", optarg);
@ -1213,7 +1297,22 @@ void parse_params(int argc, char *argv[])
} }
params.tamper = true; params.tamper = true;
break; break;
case 62: /* ipset-exclude */ case 64: /* ipset-ip */
if (bSkip) break;
if (!anon_ips && !(anon_ips=RegisterIpset(dp, false, NULL)))
{
DLOG_ERR("failed to register anonymous ipset\n");
exit_clean(1);
}
if (!parse_ip_list(optarg, &anon_ips->ipset))
{
DLOG_ERR("failed to add subnets to anonymous ipset\n");
exit_clean(1);
}
params.tamper = true;
break;
case 65: /* ipset-exclude */
if (bSkip) break;
if (!RegisterIpset(dp, true, optarg)) if (!RegisterIpset(dp, true, optarg))
{ {
DLOG_ERR("failed to register ipset '%s'\n", optarg); DLOG_ERR("failed to register ipset '%s'\n", optarg);
@ -1221,13 +1320,27 @@ void parse_params(int argc, char *argv[])
} }
params.tamper = true; params.tamper = true;
break; break;
case 66: /* ipset-exclude-ip */
if (bSkip) break;
if (!anon_ips_exclude && !(anon_ips_exclude=RegisterIpset(dp, true, NULL)))
{
DLOG_ERR("failed to register anonymous ipset\n");
exit_clean(1);
}
if (!parse_ip_list(optarg, &anon_ips_exclude->ipset))
{
DLOG_ERR("failed to add subnets to anonymous ipset\n");
exit_clean(1);
}
params.tamper = true;
break;
#if defined(__FreeBSD__) #if defined(__FreeBSD__)
case 63: /* enable-pf */ case 67: /* enable-pf */
params.pf_enable = true; params.pf_enable = true;
break; break;
#elif defined(__linux__) || defined(__APPLE__) #elif defined(__linux__) || defined(__APPLE__)
case 63: /* local-tcp-user-timeout */ case 67: /* local-tcp-user-timeout */
params.tcp_user_timeout_local = atoi(optarg); params.tcp_user_timeout_local = atoi(optarg);
if (params.tcp_user_timeout_local<0 || params.tcp_user_timeout_local>86400) if (params.tcp_user_timeout_local<0 || params.tcp_user_timeout_local>86400)
{ {
@ -1235,7 +1348,7 @@ void parse_params(int argc, char *argv[])
exit_clean(1); exit_clean(1);
} }
break; break;
case 64: /* remote-tcp-user-timeout */ case 68: /* remote-tcp-user-timeout */
params.tcp_user_timeout_remote = atoi(optarg); params.tcp_user_timeout_remote = atoi(optarg);
if (params.tcp_user_timeout_remote<0 || params.tcp_user_timeout_remote>86400) if (params.tcp_user_timeout_remote<0 || params.tcp_user_timeout_remote>86400)
{ {
@ -1246,7 +1359,7 @@ void parse_params(int argc, char *argv[])
#endif #endif
#if defined(__linux__) #if defined(__linux__)
case 65: /* mss */ case 69: /* mss */
// this option does not work in any BSD and MacOS. OS may accept but it changes nothing // this option does not work in any BSD and MacOS. OS may accept but it changes nothing
dp->mss = atoi(optarg); dp->mss = atoi(optarg);
if (dp->mss<88 || dp->mss>32767) if (dp->mss<88 || dp->mss>32767)
@ -1255,7 +1368,7 @@ void parse_params(int argc, char *argv[])
exit_clean(1); exit_clean(1);
} }
break; break;
case 66: /* fix-seg */ case 70: /* fix-seg */
if (!params.fix_seg_avail) if (!params.fix_seg_avail)
{ {
DLOG_ERR("--fix-seg is supported since kernel 4.6\n"); DLOG_ERR("--fix-seg is supported since kernel 4.6\n");
@ -1275,7 +1388,7 @@ void parse_params(int argc, char *argv[])
params.fix_seg = FIX_SEG_DEFAULT_MAX_WAIT; params.fix_seg = FIX_SEG_DEFAULT_MAX_WAIT;
break; break;
#ifdef SPLICE_PRESENT #ifdef SPLICE_PRESENT
case 67: /* nosplice */ case 71: /* nosplice */
params.nosplice = true; params.nosplice = true;
break; break;
#endif #endif
@ -1499,6 +1612,15 @@ struct salisten_s
int bind_wait_ip_left; // how much seconds left from bind_wait_ip int bind_wait_ip_left; // how much seconds left from bind_wait_ip
}; };
static const char *bindll_s[] = { "unwanted","no","prefer","force" }; static const char *bindll_s[] = { "unwanted","no","prefer","force" };
#define STRINGIFY(x) #x
#define TOSTRING(x) STRINGIFY(x)
#if defined(ZAPRET_GH_VER) || defined (ZAPRET_GH_HASH)
#define PRINT_VER printf("github version %s (%s)\n\n", TOSTRING(ZAPRET_GH_VER), TOSTRING(ZAPRET_GH_HASH))
#else
#define PRINT_VER printf("self-built version %s %s\n\n", __DATE__, __TIME__)
#endif
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
int i, listen_fd[MAX_BINDS], yes = 1, retval = 0, if_index, exit_v=EXIT_FAILURE; int i, listen_fd[MAX_BINDS], yes = 1, retval = 0, if_index, exit_v=EXIT_FAILURE;
@ -1509,6 +1631,8 @@ int main(int argc, char *argv[])
srand(time(NULL)); srand(time(NULL));
mask_from_preflen6_prepare(); mask_from_preflen6_prepare();
PRINT_VER;
parse_params(argc, argv); parse_params(argc, argv);
argv=NULL; argc=0; argv=NULL; argc=0;