50 changed files with 4237 additions and 1737 deletions
@ -0,0 +1,5 @@
|
||||
In file included from src/etcp_connections.c:1: |
||||
src/etcp_connections.h:6:10: fatal error: etcp_sockets.h: Нет такого файла или каталога |
||||
6 | #include "etcp_sockets.h" |
||||
| ^~~~~~~~~~~~~~~~ |
||||
compilation terminated. |
||||
@ -1,30 +0,0 @@
|
||||
# AGENTS.md - uTun Development Guide |
||||
|
||||
This document provides essential information for agentic coding assistants working on the uTun VPN tunnel project. |
||||
Совместимость со станым при доработках сохранять не надо. при переделке старые хвосты надо удалять. |
||||
|
||||
Если не работает - добавляй отладочную информацию чтобы быстрее найти проблемное место и не рушить работающий код. |
||||
если отладочная информация будет флудить сделай ее отключаемой или подумай как ограничить ее вывод по возможности сохраняя информативность. |
||||
Добавляй в код структуры для статистики (например суммируй число ошибок, вызовов и других потенциально нужных для анализа при ошибках метрик). |
||||
добавляй в тест подсчет времени сколько каждый этап длился для лучшего понимания оптимизации |
||||
перед запуском тестов не забывай их пересобирать |
||||
|
||||
веди changelog.txt: дата время: что поменялось |
||||
задача протокола - обеспечивать минимальную задержку при большом трафике. т.е. держать необходимый минимум данных в очередях. |
||||
дизайн - однопоточный асинхронный. |
||||
все ожидающие операции - через сокеты(дескрипторы) и таймауты -> u_async |
||||
все очереди через ll_queue |
||||
главный модуль обслуживания подключения - connection |
||||
unit-tests: для каждого теста в начале файла теста описывай что и как он тестирует - кратко но указыая на нюансы если они есть. |
||||
Если код не собирается и в этом месте написано #указание <текст> - то это указание надо выполнить в приоритетном порядке. |
||||
|
||||
не используй shell для редактирования - много ошибок допускаешь. есть встроенные инструменты. |
||||
|
||||
## Code Style Guidelines |
||||
|
||||
комменты в коде на русском |
||||
используй по возможности структуры а не typedef, пример: struct STRUCT_NAME {...}; - прототипы структур ЗАГЛАВНЫМИ БУКВАМИ |
||||
|
||||
Приоритет - простое (логически понятное, минималистичное api, но функциональное). Всегда надо думать как сделать проще и красивее. не надо нагромождать лишнего - сперва подумай действительно ли оно нужно. |
||||
|
||||
рассуждай на английском, остальное лучше на русском (отчёты, дальшейшие шаги и ответы на запросы всегда на русском) |
||||
@ -0,0 +1,153 @@
|
||||
/* config.h. Generated from config.h.in by configure. */ |
||||
/* config.h.in. Generated from configure.ac by autoheader. */ |
||||
|
||||
/* Define to 1 if you have the <arpa/inet.h> header file. */ |
||||
#define HAVE_ARPA_INET_H 1 |
||||
|
||||
/* Define to 1 if you have the <fcntl.h> header file. */ |
||||
#define HAVE_FCNTL_H 1 |
||||
|
||||
/* Define to 1 if you have the `gettimeofday' function. */ |
||||
#define HAVE_GETTIMEOFDAY 1 |
||||
|
||||
/* Define to 1 if you have the <inttypes.h> header file. */ |
||||
#define HAVE_INTTYPES_H 1 |
||||
|
||||
/* Define to 1 if you have the `crypto' library (-lcrypto). */ |
||||
#define HAVE_LIBCRYPTO 1 |
||||
|
||||
/* Define to 1 if you have the <limits.h> header file. */ |
||||
#define HAVE_LIMITS_H 1 |
||||
|
||||
/* Define to 1 if your system has a GNU libc compatible `malloc' function, and
|
||||
to 0 otherwise. */ |
||||
#define HAVE_MALLOC 1 |
||||
|
||||
/* Define to 1 if you have the `memset' function. */ |
||||
#define HAVE_MEMSET 1 |
||||
|
||||
/* Define to 1 if you have the <netinet/in.h> header file. */ |
||||
#define HAVE_NETINET_IN_H 1 |
||||
|
||||
/* Define to 1 if you have the `socket' function. */ |
||||
#define HAVE_SOCKET 1 |
||||
|
||||
/* Define to 1 if you have the <stdint.h> header file. */ |
||||
#define HAVE_STDINT_H 1 |
||||
|
||||
/* Define to 1 if you have the <stdio.h> header file. */ |
||||
#define HAVE_STDIO_H 1 |
||||
|
||||
/* Define to 1 if you have the <stdlib.h> header file. */ |
||||
#define HAVE_STDLIB_H 1 |
||||
|
||||
/* Define to 1 if you have the `strchr' function. */ |
||||
#define HAVE_STRCHR 1 |
||||
|
||||
/* Define to 1 if you have the `strdup' function. */ |
||||
#define HAVE_STRDUP 1 |
||||
|
||||
/* Define to 1 if you have the `strerror' function. */ |
||||
#define HAVE_STRERROR 1 |
||||
|
||||
/* Define to 1 if you have the <strings.h> header file. */ |
||||
#define HAVE_STRINGS_H 1 |
||||
|
||||
/* Define to 1 if you have the <string.h> header file. */ |
||||
#define HAVE_STRING_H 1 |
||||
|
||||
/* Define to 1 if you have the `strstr' function. */ |
||||
#define HAVE_STRSTR 1 |
||||
|
||||
/* Define to 1 if you have the <sys/ioctl.h> header file. */ |
||||
#define HAVE_SYS_IOCTL_H 1 |
||||
|
||||
/* Define to 1 if you have the <sys/socket.h> header file. */ |
||||
#define HAVE_SYS_SOCKET_H 1 |
||||
|
||||
/* Define to 1 if you have the <sys/stat.h> header file. */ |
||||
#define HAVE_SYS_STAT_H 1 |
||||
|
||||
/* Define to 1 if you have the <sys/types.h> header file. */ |
||||
#define HAVE_SYS_TYPES_H 1 |
||||
|
||||
/* Define if TUN/TAP is available */ |
||||
/* #undef HAVE_TUN_TAP */ |
||||
|
||||
/* Define to 1 if you have the <unistd.h> header file. */ |
||||
#define HAVE_UNISTD_H 1 |
||||
|
||||
/* Name of package */ |
||||
#define PACKAGE "utun" |
||||
|
||||
/* Define to the address where bug reports for this package should be sent. */ |
||||
#define PACKAGE_BUGREPORT "https://github.com/anomalyco/utun3/issues"
|
||||
|
||||
/* Define to the full name of this package. */ |
||||
#define PACKAGE_NAME "utun" |
||||
|
||||
/* Define to the full name and version of this package. */ |
||||
#define PACKAGE_STRING "utun 2.0.0" |
||||
|
||||
/* Define to the one symbol short name of this package. */ |
||||
#define PACKAGE_TARNAME "utun" |
||||
|
||||
/* Define to the home page for this package. */ |
||||
#define PACKAGE_URL "" |
||||
|
||||
/* Define to the version of this package. */ |
||||
#define PACKAGE_VERSION "2.0.0" |
||||
|
||||
/* Define to 1 if all of the C90 standard headers exist (not just the ones
|
||||
required in a freestanding environment). This macro is provided for |
||||
backward compatibility; new code need not use it. */ |
||||
#define STDC_HEADERS 1 |
||||
|
||||
/* Version number of package */ |
||||
#define VERSION "2.0.0" |
||||
|
||||
/* Define for Solaris 2.5.1 so the uint32_t typedef from <sys/synch.h>,
|
||||
<pthread.h>, or <semaphore.h> is not used. If the typedef were allowed, the |
||||
#define below would cause a syntax error. */ |
||||
/* #undef _UINT32_T */ |
||||
|
||||
/* Define for Solaris 2.5.1 so the uint64_t typedef from <sys/synch.h>,
|
||||
<pthread.h>, or <semaphore.h> is not used. If the typedef were allowed, the |
||||
#define below would cause a syntax error. */ |
||||
/* #undef _UINT64_T */ |
||||
|
||||
/* Define for Solaris 2.5.1 so the uint8_t typedef from <sys/synch.h>,
|
||||
<pthread.h>, or <semaphore.h> is not used. If the typedef were allowed, the |
||||
#define below would cause a syntax error. */ |
||||
/* #undef _UINT8_T */ |
||||
|
||||
/* Define to `__inline__' or `__inline' if that's what the C compiler
|
||||
calls it, or to nothing if 'inline' is not supported under any name. */ |
||||
#ifndef __cplusplus |
||||
/* #undef inline */ |
||||
#endif |
||||
|
||||
/* Define to rpl_malloc if the replacement function should be used. */ |
||||
/* #undef malloc */ |
||||
|
||||
/* Define to `unsigned int' if <sys/types.h> does not define. */ |
||||
/* #undef size_t */ |
||||
|
||||
/* Define to `int' if <sys/types.h> does not define. */ |
||||
/* #undef ssize_t */ |
||||
|
||||
/* Define to the type of an unsigned integer type of width exactly 16 bits if
|
||||
such a type exists and the standard includes do not define it. */ |
||||
/* #undef uint16_t */ |
||||
|
||||
/* Define to the type of an unsigned integer type of width exactly 32 bits if
|
||||
such a type exists and the standard includes do not define it. */ |
||||
/* #undef uint32_t */ |
||||
|
||||
/* Define to the type of an unsigned integer type of width exactly 64 bits if
|
||||
such a type exists and the standard includes do not define it. */ |
||||
/* #undef uint64_t */ |
||||
|
||||
/* Define to the type of an unsigned integer type of width exactly 8 bits if
|
||||
such a type exists and the standard includes do not define it. */ |
||||
/* #undef uint8_t */ |
||||
@ -0,0 +1,323 @@
|
||||
This file contains any messages produced by compilers while |
||||
running configure, to aid debugging if configure makes a mistake. |
||||
|
||||
It was created by utun configure 2.0.0, which was |
||||
generated by GNU Autoconf 2.71. Invocation command line was |
||||
|
||||
$ ../configure --no-create --no-recursion |
||||
|
||||
## --------- ## |
||||
## Platform. ## |
||||
## --------- ## |
||||
|
||||
hostname = user-Standard-PC-i440FX-PIIX-1996 |
||||
uname -m = x86_64 |
||||
uname -r = 6.14.0-37-generic |
||||
uname -s = Linux |
||||
uname -v = #37~24.04.1-Ubuntu SMP PREEMPT_DYNAMIC Thu Nov 20 10:25:38 UTC 2 |
||||
|
||||
/usr/bin/uname -p = x86_64 |
||||
/bin/uname -X = unknown |
||||
|
||||
/bin/arch = x86_64 |
||||
/usr/bin/arch -k = unknown |
||||
/usr/convex/getsysinfo = unknown |
||||
/usr/bin/hostinfo = unknown |
||||
/bin/machine = unknown |
||||
/usr/bin/oslevel = unknown |
||||
/bin/universe = unknown |
||||
|
||||
PATH: /home/vnc1/.cargo/bin/ |
||||
PATH: /usr/local/sbin/ |
||||
PATH: /usr/local/bin/ |
||||
PATH: /usr/sbin/ |
||||
PATH: /usr/bin/ |
||||
PATH: /sbin/ |
||||
PATH: /bin/ |
||||
PATH: /usr/games/ |
||||
PATH: /usr/local/games/ |
||||
PATH: /snap/bin/ |
||||
PATH: /snap/bin/ |
||||
|
||||
|
||||
## ----------- ## |
||||
## Core tests. ## |
||||
## ----------- ## |
||||
|
||||
configure:2453: looking for aux files: config.guess config.sub missing install-sh ar-lib compile |
||||
configure:2466: trying ../build-aux/ |
||||
configure:2495: ../build-aux/config.guess found |
||||
configure:2495: ../build-aux/config.sub found |
||||
configure:2495: ../build-aux/missing found |
||||
configure:2477: ../build-aux/install-sh found |
||||
configure:2495: ../build-aux/ar-lib found |
||||
configure:2495: ../build-aux/compile found |
||||
configure:2675: checking for gcc |
||||
configure:2696: found /usr/bin/gcc |
||||
configure:2707: result: gcc |
||||
configure:3060: checking for C compiler version |
||||
configure:3069: gcc --version >&5 |
||||
gcc (Ubuntu 13.3.0-6ubuntu2~24.04) 13.3.0 |
||||
Copyright (C) 2023 Free Software Foundation, Inc. |
||||
This is free software; see the source for copying conditions. There is NO |
||||
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
||||
|
||||
configure:3080: $? = 0 |
||||
configure:3069: gcc -v >&5 |
||||
Using built-in specs. |
||||
COLLECT_GCC=gcc |
||||
COLLECT_LTO_WRAPPER=/usr/libexec/gcc/x86_64-linux-gnu/13/lto-wrapper |
||||
OFFLOAD_TARGET_NAMES=nvptx-none:amdgcn-amdhsa |
||||
OFFLOAD_TARGET_DEFAULT=1 |
||||
Target: x86_64-linux-gnu |
||||
Configured with: ../src/configure -v --with-pkgversion='Ubuntu 13.3.0-6ubuntu2~24.04' --with-bugurl=file:///usr/share/doc/gcc-13/README.Bugs --enable-languages=c,ada,c++,go,d,fortran,objc,obj-c++,m2 --prefix=/usr --with-gcc-major-version-only --program-suffix=-13 --program-prefix=x86_64-linux-gnu- --enable-shared --enable-linker-build-id --libexecdir=/usr/libexec --without-included-gettext --enable-threads=posix --libdir=/usr/lib --enable-nls --enable-bootstrap --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --with-default-libstdcxx-abi=new --enable-libstdcxx-backtrace --enable-gnu-unique-object --disable-vtable-verify --enable-plugin --enable-default-pie --with-system-zlib --enable-libphobos-checking=release --with-target-system-zlib=auto --enable-objc-gc=auto --enable-multiarch --disable-werror --enable-cet --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32,m64,mx32 --enable-multilib --with-tune=generic --enable-offload-targets=nvptx-none=/build/gcc-13-fG75Ri/gcc-13-13.3.0/debian/tmp-nvptx/usr,amdgcn-amdhsa=/build/gcc-13-fG75Ri/gcc-13-13.3.0/debian/tmp-gcn/usr --enable-offload-defaulted --without-cuda-driver --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu --with-build-config=bootstrap-lto-lean --enable-link-serialization=2 |
||||
Thread model: posix |
||||
Supported LTO compression algorithms: zlib zstd |
||||
gcc version 13.3.0 (Ubuntu 13.3.0-6ubuntu2~24.04) |
||||
... rest of stderr output deleted ... |
||||
configure:3080: $? = 0 |
||||
configure:3069: gcc -V >&5 |
||||
gcc: error: unrecognized command-line option '-V' |
||||
gcc: fatal error: no input files |
||||
compilation terminated. |
||||
configure:3080: $? = 1 |
||||
configure:3069: gcc -qversion >&5 |
||||
gcc: error: unrecognized command-line option '-qversion'; did you mean '--version'? |
||||
gcc: fatal error: no input files |
||||
compilation terminated. |
||||
configure:3080: $? = 1 |
||||
configure:3069: gcc -version >&5 |
||||
gcc: error: unrecognized command-line option '-version' |
||||
gcc: fatal error: no input files |
||||
compilation terminated. |
||||
configure:3080: $? = 1 |
||||
configure:3100: checking whether the C compiler works |
||||
configure:3122: gcc conftest.c >&5 |
||||
configure:3126: $? = 0 |
||||
configure:3176: result: yes |
||||
configure:3179: checking for C compiler default output file name |
||||
configure:3181: result: a.out |
||||
configure:3187: checking for suffix of executables |
||||
configure:3194: gcc -o conftest conftest.c >&5 |
||||
configure:3198: $? = 0 |
||||
configure:3221: result: |
||||
configure:3243: checking whether we are cross compiling |
||||
configure:3251: gcc -o conftest conftest.c >&5 |
||||
configure:3255: $? = 0 |
||||
configure:3262: ./conftest |
||||
configure:3266: $? = 0 |
||||
configure:3281: result: no |
||||
configure:3286: checking for suffix of object files |
||||
configure:3309: gcc -c conftest.c >&5 |
||||
configure:3313: $? = 0 |
||||
configure:3335: result: o |
||||
configure:3339: checking whether the compiler supports GNU C |
||||
configure:3359: gcc -c conftest.c >&5 |
||||
configure:3359: $? = 0 |
||||
configure:3369: result: yes |
||||
configure:3380: checking whether gcc accepts -g |
||||
configure:3401: gcc -c -g conftest.c >&5 |
||||
configure:3401: $? = 0 |
||||
configure:3445: result: yes |
||||
configure:3465: checking for gcc option to enable C11 features |
||||
configure:3480: gcc -c -g -O2 conftest.c >&5 |
||||
configure:3480: $? = 0 |
||||
configure:3498: result: none needed |
||||
configure:3619: checking whether gcc understands -c and -o together |
||||
configure:3642: gcc -c conftest.c -o conftest2.o |
||||
configure:3645: $? = 0 |
||||
configure:3642: gcc -c conftest.c -o conftest2.o |
||||
configure:3645: $? = 0 |
||||
configure:3657: result: yes |
||||
configure:3722: checking for ranlib |
||||
configure:3743: found /usr/bin/ranlib |
||||
configure:3754: result: ranlib |
||||
configure:3832: checking for ar |
||||
configure:3853: found /usr/bin/ar |
||||
configure:3864: result: ar |
||||
configure:3890: checking the archiver (ar) interface |
||||
configure:3907: gcc -c -g -O2 conftest.c >&5 |
||||
configure:3907: $? = 0 |
||||
configure:3910: ar cru libconftest.a conftest.o >&5 |
||||
ar: `u' modifier ignored since `D' is the default (see `U') |
||||
configure:3913: $? = 0 |
||||
configure:3941: result: ar |
||||
configure:3978: checking for a BSD-compatible install |
||||
configure:4051: result: /usr/bin/install -c |
||||
configure:4062: checking whether build environment is sane |
||||
configure:4117: result: yes |
||||
configure:4272: checking for a race-free mkdir -p |
||||
configure:4316: result: /usr/bin/mkdir -p |
||||
configure:4323: checking for gawk |
||||
configure:4358: result: no |
||||
configure:4323: checking for mawk |
||||
configure:4344: found /usr/bin/mawk |
||||
configure:4355: result: mawk |
||||
configure:4366: checking whether make sets $(MAKE) |
||||
configure:4389: result: yes |
||||
configure:4411: checking whether make supports the include directive |
||||
configure:4426: make -f confmf.GNU && cat confinc.out |
||||
make[1]: Entering directory '/home/vnc1/proj/utun3/build' |
||||
make[1]: Leaving directory '/home/vnc1/proj/utun3/build' |
||||
this is the am__doit target |
||||
configure:4429: $? = 0 |
||||
configure:4448: result: yes (GNU style) |
||||
configure:4483: checking whether make supports nested variables |
||||
configure:4501: result: yes |
||||
configure:4518: error: source directory already configured; run "make distclean" there first |
||||
|
||||
## ---------------- ## |
||||
## Cache variables. ## |
||||
## ---------------- ## |
||||
|
||||
ac_cv_c_compiler_gnu=yes |
||||
ac_cv_env_CC_set= |
||||
ac_cv_env_CC_value= |
||||
ac_cv_env_CFLAGS_set= |
||||
ac_cv_env_CFLAGS_value= |
||||
ac_cv_env_CPPFLAGS_set= |
||||
ac_cv_env_CPPFLAGS_value= |
||||
ac_cv_env_LDFLAGS_set= |
||||
ac_cv_env_LDFLAGS_value= |
||||
ac_cv_env_LIBS_set= |
||||
ac_cv_env_LIBS_value= |
||||
ac_cv_env_build_alias_set= |
||||
ac_cv_env_build_alias_value= |
||||
ac_cv_env_host_alias_set= |
||||
ac_cv_env_host_alias_value= |
||||
ac_cv_env_target_alias_set= |
||||
ac_cv_env_target_alias_value= |
||||
ac_cv_objext=o |
||||
ac_cv_path_install='/usr/bin/install -c' |
||||
ac_cv_path_mkdir=/usr/bin/mkdir |
||||
ac_cv_prog_AWK=mawk |
||||
ac_cv_prog_ac_ct_AR=ar |
||||
ac_cv_prog_ac_ct_CC=gcc |
||||
ac_cv_prog_ac_ct_RANLIB=ranlib |
||||
ac_cv_prog_cc_c11= |
||||
ac_cv_prog_cc_g=yes |
||||
ac_cv_prog_cc_stdc= |
||||
ac_cv_prog_make_make_set=yes |
||||
am_cv_ar_interface=ar |
||||
am_cv_make_support_nested_variables=yes |
||||
am_cv_prog_cc_c_o=yes |
||||
|
||||
## ----------------- ## |
||||
## Output variables. ## |
||||
## ----------------- ## |
||||
|
||||
ACLOCAL='' |
||||
AMDEPBACKSLASH='\' |
||||
AMDEP_FALSE='#' |
||||
AMDEP_TRUE='' |
||||
AMTAR='' |
||||
AM_BACKSLASH='\' |
||||
AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)' |
||||
AM_DEFAULT_VERBOSITY='1' |
||||
AM_V='$(V)' |
||||
AR='ar' |
||||
AUTOCONF='' |
||||
AUTOHEADER='' |
||||
AUTOMAKE='' |
||||
AWK='mawk' |
||||
CC='gcc' |
||||
CCDEPMODE='' |
||||
CFLAGS='-g -O2' |
||||
CPPFLAGS='' |
||||
CSCOPE='' |
||||
CTAGS='' |
||||
CYGPATH_W='' |
||||
DEFS='' |
||||
DEPDIR='.deps' |
||||
ECHO_C='' |
||||
ECHO_N='-n' |
||||
ECHO_T='' |
||||
ETAGS='' |
||||
EXEEXT='' |
||||
INSTALL_DATA='${INSTALL} -m 644' |
||||
INSTALL_PROGRAM='${INSTALL}' |
||||
INSTALL_SCRIPT='${INSTALL}' |
||||
INSTALL_STRIP_PROGRAM='$(install_sh) -c -s' |
||||
LDFLAGS='' |
||||
LIBOBJS='' |
||||
LIBS='' |
||||
LTLIBOBJS='' |
||||
MAKEINFO='' |
||||
MKDIR_P='/usr/bin/mkdir -p' |
||||
OBJEXT='o' |
||||
PACKAGE='' |
||||
PACKAGE_BUGREPORT='https://github.com/anomalyco/utun3/issues' |
||||
PACKAGE_NAME='utun' |
||||
PACKAGE_STRING='utun 2.0.0' |
||||
PACKAGE_TARNAME='utun' |
||||
PACKAGE_URL='' |
||||
PACKAGE_VERSION='2.0.0' |
||||
PATH_SEPARATOR=':' |
||||
RANLIB='ranlib' |
||||
SET_MAKE='' |
||||
SHELL='/bin/bash' |
||||
STRIP='' |
||||
VERSION='' |
||||
ac_ct_AR='ar' |
||||
ac_ct_CC='gcc' |
||||
am__EXEEXT_FALSE='' |
||||
am__EXEEXT_TRUE='' |
||||
am__fastdepCC_FALSE='' |
||||
am__fastdepCC_TRUE='' |
||||
am__include='include' |
||||
am__isrc=' -I$(srcdir)' |
||||
am__leading_dot='.' |
||||
am__nodep='_no' |
||||
am__quote='' |
||||
am__tar='' |
||||
am__untar='' |
||||
bindir='${exec_prefix}/bin' |
||||
build='' |
||||
build_alias='' |
||||
build_cpu='' |
||||
build_os='' |
||||
build_vendor='' |
||||
datadir='${datarootdir}' |
||||
datarootdir='${prefix}/share' |
||||
docdir='${datarootdir}/doc/${PACKAGE_TARNAME}' |
||||
dvidir='${docdir}' |
||||
exec_prefix='NONE' |
||||
host='' |
||||
host_alias='' |
||||
host_cpu='' |
||||
host_os='' |
||||
host_vendor='' |
||||
htmldir='${docdir}' |
||||
includedir='${prefix}/include' |
||||
infodir='${datarootdir}/info' |
||||
install_sh='${SHELL} /home/vnc1/proj/utun3/build-aux/install-sh' |
||||
libdir='${exec_prefix}/lib' |
||||
libexecdir='${exec_prefix}/libexec' |
||||
localedir='${datarootdir}/locale' |
||||
localstatedir='${prefix}/var' |
||||
mandir='${datarootdir}/man' |
||||
mkdir_p='' |
||||
oldincludedir='/usr/include' |
||||
pdfdir='${docdir}' |
||||
prefix='NONE' |
||||
program_transform_name='s,x,x,' |
||||
psdir='${docdir}' |
||||
runstatedir='${localstatedir}/run' |
||||
sbindir='${exec_prefix}/sbin' |
||||
sharedstatedir='${prefix}/com' |
||||
sysconfdir='${prefix}/etc' |
||||
target_alias='' |
||||
|
||||
## ----------- ## |
||||
## confdefs.h. ## |
||||
## ----------- ## |
||||
|
||||
/* confdefs.h */ |
||||
#define PACKAGE_NAME "utun" |
||||
#define PACKAGE_TARNAME "utun" |
||||
#define PACKAGE_VERSION "2.0.0" |
||||
#define PACKAGE_STRING "utun 2.0.0" |
||||
#define PACKAGE_BUGREPORT "https://github.com/anomalyco/utun3/issues" |
||||
#define PACKAGE_URL "" |
||||
|
||||
configure: exit 1 |
||||
@ -0,0 +1,293 @@
|
||||
etcp_connections.c: In function ‘etcp_encrypt_send’: |
||||
etcp_connections.c:250:24: error: incompatible types when initializing type ‘sc_context_t *’ {aka ‘struct secure_channel *’} using type ‘struct secure_channel’ |
||||
250 | sc_context_t* sc = dgram->link->etcp->crypto_ctx; |
||||
| ^~~~~ |
||||
etcp_connections.c:252:59: warning: ‘return’ with no value, in function returning non-void |
||||
252 | if (len<=0 || len>1480) { dgram->link->send_errors++; return; } |
||||
| ^~~~~~ |
||||
etcp_connections.c:248:5: note: declared here |
||||
248 | int etcp_encrypt_send(struct ETCP_DGRAM* dgram) { |
||||
| ^~~~~~~~~~~~~~~~~ |
||||
etcp_connections.c:255:38: warning: passing argument 4 of ‘sc_encrypt’ from incompatible pointer type [-Wincompatible-pointer-types] |
||||
255 | sc_encrypt(sc, dgram->data, len, &enc_buf, &enc_buf_len); |
||||
| ^~~~~~~~ |
||||
| | |
||||
| uint8_t (*)[1600] {aka unsigned char (*)[1600]} |
||||
In file included from etcp_connections.h:4, |
||||
from etcp_connections.c:1: |
||||
secure_channel.h:61:102: note: expected ‘uint8_t *’ {aka ‘unsigned char *’} but argument is of type ‘uint8_t (*)[1600]’ {aka ‘unsigned char (*)[1600]’} |
||||
61 | sc_status_t sc_encrypt(sc_context_t *ctx, const uint8_t *plaintext, size_t plaintext_len, uint8_t *ciphertext, size_t *ciphertext_len); |
||||
| ~~~~~~~~~^~~~~~~~~~ |
||||
etcp_connections.c:256:82: warning: ‘return’ with no value, in function returning non-void |
||||
256 | if (enc_buf_len + dgram->noencrypt_len > 1480) { dgram->link->send_errors++; return; } |
||||
| ^~~~~~ |
||||
etcp_connections.c:248:5: note: declared here |
||||
248 | int etcp_encrypt_send(struct ETCP_DGRAM* dgram) { |
||||
| ^~~~~~~~~~~~~~~~~ |
||||
etcp_connections.c:259:35: error: incompatible types when initializing type ‘struct sockaddr_storage *’ using type ‘struct sockaddr_storage’ |
||||
259 | struct sockaddr_storage* addr=dgram->link->remote_addr; |
||||
| ^~~~~ |
||||
etcp_connections.c:260:27: error: ‘to_addr’ undeclared (first use in this function); did you mean ‘in_addr’? |
||||
260 | socklen_t addr_len = (to_addr->ss_family == AF_INET) ? sizeof(struct sockaddr_in) : sizeof(struct sockaddr_in6); |
||||
| ^~~~~~~ |
||||
| in_addr |
||||
etcp_connections.c:260:27: note: each undeclared identifier is reported only once for each function it appears in |
||||
etcp_connections.c:261:67: warning: passing argument 5 of ‘sendto’ from incompatible pointer type [-Wincompatible-pointer-types] |
||||
261 | ssize_t sent = sendto(dgram->link->conn->fd, enc_buf, len, 0, addr, addr_len); |
||||
| ^~~~ |
||||
| | |
||||
| struct sockaddr_storage * |
||||
In file included from etcp_connections.h:7: |
||||
/usr/include/x86_64-linux-gnu/sys/socket.h:153:58: note: expected ‘const struct sockaddr *’ but argument is of type ‘struct sockaddr_storage *’ |
||||
153 | int __flags, __CONST_SOCKADDR_ARG __addr, |
||||
| ^ |
||||
etcp_connections.c: In function ‘etcp_connections_read_callback’: |
||||
etcp_connections.c:311:33: error: ‘pkt’ undeclared (first use in this function) |
||||
311 | socklen_t addr_len = sizeof(pkt->metadata.remote_addr); |
||||
| ^~~ |
||||
etcp_connections.c:314:15: error: redefinition of ‘addr_len’ |
||||
314 | socklen_t addr_len=sizeof(addr); |
||||
| ^~~~~~~~ |
||||
etcp_connections.c:311:15: note: previous definition of ‘addr_len’ with type ‘socklen_t’ {aka ‘unsigned int’} |
||||
311 | socklen_t addr_len = sizeof(pkt->metadata.remote_addr); |
||||
| ^~~~~~~~ |
||||
etcp_connections.c:322:48: warning: passing argument 1 of ‘memory_pool_alloc’ from incompatible pointer type [-Wincompatible-pointer-types] |
||||
322 | struct ETCP_DGRAM* pkt = memory_pool_alloc(&e_sock->instance->pkt_pool); |
||||
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
| | |
||||
| struct memory_pool ** |
||||
In file included from utun_instance.h:7, |
||||
from etcp_connections.h:5: |
||||
../lib/memory_pool.h:18:45: note: expected ‘struct memory_pool *’ but argument is of type ‘struct memory_pool **’ |
||||
18 | void* memory_pool_alloc(struct memory_pool* pool); |
||||
| ~~~~~~~~~~~~~~~~~~~~^~~~ |
||||
etcp_connections.c:327:51: error: expected expression before ‘struct’ |
||||
327 | struct ETCP_LINK* link=etcp_link_find_by_addr(struct ETCP_SOCKET* e_sock, &addr); |
||||
| ^~~~~~ |
||||
etcp_connections.c:327:28: error: too few arguments to function ‘etcp_link_find_by_addr’ |
||||
327 | struct ETCP_LINK* link=etcp_link_find_by_addr(struct ETCP_SOCKET* e_sock, &addr); |
||||
| ^~~~~~~~~~~~~~~~~~~~~~ |
||||
etcp_connections.c:105:26: note: declared here |
||||
105 | static struct ETCP_LINK* etcp_link_find_by_addr(struct ETCP_SOCKET* e_sock, struct sockaddr_storage* addr) { |
||||
| ^~~~~~~~~~~~~~~~~~~~~~ |
||||
etcp_connections.c:360:41: error: invalid type argument of ‘->’ (have ‘struct secure_channel’) |
||||
360 | if (memcmp(&conn->crypto_ctx->peer_public_key, &sc.peer_public_key, SC_PUBKEY_SIZE)) { errorcode=5; goto ec_fr; }// коллизия - peer id совпал а ключи разные. |
||||
| ^~ |
||||
etcp_connections.c:362:48: error: ‘etcp’ undeclared (first use in this function) |
||||
362 | struct ETCP_LINK* link = etcp_link_new(etcp, e_sock, addr, 1); |
||||
| ^~~~ |
||||
etcp_connections.c:362:62: error: incompatible type for argument 3 of ‘etcp_link_new’ |
||||
362 | struct ETCP_LINK* link = etcp_link_new(etcp, e_sock, addr, 1); |
||||
| ^~~~ |
||||
| | |
||||
| struct sockaddr_storage |
||||
etcp_connections.c:209:108: note: expected ‘struct sockaddr_storage *’ but argument is of type ‘struct sockaddr_storage’ |
||||
209 | struct ETCP_LINK* etcp_link_new(struct ETCP_CONN* etcp, struct ETCP_SOCKET* conn, struct sockaddr_storage* remote_addr, uint8_t is_server) { |
||||
| ~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~ |
||||
etcp_connections.c:376:49: error: invalid type argument of ‘->’ (have ‘struct global_config’) |
||||
376 | int mtu=e_sock->instance->config->global->mtu; |
||||
| ^~ |
||||
etcp_connections.c:383:9: warning: implicit declaration of function ‘packet_pool_free’ [-Wimplicit-function-declaration] |
||||
383 | packet_pool_free(&e_sock->instance->pkt_pool, pkt); |
||||
| ^~~~~~~~~~~~~~~~ |
||||
etcp_connections.c:392:5: warning: implicit declaration of function ‘etcp_input’; did you mean ‘etcp_conn_input’? [-Wimplicit-function-declaration] |
||||
392 | etcp_input(pkt, conns); |
||||
| ^~~~~~~~~~ |
||||
| etcp_conn_input |
||||
etcp_connections.c:392:21: error: ‘conns’ undeclared (first use in this function); did you mean ‘confstr’? |
||||
392 | etcp_input(pkt, conns); |
||||
| ^~~~~ |
||||
| confstr |
||||
etcp_connections.c: In function ‘etcp_input’: |
||||
etcp_connections.c:405:18: error: ‘e_sock’ undeclared (first use in this function) |
||||
405 | if (!pkt || !e_sock) return -1; |
||||
| ^~~~~~ |
||||
etcp_connections.c:408:21: error: ‘struct ETCP_DGRAM’ has no member named ‘metadata’ |
||||
408 | size_t len = pkt->metadata.data_len; |
||||
| ^~ |
||||
etcp_connections.c:417:75: error: ‘struct ETCP_CONN’ has no member named ‘has_peer_key’ |
||||
417 | if (header != ETCP_INIT_REQUEST && header != ETCP_CHANNEL_INIT && etcp->has_peer_key) { |
||||
| ^~ |
||||
etcp_connections.c:419:28: error: incompatible types when initializing type ‘sc_context_t *’ {aka ‘struct secure_channel *’} using type ‘struct secure_channel’ |
||||
419 | sc_context_t* sc = etcp->crypto_ctx; |
||||
| ^~~~ |
||||
etcp_connections.c:431:83: error: ‘struct ETCP_DGRAM’ has no member named ‘metadata’ |
||||
431 | struct ETCP_LINK* link = etcp_link_find_by_addr(e_sock, (struct sockaddr*)&pkt->metadata.remote_addr, |
||||
| ^~ |
||||
etcp_connections.c:432:63: error: ‘struct ETCP_DGRAM’ has no member named ‘metadata’ |
||||
432 | sizeof(pkt->metadata.remote_addr)); |
||||
| ^~ |
||||
etcp_connections.c:431:30: error: too many arguments to function ‘etcp_link_find_by_addr’ |
||||
431 | struct ETCP_LINK* link = etcp_link_find_by_addr(e_sock, (struct sockaddr*)&pkt->metadata.remote_addr, |
||||
| ^~~~~~~~~~~~~~~~~~~~~~ |
||||
etcp_connections.c:105:26: note: declared here |
||||
105 | static struct ETCP_LINK* etcp_link_find_by_addr(struct ETCP_SOCKET* e_sock, struct sockaddr_storage* addr) { |
||||
| ^~~~~~~~~~~~~~~~~~~~~~ |
||||
etcp_connections.c:437:70: error: ‘struct ETCP_DGRAM’ has no member named ‘metadata’ |
||||
437 | link = etcp_link_new(etcp, e_sock, (struct sockaddr*)&pkt->metadata.remote_addr, |
||||
| ^~ |
||||
etcp_connections.c:438:44: error: ‘struct ETCP_DGRAM’ has no member named ‘metadata’ |
||||
438 | sizeof(pkt->metadata.remote_addr)); |
||||
| ^~ |
||||
etcp_connections.c:443:13: warning: implicit declaration of function ‘etcp_connections_send’; did you mean ‘etcp_connection_create’? [-Wimplicit-function-declaration] |
||||
443 | etcp_connections_send(e_sock, reset_pkt, 1, (struct sockaddr*)&pkt->metadata.remote_addr, sizeof(pkt->metadata.remote_addr)); |
||||
| ^~~~~~~~~~~~~~~~~~~~~ |
||||
| etcp_connection_create |
||||
etcp_connections.c:443:79: error: ‘struct ETCP_DGRAM’ has no member named ‘metadata’ |
||||
443 | etcp_connections_send(e_sock, reset_pkt, 1, (struct sockaddr*)&pkt->metadata.remote_addr, sizeof(pkt->metadata.remote_addr)); |
||||
| ^~ |
||||
etcp_connections.c:443:113: error: ‘struct ETCP_DGRAM’ has no member named ‘metadata’ |
||||
443 | etcp_connections_send(e_sock, reset_pkt, 1, (struct sockaddr*)&pkt->metadata.remote_addr, sizeof(pkt->metadata.remote_addr)); |
||||
| ^~ |
||||
etcp_connections.c:459:20: error: ‘struct ETCP_CONN’ has no member named ‘peer_public_key’ |
||||
459 | memcpy(etcp->peer_public_key, peer_pubkey, SC_PUBKEY_SIZE); |
||||
| ^~ |
||||
etcp_connections.c:460:13: error: ‘struct ETCP_CONN’ has no member named ‘has_peer_key’ |
||||
460 | etcp->has_peer_key = 1; |
||||
| ^~ |
||||
etcp_connections.c:461:36: error: incompatible type for argument 1 of ‘sc_set_peer_public_key’ |
||||
461 | sc_set_peer_public_key(etcp->crypto_ctx, peer_pubkey); |
||||
| ~~~~^~~~~~~~~~~~ |
||||
| | |
||||
| struct secure_channel |
||||
secure_channel.h:58:50: note: expected ‘sc_context_t *’ {aka ‘struct secure_channel *’} but argument is of type ‘struct secure_channel’ |
||||
58 | sc_status_t sc_set_peer_public_key(sc_context_t *ctx, const char *peer_public_key, int mode);// mode: 0-bin 1-hex key format |
||||
| ~~~~~~~~~~~~~~^~~ |
||||
etcp_connections.c:461:9: error: too few arguments to function ‘sc_set_peer_public_key’ |
||||
461 | sc_set_peer_public_key(etcp->crypto_ctx, peer_pubkey); |
||||
| ^~~~~~~~~~~~~~~~~~~~~~ |
||||
secure_channel.h:58:13: note: declared here |
||||
58 | sc_status_t sc_set_peer_public_key(sc_context_t *ctx, const char *peer_public_key, int mode);// mode: 0-bin 1-hex key format |
||||
| ^~~~~~~~~~~~~~~~~~~~~~ |
||||
etcp_connections.c:478:12: error: ‘struct ETCP_DGRAM’ has no member named ‘metadata’ |
||||
478 | pkt->metadata.channel = link; // Or etcp_channel if separate |
||||
| ^~ |
||||
etcp_connections.c:483:5: warning: implicit declaration of function ‘packet_pool_put’ [-Wimplicit-function-declaration] |
||||
483 | packet_pool_put(&etcp->packet_pool, pkt); |
||||
| ^~~~~~~~~~~~~~~ |
||||
etcp_connections.c:483:26: error: ‘struct ETCP_CONN’ has no member named ‘packet_pool’ |
||||
483 | packet_pool_put(&etcp->packet_pool, pkt); |
||||
| ^~ |
||||
etcp_connections.c: In function ‘init_connections’: |
||||
etcp_connections.c:490:29: warning: initialization of ‘struct config *’ from incompatible pointer type ‘struct utun_config *’ [-Wincompatible-pointer-types] |
||||
490 | struct config* config = instance->config; |
||||
| ^~~~~~~~ |
||||
etcp_connections.c:491:42: error: invalid use of undefined type ‘struct config’ |
||||
491 | instance->connections = calloc(config->server_count, sizeof(struct ETCP_CONN)); |
||||
| ^~ |
||||
etcp_connections.c:494:15: error: ‘struct UTUN_INSTANCE’ has no member named ‘connection_count’; did you mean ‘connections’? |
||||
494 | instance->connection_count = 0; |
||||
| ^~~~~~~~~~~~~~~~ |
||||
| connections |
||||
etcp_connections.c:496:39: error: invalid use of undefined type ‘struct config’ |
||||
496 | struct CFG_SERVER* server = config->servers; |
||||
| ^~ |
||||
etcp_connections.c:500:34: warning: implicit declaration of function ‘etcp_connection_add’; did you mean ‘etcp_connection_create’? [-Wimplicit-function-declaration] |
||||
500 | struct ETCP_CONN* conn = etcp_connection_add(instance, server->ip, server->netif_index, server->so_mark, server->type); |
||||
| ^~~~~~~~~~~~~~~~~~~ |
||||
| etcp_connection_create |
||||
etcp_connections.c:500:34: warning: initialization of ‘struct ETCP_CONN *’ from ‘int’ makes pointer from integer without a cast [-Wint-conversion] |
||||
etcp_connections.c:503:26: error: ‘etcp’ undeclared (first use in this function) |
||||
503 | etcp_destroy(etcp); |
||||
| ^~~~ |
||||
etcp_connections.c:508:36: error: ‘struct CFG_SERVER’ has no member named ‘addr’ |
||||
508 | server->name, server->addr, e_sock->num_channels); |
||||
| ^~ |
||||
etcp_connections.c:508:44: error: ‘e_sock’ undeclared (first use in this function) |
||||
508 | server->name, server->addr, e_sock->num_channels); |
||||
| ^~~~~~ |
||||
etcp_connections.c:513:31: error: invalid use of undefined type ‘struct config’ |
||||
513 | for (int j = 0; j < config->client_count; j++) { |
||||
| ^~ |
||||
etcp_connections.c:514:47: error: invalid use of undefined type ‘struct config’ |
||||
514 | struct client_config* client = &config->clients[j]; |
||||
| ^~ |
||||
etcp_connections.c:517:26: error: invalid use of undefined type ‘struct client_config’ |
||||
517 | if (strcmp(client->from, server->name) != 0) { |
||||
| ^~ |
||||
etcp_connections.c:525:31: error: ‘struct ETCP_CONN’ has no member named ‘ctx’ |
||||
525 | sc_init_ctx(&etcp_conn->ctx, &instance->my_keys); |
||||
| ^~ |
||||
etcp_connections.c:526:26: error: invalid use of undefined type ‘struct client_config’ |
||||
526 | if (strlen(client->peer_public_key_hex) > 0) { |
||||
| ^~ |
||||
etcp_connections.c:528:17: warning: implicit declaration of function ‘hex_to_binary’ [-Wimplicit-function-declaration] |
||||
528 | if (hex_to_binary(client->peer_public_key_hex, peer_key_bin, SC_PUBKEY_SIZE) == 0) { |
||||
| ^~~~~~~~~~~~~ |
||||
etcp_connections.c:528:37: error: invalid use of undefined type ‘struct client_config’ |
||||
528 | if (hex_to_binary(client->peer_public_key_hex, peer_key_bin, SC_PUBKEY_SIZE) == 0) { |
||||
| ^~ |
||||
etcp_connections.c:529:33: error: ‘struct ETCP_CONN’ has no member named ‘peer_public_key’ |
||||
529 | memcpy(etcp_conn->peer_public_key, peer_key_bin, SC_PUBKEY_SIZE); |
||||
| ^~ |
||||
etcp_connections.c:530:26: error: ‘struct ETCP_CONN’ has no member named ‘has_peer_key’ |
||||
530 | etcp_conn->has_peer_key = 1; |
||||
| ^~ |
||||
etcp_connections.c:531:49: error: incompatible type for argument 1 of ‘sc_set_peer_public_key’ |
||||
531 | sc_set_peer_public_key(etcp_conn->crypto_ctx, peer_key_bin); |
||||
| ~~~~~~~~~^~~~~~~~~~~~ |
||||
| | |
||||
| struct secure_channel |
||||
secure_channel.h:58:50: note: expected ‘sc_context_t *’ {aka ‘struct secure_channel *’} but argument is of type ‘struct secure_channel’ |
||||
58 | sc_status_t sc_set_peer_public_key(sc_context_t *ctx, const char *peer_public_key, int mode);// mode: 0-bin 1-hex key format |
||||
| ~~~~~~~~~~~~~~^~~ |
||||
etcp_connections.c:531:17: error: too few arguments to function ‘sc_set_peer_public_key’ |
||||
531 | sc_set_peer_public_key(etcp_conn->crypto_ctx, peer_key_bin); |
||||
| ^~~~~~~~~~~~~~~~~~~~~~ |
||||
secure_channel.h:58:13: note: declared here |
||||
58 | sc_status_t sc_set_peer_public_key(sc_context_t *ctx, const char *peer_public_key, int mode);// mode: 0-bin 1-hex key format |
||||
| ^~~~~~~~~~~~~~~~~~~~~~ |
||||
etcp_connections.c:537:16: error: variable ‘cl’ has initializer but incomplete type |
||||
537 | struct client_link cl=client->links; |
||||
| ^~~~~~~~~~~ |
||||
etcp_connections.c:537:37: error: invalid use of undefined type ‘struct client_config’ |
||||
537 | struct client_link cl=client->links; |
||||
| ^~ |
||||
etcp_connections.c:537:28: error: storage size of ‘cl’ isn’t known |
||||
537 | struct client_link cl=client->links; |
||||
| ^~ |
||||
etcp_connections.c:539:13: error: ‘conn’ undeclared (first use in this function) |
||||
539 | conn= (надо найти) |
||||
| ^~~~ |
||||
etcp_connections.c:539:20: error: ‘надо’ undeclared (first use in this function) |
||||
539 | conn= (надо найти) |
||||
| ^~~~ |
||||
etcp_connections.c:539:24: error: expected ‘)’ before ‘найти’ |
||||
539 | conn= (надо найти) |
||||
| ~ ^~~~~~ |
||||
| ) |
||||
etcp_connections.c:539:31: error: expected ‘;’ before ‘struct’ |
||||
539 | conn= (надо найти) |
||||
| ^ |
||||
| ; |
||||
...... |
||||
542 | struct ETCP_LINK* link = etcp_link_new(etcp, conn, cl->remote_sockaddr, sizeof(struct sockaddr_storage)); |
||||
| ~~~~~~ |
||||
In file included from etcp_connections.c:8: |
||||
etcp_connections.c:544:95: error: invalid use of undefined type ‘struct client_config’ |
||||
544 | DEBUG_ERROR(DEBUG_CATEGORY_ETCP, "Failed to create link for client %s", client->name); |
||||
| ^~ |
||||
../lib/debug_config.h:114:92: note: in definition of macro ‘DEBUG_ERROR’ |
||||
114 | debug_output(DEBUG_LEVEL_ERROR, category, __FUNCTION__, __FILE__, __LINE__, fmt, ##__VA_ARGS__); \ |
||||
| ^~~~~~~~~~~ |
||||
etcp_connections.c:550:51: error: invalid use of undefined type ‘struct client_config’ |
||||
550 | printf(" Added client %s -> %s\n", client->name, client->to_addr); |
||||
| ^~ |
||||
etcp_connections.c:550:65: error: invalid use of undefined type ‘struct client_config’ |
||||
550 | printf(" Added client %s -> %s\n", client->name, client->to_addr); |
||||
| ^~ |
||||
etcp_connections.c:554:19: error: ‘struct UTUN_INSTANCE’ has no member named ‘connection_count’; did you mean ‘connections’? |
||||
554 | if (instance->connection_count == 0) { |
||||
| ^~~~~~~~~~~~~~~~ |
||||
| connections |
||||
etcp_connections.c:561:54: error: ‘struct UTUN_INSTANCE’ has no member named ‘connection_count’; did you mean ‘connections’? |
||||
561 | printf("Initialized %d connections\n", instance->connection_count); |
||||
| ^~~~~~~~~~~~~~~~ |
||||
| connections |
||||
etcp_connections.c: At top level: |
||||
etcp_connections.c:26:12: warning: ‘etcp_link_send_init_response’ used but never defined |
||||
26 | static int etcp_link_send_init_response(struct ETCP_LINK* link, int mtu, uint16_t keepalive_interval); |
||||
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||||
make[2]: *** [Makefile:619: utun-etcp_connections.o] Ошибка 1 |
||||
make[1]: *** [Makefile:433: all-recursive] Ошибка 1 |
||||
make: *** [Makefile:353: all] Ошибка 2 |
||||
@ -0,0 +1,87 @@
|
||||
// memory_pool.c
|
||||
#include "memory_pool.h" |
||||
#include <stdlib.h> |
||||
#include <string.h> |
||||
|
||||
// Инициализировать пул памяти
|
||||
struct memory_pool* memory_pool_init(size_t object_size) { |
||||
struct memory_pool* pool = calloc(1, sizeof(struct memory_pool)); |
||||
if (!pool) { |
||||
return NULL; |
||||
} |
||||
pool->free_head = NULL; |
||||
pool->object_size = object_size; |
||||
pool->free_count = 0; |
||||
pool->allocations = 0; |
||||
pool->reuse_count = 0; |
||||
return pool; |
||||
} |
||||
|
||||
// Выделить объект из пула или из malloc
|
||||
void* memory_pool_alloc(struct memory_pool* pool) { |
||||
if (!pool) { |
||||
return NULL; |
||||
} |
||||
|
||||
if (pool->free_head) { |
||||
void* obj = pool->free_head; |
||||
pool->free_head = *(void**)obj; // Извлекаем next из начала блока
|
||||
pool->free_count--; |
||||
pool->reuse_count++; |
||||
memset(obj, 0, pool->object_size); // Опционально: очищаем память для безопасности
|
||||
return obj; |
||||
} |
||||
|
||||
pool->allocations++; |
||||
return calloc(1, pool->object_size); // Используем calloc для инициализации нулями
|
||||
} |
||||
|
||||
// Освободить объект в пул или в free
|
||||
void memory_pool_free(struct memory_pool* pool, void* obj) { |
||||
if (!pool || !obj) { |
||||
return; |
||||
} |
||||
|
||||
// Если пул не заполнен, сохранить объект для повторного использования
|
||||
if (pool->free_count < MEMORY_POOL_MAX_FREE) { |
||||
*(void**)obj = pool->free_head; // Сохраняем next в начало блока
|
||||
pool->free_head = obj; |
||||
pool->free_count++; |
||||
return; |
||||
} |
||||
|
||||
// Иначе освободить через free
|
||||
free(obj); |
||||
} |
||||
|
||||
// Получить статистику пула
|
||||
void memory_pool_get_stats(struct memory_pool* pool, size_t* allocations, size_t* reuse_count) { |
||||
if (!pool) { |
||||
return; |
||||
} |
||||
if (allocations) { |
||||
*allocations = pool->allocations; |
||||
} |
||||
if (reuse_count) { |
||||
*reuse_count = pool->reuse_count; |
||||
} |
||||
} |
||||
|
||||
// Очистить пул памяти
|
||||
void memory_pool_destroy(struct memory_pool* pool) { |
||||
if (!pool) { |
||||
return; |
||||
} |
||||
|
||||
// Освободить все объекты в пуле
|
||||
void* obj = pool->free_head; |
||||
while (obj) { |
||||
void* next = *(void**)obj; |
||||
free(obj); |
||||
obj = next; |
||||
} |
||||
|
||||
pool->free_head = NULL; |
||||
pool->free_count = 0; |
||||
free(pool); |
||||
} |
||||
@ -0,0 +1,23 @@
|
||||
// memory_pool.h
|
||||
#ifndef MEMORY_POOL_H |
||||
#define MEMORY_POOL_H |
||||
|
||||
#include <stddef.h> |
||||
|
||||
#define MEMORY_POOL_MAX_FREE 64 // Максимальное количество свободных объектов в пуле (чтобы не накапливать слишком много)
|
||||
|
||||
struct memory_pool { |
||||
void* free_head; // Голова linked list свободных блоков (next хранится в начале каждого блока)
|
||||
int free_count; // Количество свободных блоков
|
||||
size_t object_size; // Размер объектов в пуле
|
||||
size_t allocations; // Общее количество аллокаций (включая новые malloc)
|
||||
size_t reuse_count; // Количество повторных использований из пула
|
||||
}; |
||||
|
||||
struct memory_pool* memory_pool_init(size_t object_size); |
||||
void* memory_pool_alloc(struct memory_pool* pool); |
||||
void memory_pool_free(struct memory_pool* pool, void* obj); |
||||
void memory_pool_get_stats(struct memory_pool* pool, size_t* allocations, size_t* reuse_count); |
||||
void memory_pool_destroy(struct memory_pool* pool); |
||||
|
||||
#endif // MEMORY_POOL_H
|
||||
@ -0,0 +1,53 @@
|
||||
ar: модификатор «u» игнорируется, так как по умолчанию используется «D» (смотрите «U») |
||||
utun_instance.c: In function ‘utun_instance_destroy’: |
||||
utun_instance.c:98:17: warning: implicit declaration of function ‘conn_destroy’; did you mean ‘uasync_destroy’? [-Wimplicit-function-declaration] |
||||
98 | conn_destroy(instance->connections[i]); |
||||
| ^~~~~~~~~~~~ |
||||
| uasync_destroy |
||||
utun_instance.c: In function ‘tun_read_callback’: |
||||
utun_instance.c:237:21: warning: implicit declaration of function ‘conn_send’ [-Wimplicit-function-declaration] |
||||
237 | if (conn_send(route.next_hop, buffer, nread) < 0) { |
||||
| ^~~~~~~~~ |
||||
utun_instance.c: In function ‘utun_instance_unregister_sockets’: |
||||
utun_instance.c:276:57: warning: passing argument 2 of ‘uasync_remove_socket’ makes pointer from integer without a cast [-Wint-conversion] |
||||
276 | uasync_remove_socket(instance->ua, instance->tun.fd); |
||||
| ~~~~~~~~~~~~~^~~ |
||||
| | |
||||
| int |
||||
In file included from utun_instance.c:8: |
||||
../lib/u_async.h:35:48: note: expected ‘void *’ but argument is of type ‘int’ |
||||
35 | err_t uasync_remove_socket(uasync_t* ua, void* s_id); |
||||
| ~~~~~~^~~~ |
||||
etcp_connections.c: In function ‘etcp_link_send_init’: |
||||
etcp_connections.c:223:5: warning: implicit declaration of function ‘sc_get_public_key’; did you mean ‘sc_set_peer_public_key’? [-Wimplicit-function-declaration] |
||||
223 | sc_get_public_key(sc, pubkey); |
||||
| ^~~~~~~~~~~~~~~~~ |
||||
| sc_set_peer_public_key |
||||
etcp_connections.c: In function ‘init_connections’: |
||||
etcp_connections.c:432:29: warning: initialization of ‘struct config *’ from incompatible pointer type ‘struct utun_config *’ [-Wincompatible-pointer-types] |
||||
432 | struct config* config = instance->config; |
||||
| ^~~~~~~~ |
||||
etcp_connections.c:433:42: error: invalid use of undefined type ‘struct config’ |
||||
433 | instance->connections = calloc(config->server_count, sizeof(conn_handle_t*)); |
||||
| ^~ |
||||
etcp_connections.c:438:31: error: invalid use of undefined type ‘struct config’ |
||||
438 | for (int i = 0; i < config->server_count; i++) { |
||||
| ^~ |
||||
etcp_connections.c:439:47: error: invalid use of undefined type ‘struct config’ |
||||
439 | struct server_config* server = &config->servers[i]; |
||||
| ^~ |
||||
etcp_connections.c:442:30: warning: implicit declaration of function ‘parse_ip_port’ [-Wimplicit-function-declaration] |
||||
442 | uint16_t bind_port = parse_ip_port(server->addr, bind_ip_str, sizeof(bind_ip_str)); |
||||
| ^~~~~~~~~~~~~ |
||||
etcp_connections.c:485:43: warning: assignment to ‘struct ETCP_SOCKET *’ from incompatible pointer type ‘struct ETCP_CONNECTIONS *’ [-Wincompatible-pointer-types] |
||||
485 | instance->first_listen_socket = conns; |
||||
| ^ |
||||
etcp_connections.c:489:35: error: invalid use of undefined type ‘struct config’ |
||||
489 | for (int j = 0; j < config->client_count; j++) { |
||||
| ^~ |
||||
etcp_connections.c:490:51: error: invalid use of undefined type ‘struct config’ |
||||
490 | struct client_config* client = &config->clients[j]; |
||||
| ^~ |
||||
make[2]: *** [Makefile:626: utun-etcp_connections.o] Ошибка 1 |
||||
make[1]: *** [Makefile:433: all-recursive] Ошибка 1 |
||||
make: *** [Makefile:353: all] Ошибка 2 |
||||
@ -1,5 +0,0 @@
|
||||
// etcp.h - demo with original typedef |
||||
typedef struct ETCP_CONN etcp_t; |
||||
|
||||
struct ETCP_CONN* etcp_create(utun_instance_t *instance); |
||||
void etcp_destroy(etcp_t* etcp); |
||||
@ -1,31 +0,0 @@
|
||||
#ifndef ETCP_SOCKET_H |
||||
#define ETCP_SOCKET_H |
||||
|
||||
#include "packet_buffer.h" |
||||
#include <sys/socket.h> |
||||
#include <sys/types.h> |
||||
#include <netinet/in.h> |
||||
#include <stdint.h> |
||||
|
||||
// Forward declarations
|
||||
struct ETCP_CONN; |
||||
|
||||
// ETCP Socket - интегрированный UDP сокет с ETCP функциональностью
|
||||
struct ETCP_SOCKET { |
||||
int fd; // Файловый дескриптор UDP сокета
|
||||
struct sockaddr_storage local_addr; // Локальный адрес
|
||||
socklen_t local_addr_len; // Длина локального адреса
|
||||
|
||||
struct ETCP_CONN* etcp; // Родительский ETCP instance
|
||||
uint32_t socket_id; // Уникальный ID сокета
|
||||
|
||||
// Callback для получения данных
|
||||
void (*recv_callback)(struct ETCP_SOCKET* sock, struct packet_buffer* pkt, void* user_data); |
||||
void* recv_user_data; // User data для callback
|
||||
}; |
||||
|
||||
typedef void (*etcp_socket_recv_cb)(struct ETCP_SOCKET* sock, |
||||
struct packet_buffer* pkt, |
||||
void* user_data); |
||||
|
||||
#endif // ETCP_SOCKET_H
|
||||
@ -1,62 +0,0 @@
|
||||
#include "memory_pool.h" |
||||
#include <stdlib.h> |
||||
#include <string.h> |
||||
|
||||
// Инициализировать пул памяти
|
||||
void memory_pool_init(struct memory_pool* pool, size_t object_size) { |
||||
pool->object_size = object_size; |
||||
pool->free_count = 0; |
||||
pool->allocations = 0; |
||||
pool->reuse_count = 0; |
||||
memset(pool->free_list, 0, sizeof(pool->free_list)); |
||||
} |
||||
|
||||
// Выделить объект из пула или из malloc
|
||||
void* memory_pool_alloc(struct memory_pool* pool) { |
||||
pool->allocations++; |
||||
|
||||
// Если есть свободные объекты в пуле, использовать их
|
||||
if (pool->free_count > 0) { |
||||
pool->free_count--; |
||||
pool->reuse_count++; |
||||
void* obj = pool->free_list[pool->free_count]; |
||||
pool->free_list[pool->free_count] = NULL; |
||||
return obj; |
||||
} |
||||
|
||||
// Иначе выделить через malloc
|
||||
return malloc(pool->object_size); |
||||
} |
||||
|
||||
// Освободить объект в пул или в free
|
||||
void memory_pool_free(struct memory_pool* pool, void* obj) { |
||||
if (!obj) return; |
||||
|
||||
// Если пул не заполнен, сохранить объект для повторного использования
|
||||
if (pool->free_count < MEMORY_POOL_SIZE) { |
||||
pool->free_list[pool->free_count] = obj; |
||||
pool->free_count++; |
||||
return; |
||||
} |
||||
|
||||
// Иначе освободить через free
|
||||
free(obj); |
||||
} |
||||
|
||||
// Получить статистику пула
|
||||
void memory_pool_get_stats(struct memory_pool* pool, size_t* allocations, size_t* reuse_count) { |
||||
if (allocations) *allocations = pool->allocations; |
||||
if (reuse_count) *reuse_count = pool->reuse_count; |
||||
} |
||||
|
||||
// Очистить пул памяти
|
||||
void memory_pool_destroy(struct memory_pool* pool) { |
||||
// Освободить все объекты в пуле
|
||||
for (int i = 0; i < pool->free_count; i++) { |
||||
if (pool->free_list[i]) { |
||||
free(pool->free_list[i]); |
||||
pool->free_list[i] = NULL; |
||||
} |
||||
} |
||||
pool->free_count = 0; |
||||
} |
||||
@ -1,36 +0,0 @@
|
||||
#ifndef MEMORY_POOL_H |
||||
#define MEMORY_POOL_H |
||||
|
||||
#include <stddef.h> // для size_t |
||||
|
||||
// Размер пула для объектов одинакового размера
|
||||
#define MEMORY_POOL_SIZE 64 |
||||
|
||||
// Структура пула памяти для оптимизации аллокаций
|
||||
struct memory_pool { |
||||
void* free_list[MEMORY_POOL_SIZE]; // Список свободных блоков
|
||||
int free_count; // Количество свободных блоков
|
||||
size_t object_size; // Размер объектов в пуле
|
||||
size_t allocations; // Статистика: всего аллокаций
|
||||
size_t reuse_count; // Статистика: повторное использование
|
||||
}; |
||||
|
||||
// Тип пула памяти
|
||||
typedef struct memory_pool memory_pool_t; |
||||
|
||||
// Инициализировать пул памяти
|
||||
void memory_pool_init(struct memory_pool* pool, size_t object_size); |
||||
|
||||
// Выделить объект из пула или из malloc
|
||||
void* memory_pool_alloc(struct memory_pool* pool); |
||||
|
||||
// Освободить объект в пул или в free
|
||||
void memory_pool_free(struct memory_pool* pool, void* obj); |
||||
|
||||
// Получить статистику пула
|
||||
void memory_pool_get_stats(struct memory_pool* pool, size_t* allocations, size_t* reuse_count); |
||||
|
||||
// Очистить пул памяти
|
||||
void memory_pool_destroy(struct memory_pool* pool); |
||||
|
||||
#endif // MEMORY_POOL_H
|
||||
@ -1,76 +0,0 @@
|
||||
#ifndef PACKET_BUFFER_H |
||||
#define PACKET_BUFFER_H |
||||
|
||||
#include <stdint.h> |
||||
#include <sys/socket.h> |
||||
#include <netinet/in.h> |
||||
#include <string.h> |
||||
|
||||
|
||||
// Стадии обработки пакета
|
||||
typedef enum { |
||||
PACKET_STAGE_RX_SOCKET, // Получен из сокета (зашифрован)
|
||||
PACKET_STAGE_RX_DECRYPTED, // Расшифрован (plain-text)
|
||||
PACKET_STAGE_RX_ETCP, // Обработан ETCP (собран фрагмент)
|
||||
PACKET_STAGE_RX_APP, // Передан в приложение
|
||||
PACKET_STAGE_TX_APP, // Из приложения на отправку
|
||||
PACKET_STAGE_TX_ETCP, // Обработан ETCP (фрагментирован)
|
||||
PACKET_STAGE_TX_ENCRYPTED // Зашифрован, готов к отправке
|
||||
} packet_stage_t; |
||||
|
||||
// Флаги пакета
|
||||
#define PACKET_FLAG_ENCRYPTED (1 << 0) |
||||
#define PACKET_FLAG_FRAGMENTED (1 << 1) |
||||
#define PACKET_FLAG_RETRANSMIT (1 << 2) |
||||
#define PACKET_FLAG_CONTROL (1 << 3) // Служебный пакет (RST, INIT)
|
||||
|
||||
// Размеры
|
||||
#define PACKET_METADATA_SIZE 64 |
||||
#define PACKET_DATA_SIZE 1536 |
||||
#define PACKET_TOTAL_SIZE 1600 |
||||
#define PACKET_POOL_SIZE 64 |
||||
|
||||
// Основная структура пакета
|
||||
struct packet_buffer { |
||||
|
||||
// Метаданные (64 байта)
|
||||
struct { |
||||
struct ETCP_SOCKET* s; // Сокет через который получен/ планируется отправить
|
||||
struct etcp_channel* channel; // Канал ETCP (NULL до поиска)
|
||||
struct sockaddr_storage remote_addr;// Адрес удаленного endpoint
|
||||
uint64_t timestamp_us; // Время создания пакета
|
||||
uint16_t data_len; // Длина данных в буфере
|
||||
uint8_t stage; // Стадия обработки пакета
|
||||
} metadata; |
||||
struct packet_buffer* next_free; // Для пула - используется только когда пакет свободен
|
||||
|
||||
uint8_t data[0]; // Данные (variable size)
|
||||
|
||||
}; |
||||
|
||||
// Инлайн функции для удобного доступа
|
||||
|
||||
// Доступ к данным
|
||||
static inline uint8_t* packet_data(struct packet_buffer* pkt) { |
||||
return pkt->data; |
||||
} |
||||
|
||||
static inline struct sockaddr* packet_remote_addr(struct packet_buffer* pkt) { |
||||
return (struct sockaddr*)&pkt->metadata.remote_addr; |
||||
} |
||||
|
||||
static inline uint16_t packet_remote_port(const struct packet_buffer* pkt) { |
||||
if (pkt->metadata.remote_addr.ss_family == AF_INET) { |
||||
return ((struct sockaddr_in*)&pkt->metadata.remote_addr)->sin_port; |
||||
} |
||||
return 0; |
||||
} |
||||
|
||||
// Инициализация
|
||||
static inline void packet_init(struct packet_buffer* pkt) { |
||||
memset(&pkt->metadata, 0, sizeof(pkt->metadata)); |
||||
pkt->metadata.timestamp_us = 0; // TODO: get current time
|
||||
pkt->metadata.stage = PACKET_STAGE_RX_SOCKET; |
||||
} |
||||
|
||||
#endif // PACKET_BUFFER_H
|
||||
@ -1,85 +0,0 @@
|
||||
#include "packet_pool.h" |
||||
#include "packet_buffer.h" |
||||
#include <stdlib.h> |
||||
#include <string.h> |
||||
#include <stdio.h> |
||||
|
||||
void packet_pool_init(struct packet_pool* pool) { |
||||
pool->free_count = 0; |
||||
pool->allocations = 0; |
||||
pool->reuse_count = 0; |
||||
pool->overflow_count = 0; |
||||
memset(pool->free_list, 0, sizeof(pool->free_list)); |
||||
|
||||
// Предварительно аллоцируем пакеты
|
||||
for (int i = 0; i < PACKET_POOL_SIZE / 2; i++) { |
||||
struct packet_buffer* pkt = calloc(1, PACKET_TOTAL_SIZE); |
||||
if (pkt) { |
||||
pool->free_list[pool->free_count++] = pkt; |
||||
} |
||||
} |
||||
} |
||||
|
||||
struct packet_buffer* packet_pool_get(struct packet_pool* pool) { |
||||
pool->allocations++; |
||||
|
||||
// Если есть свободные пакеты в пуле, использовать их
|
||||
if (pool->free_count > 0) { |
||||
pool->reuse_count++; |
||||
pool->free_count--; |
||||
struct packet_buffer* pkt = pool->free_list[pool->free_count]; |
||||
pool->free_list[pool->free_count] = NULL; |
||||
|
||||
// Инициализировать метаданные
|
||||
packet_init(pkt); |
||||
pkt->next_free = NULL; |
||||
|
||||
return pkt; |
||||
} |
||||
|
||||
// Иначе выделить через malloc
|
||||
pool->overflow_count++; |
||||
struct packet_buffer* pkt = calloc(1, PACKET_TOTAL_SIZE); |
||||
if (pkt) { |
||||
packet_init(pkt); |
||||
} |
||||
|
||||
return pkt; |
||||
} |
||||
|
||||
void packet_pool_put(struct packet_pool* pool, struct packet_buffer* pkt) { |
||||
if (!pkt) return; |
||||
|
||||
// Если пул не заполнен, сохранить пакет для повторного использования
|
||||
if (pool->free_count < PACKET_POOL_SIZE) { |
||||
pool->free_list[pool->free_count] = pkt; |
||||
pool->free_count++; |
||||
return; |
||||
} |
||||
|
||||
// Иначе освободить через free (переполнение)
|
||||
free(pkt); |
||||
} |
||||
|
||||
void packet_pool_get_stats(const struct packet_pool* pool,
|
||||
size_t* allocations,
|
||||
size_t* reuse_count, |
||||
size_t* overflow_count) { |
||||
if (allocations) *allocations = pool->allocations; |
||||
if (reuse_count) *reuse_count = pool->reuse_count; |
||||
if (overflow_count) *overflow_count = pool->overflow_count; |
||||
} |
||||
|
||||
void packet_pool_destroy(struct packet_pool* pool) { |
||||
// Освободить все пакеты в пуле
|
||||
for (int i = 0; i < pool->free_count; i++) { |
||||
if (pool->free_list[i]) { |
||||
free(pool->free_list[i]); |
||||
pool->free_list[i] = NULL; |
||||
} |
||||
} |
||||
pool->free_count = 0; |
||||
pool->allocations = 0; |
||||
pool->reuse_count = 0; |
||||
pool->overflow_count = 0; |
||||
} |
||||
@ -1,35 +0,0 @@
|
||||
#ifndef PACKET_POOL_H |
||||
#define PACKET_POOL_H |
||||
|
||||
#include "packet_buffer.h" |
||||
|
||||
// Размер пула пакетов
|
||||
#define PACKET_POOL_SIZE 64 |
||||
|
||||
struct packet_pool { |
||||
struct packet_buffer* free_list[PACKET_POOL_SIZE]; // Список свободных пакетов
|
||||
int free_count; // Количество свободных пакетов
|
||||
size_t allocations; // Всего аллокаций
|
||||
size_t reuse_count; // Повторное использование
|
||||
size_t overflow_count; // Переполнения пула
|
||||
}; |
||||
|
||||
// Инициализация пула
|
||||
void packet_pool_init(struct packet_pool* pool); |
||||
|
||||
// Получить пакет из пула
|
||||
struct packet_buffer* packet_pool_get(struct packet_pool* pool); |
||||
|
||||
// Вернуть пакет в пул
|
||||
void packet_pool_put(struct packet_pool* pool, struct packet_buffer* pkt); |
||||
|
||||
// Получить статистику
|
||||
void packet_pool_get_stats(const struct packet_pool* pool,
|
||||
size_t* allocations,
|
||||
size_t* reuse_count, |
||||
size_t* overflow_count); |
||||
|
||||
// Очистить пул и освободить всю память
|
||||
void packet_pool_destroy(struct packet_pool* pool); |
||||
|
||||
#endif // PACKET_POOL_H
|
||||
@ -1,52 +0,0 @@
|
||||
#include "utun_instance.h" |
||||
#include "routing.h" |
||||
#include "etcp_connections.h" |
||||
#include "config_parser.h" |
||||
#include "../lib/u_async.h" |
||||
|
||||
conn_handle_t* route_get_next_hop(routing_table_t* rt, uint32_t dest_ip) { |
||||
route_entry_t route = {0}; |
||||
if (!rt || !routing_table_lookup(rt, dest_ip, &route)) return NULL; |
||||
return (conn_handle_t*)route.next_hop; |
||||
} |
||||
|
||||
static int add_default_route(struct UTUN_INSTANCE* *instance) { |
||||
if (!instance || !instance->routing_table || instance->connection_count == 0) return -1; |
||||
|
||||
route_entry_t default_route = {0}; |
||||
default_route.network = 0; // 0.0.0.0
|
||||
default_route.prefix_length = 0; |
||||
default_route.next_hop_ip = 0; |
||||
default_route.next_hop = (struct ETCP_CONNECTIONS*)instance->connections[0]->conns; |
||||
default_route.type = ROUTE_TYPE_STATIC; |
||||
default_route.flags = ROUTE_FLAG_ACTIVE; |
||||
default_route.created_time = 0; |
||||
|
||||
return routing_table_insert((routing_table_t*)instance->routing_table, &default_route) ? 0 : -1; |
||||
} |
||||
|
||||
void conn_destroy(conn_handle_t* conn); |
||||
int conn_send(conn_handle_t* conn, const uint8_t* data, size_t len); |
||||
uint32_t get_dest_ip(const uint8_t *packet, size_t len); |
||||
int parse_subnet(const char* subnet_str, uint32_t* network, uint8_t* prefix_len); |
||||
|
||||
conn_handle_t* route_find_connection(struct UTUN_INSTANCE** instance, uint32_t dest_ip) { |
||||
if (!instance || !instance->routing_table) return NULL; |
||||
|
||||
route_entry_t route = {0}; |
||||
if (!routing_table_lookup((routing_table_t*)instance->routing_table, dest_ip, &route)) { |
||||
return NULL; |
||||
} |
||||
|
||||
struct ETCP_CONNECTIONS* conns = route.next_hop; |
||||
if (!conns) return NULL; |
||||
|
||||
// Find matching connection handle
|
||||
for (int i = 0; i < instance->connection_count; i++) { |
||||
if (instance->connections[i] && instance->connections[i]->conns == conns) { |
||||
return instance->connections[i]; |
||||
} |
||||
} |
||||
|
||||
return NULL; |
||||
} |
||||
@ -0,0 +1,19 @@
|
||||
[global] |
||||
my_private_key=8d893d54930fc1b428e17c3ef01f0eb7578fba00bc43f3b5260b30aace064c81 |
||||
|
||||
my_public_key=193ba8d4829818e2571789432ec065963ee364b1c524ba04902130e9a0961ab7 |
||||
|
||||
my_node_id=3e62f4ffc02efa41 |
||||
|
||||
tun_ip=10.0.0.1/24 |
||||
mtu=1500 |
||||
control_ip=127.0.0.1 |
||||
control_port=12345 |
||||
net_debug=0 |
||||
|
||||
[routing] |
||||
allowed_subnet=10.0.0.0/24 |
||||
|
||||
[server:test] |
||||
addr=192.168.0.10:1234 |
||||
netif=et |
||||
@ -0,0 +1,16 @@
|
||||
[global] |
||||
tun_ip=10.0.0.1/24 |
||||
mtu=1500 |
||||
control_ip=127.0.0.1 |
||||
control_port=12345 |
||||
net_debug=0 |
||||
|
||||
my_node_id=338e13218f721d15 |
||||
my_private_key=ccb9f2ae2f348f7f8fc8618c58395c242107a802a1de5f674e81ecd03bfc7a0d |
||||
my_public_key=d12a4aa8d289b15264c47c867812620abab80890164b22e0f69918d696d91ccd |
||||
[routing] |
||||
allowed_subnet=10.0.0.0/24 |
||||
|
||||
[server:test] |
||||
addr=192.168.0.10:1234 |
||||
netif=eth0 |
||||
Binary file not shown.
@ -0,0 +1,213 @@
|
||||
// test_etcp_crypto.c - Test ETCP encryption/decryption with secure channel
|
||||
#include "etcp.h" |
||||
#include "config_parser.h" |
||||
#include "secure_channel.h" |
||||
#include "etcp_connections.h" |
||||
#include <stdio.h> |
||||
#include <string.h> |
||||
#include <stdlib.h> |
||||
#include <unistd.h> |
||||
#include <arpa/inet.h> |
||||
#include <sys/socket.h> |
||||
#include <fcntl.h> |
||||
#include <errno.h> |
||||
|
||||
// Test configuration
|
||||
#define TEST_PORT 32345 |
||||
#define CLIENT_PORT 32346 |
||||
#define TEST_DATA "Hello, encrypted world!" |
||||
#define TEST_DATA_LEN 23 |
||||
|
||||
// Helper: create UDP socket bound to port
|
||||
static int create_udp_socket(int port) { |
||||
int fd = socket(AF_INET, SOCK_DGRAM, 0); |
||||
if (fd < 0) return -1; |
||||
|
||||
int flags = fcntl(fd, F_GETFL, 0); |
||||
fcntl(fd, F_SETFL, flags | O_NONBLOCK); |
||||
|
||||
struct sockaddr_in addr; |
||||
memset(&addr, 0, sizeof(addr)); |
||||
addr.sin_family = AF_INET; |
||||
addr.sin_addr.s_addr = INADDR_ANY; |
||||
addr.sin_port = htons(port); |
||||
|
||||
if (bind(fd, (struct sockaddr*)&addr, sizeof(addr)) < 0) { |
||||
close(fd); |
||||
return -1; |
||||
} |
||||
|
||||
return fd; |
||||
} |
||||
|
||||
// Helper: generate test keys
|
||||
static void generate_test_keys(uint8_t* server_priv, uint8_t* server_pub, |
||||
uint8_t* client_priv, uint8_t* client_pub) { |
||||
// Use fixed test keys for reproducibility
|
||||
const char* server_priv_hex = "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"; |
||||
const char* server_pub_hex = "abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789"; |
||||
const char* client_priv_hex = "fedcba9876543210fedcba9876543210fedcba9876543210fedcba9876543210"; |
||||
const char* client_pub_hex = "1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef"; |
||||
|
||||
for (int i = 0; i < 32; i++) { |
||||
sscanf(server_priv_hex + i*2, "%2hhx", &server_priv[i]); |
||||
sscanf(server_pub_hex + i*2, "%2hhx", &server_pub[i]); |
||||
sscanf(client_priv_hex + i*2, "%2hhx", &client_priv[i]); |
||||
sscanf(client_pub_hex + i*2, "%2hhx", &client_pub[i]); |
||||
} |
||||
} |
||||
|
||||
// Helper: hex to binary
|
||||
static int hex_to_bin(const char* hex, uint8_t* bin, size_t len) { |
||||
if (strlen(hex) != len * 2) return -1; |
||||
for (size_t i = 0; i < len; i++) { |
||||
if (sscanf(hex + i*2, "%2hhx", &bin[i]) != 1) return -1; |
||||
} |
||||
return 0; |
||||
} |
||||
|
||||
int main(void) { |
||||
printf("=== ETCP Crypto Test ===\n"); |
||||
|
||||
// Generate test keys
|
||||
uint8_t server_priv[32], server_pub[32]; |
||||
uint8_t client_priv[32], client_pub[32]; |
||||
generate_test_keys(server_priv, server_pub, client_priv, client_pub); |
||||
|
||||
// Create UDP sockets
|
||||
int server_fd = create_udp_socket(TEST_PORT); |
||||
int client_fd = create_udp_socket(CLIENT_PORT); |
||||
if (server_fd < 0 || client_fd < 0) { |
||||
printf("ERROR: Failed to create sockets\n"); |
||||
return 1; |
||||
} |
||||
|
||||
// Create ETCP instances
|
||||
struct ETCP_CONN* server_etcp = calloc(1, sizeof(struct ETCP_CONN)); |
||||
struct ETCP_CONN* client_etcp = calloc(1, sizeof(struct ETCP_CONN)); |
||||
if (!server_etcp || !client_etcp) { |
||||
printf("ERROR: Failed to allocate ETCP instances\n"); |
||||
return 1; |
||||
} |
||||
|
||||
// Initialize secure channels
|
||||
server_etcp->crypto_ctx = calloc(1, sizeof(sc_context_t)); |
||||
client_etcp->crypto_ctx = calloc(1, sizeof(sc_context_t)); |
||||
if (!server_etcp->crypto_ctx || !client_etcp->crypto_ctx) { |
||||
printf("ERROR: Failed to allocate crypto contexts\n"); |
||||
return 1; |
||||
} |
||||
|
||||
// Set keys
|
||||
memcpy(server_etcp->crypto_ctx->private_key, server_priv, 32); |
||||
memcpy(server_etcp->crypto_ctx->public_key, server_pub, 32); |
||||
server_etcp->crypto_ctx->initialized = 1; |
||||
|
||||
memcpy(client_etcp->crypto_ctx->private_key, client_priv, 32); |
||||
memcpy(client_etcp->crypto_ctx->public_key, client_pub, 32); |
||||
client_etcp->crypto_ctx->initialized = 1; |
||||
|
||||
// Client sets server's public key as peer
|
||||
memcpy(client_etcp->peer_public_key, server_pub, 32); |
||||
client_etcp->has_peer_key = 1; |
||||
sc_set_peer_public_key(client_etcp->crypto_ctx, server_pub); |
||||
|
||||
// Server will get client's public key from INIT packet
|
||||
|
||||
// Create connections managers
|
||||
struct ETCP_CONNECTIONS* server_conns = etcp_connections_init(server_etcp, "127.0.0.1", 0); |
||||
struct ETCP_CONNECTIONS* client_conns = etcp_connections_init(client_etcp, "127.0.0.1", 0); |
||||
if (!server_conns || !client_conns) { |
||||
printf("ERROR: Failed to create connections\n"); |
||||
return 1; |
||||
} |
||||
|
||||
// Create client link (client initiates connection)
|
||||
struct sockaddr_in server_addr; |
||||
memset(&server_addr, 0, sizeof(server_addr)); |
||||
server_addr.sin_family = AF_INET; |
||||
server_addr.sin_addr.s_addr = inet_addr("127.0.0.1"); |
||||
server_addr.sin_port = htons(TEST_PORT); |
||||
|
||||
struct ETCP_LINK* client_link = etcp_link_new(client_etcp, &client_conns->socket, client_conns, |
||||
(struct sockaddr*)&server_addr, sizeof(server_addr)); |
||||
if (!client_link) { |
||||
printf("ERROR: Failed to create client link\n"); |
||||
return 1; |
||||
} |
||||
|
||||
// Send INIT from client to server
|
||||
printf("Sending INIT from client...\n"); |
||||
if (etcp_link_send_init(client_link, 1500, 30) < 0) { |
||||
printf("ERROR: Failed to send INIT\n"); |
||||
return 1; |
||||
} |
||||
|
||||
// Server should receive INIT and create link
|
||||
usleep(100000); // 100ms
|
||||
|
||||
struct sockaddr_in from_addr; |
||||
socklen_t from_len = sizeof(from_addr); |
||||
uint8_t buffer[2048]; |
||||
ssize_t received = recvfrom(server_fd, buffer, sizeof(buffer), MSG_DONTWAIT, |
||||
(struct sockaddr*)&from_addr, &from_len); |
||||
|
||||
if (received > 0) { |
||||
printf("Server received %zd bytes\n", received); |
||||
|
||||
// Process packet on server
|
||||
struct packet_buffer pkt; |
||||
memcpy(pkt.data, buffer, received); |
||||
pkt.metadata.data_len = received; |
||||
pkt.metadata.remote_addr = *(struct sockaddr_storage*)&from_addr; |
||||
pkt.metadata.s = &server_conns->socket; |
||||
|
||||
if (etcp_input(&pkt, &server_conns->socket, server_conns) == 0) { |
||||
printf("Server processed INIT successfully\n"); |
||||
|
||||
// Check that server got client's public key
|
||||
if (server_etcp->has_peer_key) { |
||||
printf("Server received client's public key\n"); |
||||
} |
||||
} |
||||
} |
||||
|
||||
// Test encrypted data transfer
|
||||
printf("\nTesting encrypted data transfer...\n"); |
||||
|
||||
const char* test_data = TEST_DATA; |
||||
if (etcp_link_send(client_etcp, client_link, (const uint8_t*)test_data, TEST_DATA_LEN) == 0) { |
||||
printf("Client sent encrypted data\n"); |
||||
} |
||||
|
||||
usleep(100000); |
||||
|
||||
received = recvfrom(server_fd, buffer, sizeof(buffer), MSG_DONTWAIT, |
||||
(struct sockaddr*)&from_addr, &from_len); |
||||
if (received > 0) { |
||||
printf("Server received %zd encrypted bytes\n", received); |
||||
// In real scenario, etcp_input would decrypt and process
|
||||
} |
||||
|
||||
// Print statistics
|
||||
printf("\n=== Statistics ===\n"); |
||||
size_t enc_err, dec_err, send_err, total_enc, total_dec; |
||||
etcp_connections_get_crypto_stats(server_conns, &enc_err, &dec_err, &send_err, NULL, &total_enc, &total_dec); |
||||
printf("Server: encrypted=%zu, decrypted=%zu, errors=%zu/%zu/%zu\n", |
||||
total_enc, total_dec, enc_err, dec_err, send_err); |
||||
|
||||
etcp_connections_get_crypto_stats(client_conns, &enc_err, &dec_err, &send_err, NULL, &total_enc, &total_dec); |
||||
printf("Client: encrypted=%zu, decrypted=%zu, errors=%zu/%zu/%zu\n", |
||||
total_enc, total_dec, enc_err, dec_err, send_err); |
||||
|
||||
// Cleanup
|
||||
close(server_fd); |
||||
close(client_fd); |
||||
free(server_etcp->crypto_ctx); |
||||
free(client_etcp->crypto_ctx); |
||||
free(server_etcp); |
||||
free(client_etcp); |
||||
|
||||
printf("\n=== Test completed ===\n"); |
||||
return 0; |
||||
} |
||||
Binary file not shown.
@ -0,0 +1,219 @@
|
||||
// test_etcp_crypto.c - Test ETCP encryption/decryption with secure channel
|
||||
#include "etcp.h" |
||||
#include "config_parser.h" |
||||
#include "secure_channel.h" |
||||
#include "etcp_connections.h" |
||||
#include "packet_buffer.h" |
||||
#include "packet_pool.h" |
||||
#include <stdio.h> |
||||
#include <string.h> |
||||
#include <stdlib.h> |
||||
#include <unistd.h> |
||||
#include <arpa/inet.h> |
||||
#include <sys/socket.h> |
||||
#include <fcntl.h> |
||||
#include <errno.h> |
||||
|
||||
// Test configuration
|
||||
#define TEST_PORT 42345 |
||||
#define CLIENT_PORT 42346 |
||||
#define TEST_DATA "Hello, encrypted world!" |
||||
#define TEST_DATA_LEN 23 |
||||
|
||||
// Helper: create UDP socket bound to port
|
||||
static int create_udp_socket(int port) { |
||||
int fd = socket(AF_INET, SOCK_DGRAM, 0); |
||||
if (fd < 0) return -1; |
||||
|
||||
int flags = fcntl(fd, F_GETFL, 0); |
||||
fcntl(fd, F_SETFL, flags | O_NONBLOCK); |
||||
|
||||
struct sockaddr_in addr; |
||||
memset(&addr, 0, sizeof(addr)); |
||||
addr.sin_family = AF_INET; |
||||
addr.sin_addr.s_addr = INADDR_ANY; |
||||
addr.sin_port = htons(port); |
||||
|
||||
if (bind(fd, (struct sockaddr*)&addr, sizeof(addr)) < 0) { |
||||
close(fd); |
||||
return -1; |
||||
} |
||||
|
||||
return fd; |
||||
} |
||||
|
||||
// Helper: generate test keys
|
||||
static void generate_test_keys(uint8_t* server_priv, uint8_t* server_pub, |
||||
uint8_t* client_priv, uint8_t* client_pub) { |
||||
// Use fixed test keys for reproducibility
|
||||
const char* server_priv_hex = "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"; |
||||
const char* server_pub_hex = "abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789"; |
||||
const char* client_priv_hex = "fedcba9876543210fedcba9876543210fedcba9876543210fedcba9876543210"; |
||||
const char* client_pub_hex = "1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef"; |
||||
|
||||
for (int i = 0; i < 32; i++) { |
||||
sscanf(server_priv_hex + i*2, "%2hhx", &server_priv[i]); |
||||
sscanf(server_pub_hex + i*2, "%2hhx", &server_pub[i]); |
||||
sscanf(client_priv_hex + i*2, "%2hhx", &client_priv[i]); |
||||
sscanf(client_pub_hex + i*2, "%2hhx", &client_pub[i]); |
||||
} |
||||
} |
||||
|
||||
// Helper: hex to binary
|
||||
static int hex_to_bin(const char* hex, uint8_t* bin, size_t len) { |
||||
if (strlen(hex) != len * 2) return -1; |
||||
for (size_t i = 0; i < len; i++) { |
||||
if (sscanf(hex + i*2, "%2hhx", &bin[i]) != 1) return -1; |
||||
} |
||||
return 0; |
||||
} |
||||
|
||||
int main(void) { |
||||
printf("=== ETCP Crypto Test ===\n"); |
||||
|
||||
// Generate test keys
|
||||
uint8_t server_priv[32], server_pub[32]; |
||||
uint8_t client_priv[32], client_pub[32]; |
||||
generate_test_keys(server_priv, server_pub, client_priv, client_pub); |
||||
|
||||
// Create UDP sockets
|
||||
int server_fd = create_udp_socket(TEST_PORT); |
||||
int client_fd = create_udp_socket(CLIENT_PORT); |
||||
if (server_fd < 0 || client_fd < 0) { |
||||
printf("ERROR: Failed to create sockets\n"); |
||||
return 1; |
||||
} |
||||
|
||||
// Create ETCP instances
|
||||
struct ETCP_CONN* server_etcp = calloc(1, sizeof(struct ETCP_CONN)); |
||||
struct ETCP_CONN* client_etcp = calloc(1, sizeof(struct ETCP_CONN)); |
||||
if (!server_etcp || !client_etcp) { |
||||
printf("ERROR: Failed to allocate ETCP instances\n"); |
||||
return 1; |
||||
} |
||||
|
||||
// Initialize secure channels
|
||||
server_etcp->crypto_ctx = calloc(1, sizeof(sc_context_t)); |
||||
client_etcp->crypto_ctx = calloc(1, sizeof(sc_context_t)); |
||||
if (!server_etcp->crypto_ctx || !client_etcp->crypto_ctx) { |
||||
printf("ERROR: Failed to allocate crypto contexts\n"); |
||||
return 1; |
||||
} |
||||
|
||||
// Set keys
|
||||
memcpy(server_etcp->crypto_ctx->private_key, server_priv, 32); |
||||
memcpy(server_etcp->crypto_ctx->public_key, server_pub, 32); |
||||
server_etcp->crypto_ctx->initialized = 1; |
||||
|
||||
memcpy(client_etcp->crypto_ctx->private_key, client_priv, 32); |
||||
memcpy(client_etcp->crypto_ctx->public_key, client_pub, 32); |
||||
client_etcp->crypto_ctx->initialized = 1; |
||||
|
||||
// Client sets server's public key as peer
|
||||
memcpy(client_etcp->peer_public_key, server_pub, 32); |
||||
client_etcp->has_peer_key = 1; |
||||
sc_set_peer_public_key(client_etcp->crypto_ctx, server_pub); |
||||
|
||||
// Server will get client's public key from INIT packet
|
||||
|
||||
// Create connections managers
|
||||
struct ETCP_CONNECTIONS* server_conns = etcp_connections_init(server_etcp, "127.0.0.1", 0); |
||||
struct ETCP_CONNECTIONS* client_conns = etcp_connections_init(client_etcp, "127.0.0.1", 0); |
||||
if (!server_conns || !client_conns) { |
||||
printf("ERROR: Failed to create connections\n"); |
||||
return 1; |
||||
} |
||||
|
||||
// Create client link (client initiates connection)
|
||||
struct sockaddr_in server_addr; |
||||
memset(&server_addr, 0, sizeof(server_addr)); |
||||
server_addr.sin_family = AF_INET; |
||||
server_addr.sin_addr.s_addr = inet_addr("127.0.0.1"); |
||||
server_addr.sin_port = htons(TEST_PORT); |
||||
|
||||
struct ETCP_LINK* client_link = etcp_link_new(client_etcp, &client_conns->socket, client_conns, |
||||
(struct sockaddr*)&server_addr, sizeof(server_addr)); |
||||
if (!client_link) { |
||||
printf("ERROR: Failed to create client link\n"); |
||||
return 1; |
||||
} |
||||
|
||||
// Send INIT from client to server
|
||||
printf("Sending INIT from client...\n"); |
||||
if (etcp_link_send_init(client_link, 1500, 30) < 0) { |
||||
printf("ERROR: Failed to send INIT\n"); |
||||
return 1; |
||||
} |
||||
|
||||
// Server should receive INIT and create link
|
||||
usleep(100000); // 100ms
|
||||
|
||||
struct sockaddr_in from_addr; |
||||
socklen_t from_len = sizeof(from_addr); |
||||
uint8_t buffer[2048]; |
||||
ssize_t received = recvfrom(server_fd, buffer, sizeof(buffer), MSG_DONTWAIT, |
||||
(struct sockaddr*)&from_addr, &from_len); |
||||
|
||||
if (received > 0) { |
||||
printf("Server received %zd bytes\n", received); |
||||
|
||||
// Process packet on server - use packet pool
|
||||
struct packet_buffer* pkt = packet_pool_get(&server_etcp->packet_pool); |
||||
if (pkt) { |
||||
memcpy(packet_data(pkt), buffer, received); |
||||
pkt->metadata.data_len = received; |
||||
pkt->metadata.remote_addr = *(struct sockaddr_storage*)&from_addr; |
||||
pkt->metadata.s = &server_conns->socket; |
||||
|
||||
if (etcp_input(pkt, &server_conns->socket, server_conns) == 0) { |
||||
printf("Server processed INIT successfully\n"); |
||||
|
||||
// Check that server got client's public key
|
||||
if (server_etcp->has_peer_key) { |
||||
printf("Server received client's public key\n"); |
||||
} |
||||
} |
||||
|
||||
packet_pool_put(&server_etcp->packet_pool, pkt); |
||||
} |
||||
} |
||||
|
||||
// Test encrypted data transfer
|
||||
printf("\nTesting encrypted data transfer...\n"); |
||||
|
||||
const char* test_data = TEST_DATA; |
||||
if (etcp_link_send(client_etcp, client_link, (const uint8_t*)test_data, TEST_DATA_LEN) == 0) { |
||||
printf("Client sent encrypted data\n"); |
||||
} |
||||
|
||||
usleep(100000); |
||||
|
||||
received = recvfrom(server_fd, buffer, sizeof(buffer), MSG_DONTWAIT, |
||||
(struct sockaddr*)&from_addr, &from_len); |
||||
if (received > 0) { |
||||
printf("Server received %zd encrypted bytes\n", received); |
||||
// In real scenario, etcp_input would decrypt and process
|
||||
} |
||||
|
||||
// Print statistics
|
||||
printf("\n=== Statistics ===\n"); |
||||
size_t enc_err, dec_err, send_err, total_enc, total_dec; |
||||
etcp_connections_get_crypto_stats(server_conns, &enc_err, &dec_err, &send_err, NULL, &total_enc, &total_dec); |
||||
printf("Server: encrypted=%zu, decrypted=%zu, errors=%zu/%zu/%zu\n", |
||||
total_enc, total_dec, enc_err, dec_err, send_err); |
||||
|
||||
etcp_connections_get_crypto_stats(client_conns, &enc_err, &dec_err, &send_err, NULL, &total_enc, &total_dec); |
||||
printf("Client: encrypted=%zu, decrypted=%zu, errors=%zu/%zu/%zu\n", |
||||
total_enc, total_dec, enc_err, dec_err, send_err); |
||||
|
||||
// Cleanup
|
||||
close(server_fd); |
||||
close(client_fd); |
||||
free(server_etcp->crypto_ctx); |
||||
free(client_etcp->crypto_ctx); |
||||
free(server_etcp); |
||||
free(client_etcp); |
||||
|
||||
printf("\n=== Test completed ===\n"); |
||||
return 0; |
||||
} |
||||
@ -0,0 +1,42 @@
|
||||
[global] |
||||
my_private_key=0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef |
||||
my_public_key=abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789 |
||||
my_node_id=babababa1123 # 64bit ID |
||||
option=value1,value2 |
||||
tun_ip=10.0.0.1 |
||||
mtu=1500 # MTU for all connections (0 = use default 1500) |
||||
control_ip=127.0.0.1 |
||||
control_port=12345 |
||||
net_debug=0 |
||||
|
||||
[routing] |
||||
allowed_subnet=10.0.0.0/24 |
||||
allowed_subnet=10.22.0.0/16 |
||||
allowed_subnet=10.23.0.0/16 |
||||
my_subnet=10.23.5.0/24 |
||||
my_subnet=10.23.6.0/24 |
||||
|
||||
# мои адреса и каналы |
||||
[server: wired1_fast] |
||||
addr=192.168.0.10:1234 |
||||
so_mark=100 |
||||
netif=eth0 |
||||
type=nat # public / nat / private |
||||
|
||||
[server: wireless_bkp] |
||||
addr=192.168.0.10:1234 |
||||
so_mark=100 |
||||
netif=eth0 |
||||
type=public # public / nat / private |
||||
|
||||
[client: client_test1] |
||||
|
||||
# линки |
||||
link=wired1_fast:192.168.0.20:1234 |
||||
link=wired1_fast:1.2.3.4:1234 |
||||
link=wireless_bkp:192.168.0.20:1234 |
||||
link=wireless_bkp:1.2.3.4:1234 |
||||
|
||||
#keepalive после ресета etcp передаём серверу |
||||
keepalive=1 |
||||
peer_public_key=deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef |
||||
Loading…
Reference in new issue