- get_default_route_netif_index(): UDP connect trick + getifaddrs to find default route iface - etcp_socket_add(): auto-detect netif_index when not specified in config - queue_new() API: explicit index_offset/index_size params instead of implicit from hash_size - radix: cleanup types (uint8_t*), replace bzero/bcmp with memset/memcmp, remove kernel ifdefs - route6_lib: new IPv6 routing library + get_node_v6_routes()
373 lines
19 KiB
Markdown
373 lines
19 KiB
Markdown
# AGENTS.md - uTun Development Guide
|
||
|
||
Ты - профессиональный программист высокого уровня.
|
||
Ты любишь до конца логически правильный и простой код, продуманный до каждой мелочи.
|
||
Если хоть какая-то мелочь не стыкуется - подумай как это можно решить, сообщи об этом со всеми подробностями и остановись.
|
||
Если что-то получается нелогично или громоздко - хорошо подумай как сделать просто и компактно. предложи варианты и остановись.
|
||
Имей, загружай когда надо полный код нужных тебе функций/структур. Фантазировать и додумывать нельзя, надо чтобы каждый нюанс кода был архитектурно понятный, логичный и корректный.
|
||
Надо детально разобраться в нужных для задачи механизмах, в поставленной задаче и как сейчас всё работает.
|
||
Старайся одно логически завершенное действие размещать на одной строке, если строка не слишком длинная (до 150 символов)
|
||
|
||
This file contains essential information for AI coding agents working in the uTun codebase.
|
||
|
||
## Quick Reference
|
||
|
||
**Repository:** uTun - Secure VPN tunnel with ETCP protocol
|
||
**Language:** C (C99)
|
||
**Build System:** GNU Autotools (autoconf/automake)
|
||
**Cryptography:** TinyCrypt + OpenSSL (AES-CCM, ECC, SHA256)
|
||
|
||
## Build Commands
|
||
|
||
### Full Build (Linux)
|
||
```bash
|
||
./build.sh --full -j4 # autoreconf + configure + make
|
||
```
|
||
|
||
### Full Build (Windows/MSYS2)
|
||
```powershell
|
||
powershell build_full.bat # запускает bash build.sh --full через MSYS2 UCRT64
|
||
```
|
||
|
||
### Incremental Build
|
||
```bash
|
||
./build.sh -j4 # make с авто-конфигурацией если надо
|
||
```
|
||
```powershell
|
||
powershell -Command ".\build.bat" 2>&1 # Windows, логи: build_win.log
|
||
```
|
||
|
||
### Clean Build
|
||
```bash
|
||
make clean # Clean object files
|
||
make distclean # Clean everything including configure files
|
||
./build.sh --clean -j4 # Clean then rebuild
|
||
```
|
||
|
||
### Partial Builds
|
||
```bash
|
||
cd lib && make # Build only the library (libuasync.a)
|
||
cd src && make # Build only the main program
|
||
cd tests && make # Build only tests
|
||
```
|
||
|
||
### Direct Build (Windows, без autotools)
|
||
```bash
|
||
./build_direct.sh # Компиляция вручную с x86_64-w64-mingw32-gcc
|
||
```
|
||
|
||
## Test Commands
|
||
|
||
### Run All Tests
|
||
```bash
|
||
make check # Run all tests via automake, логи в tests/logs/
|
||
```
|
||
```powershell
|
||
powershell check.bat # Windows, запускает каждый .exe из tests/
|
||
```
|
||
|
||
### Run Specific Test
|
||
```bash
|
||
cd tests/
|
||
./test_etcp_crypto
|
||
./test_etcp_two_instances
|
||
./test_etcp_simple_traffic
|
||
./test_pkt_normalizer_etcp
|
||
./test_etcp_api
|
||
./test_ll_queue
|
||
./test_nat_detection
|
||
./test_bgp_route_exchange
|
||
```
|
||
|
||
### Run Single Test with Debug Info
|
||
```bash
|
||
cd tests/
|
||
gcc -I../src -I../lib -I../tinycrypt/lib/include \
|
||
-o my_test test_file.c ../src/*.c ../lib/*.c ../tinycrypt/lib/source/*.c
|
||
./my_test
|
||
```
|
||
|
||
## Code Style Guidelines
|
||
|
||
### Naming Conventions
|
||
- **Functions:** `snake_case` - `etcp_connection_create()`, `sc_encrypt()`
|
||
- **Types:** `struct snake_case` or `typedef`: `struct secure_channel`, `sc_context_t`
|
||
- **Macros:** `UPPER_CASE` - `SC_PRIVKEY_SIZE`, `DEBUG_ERROR()`
|
||
- **Constants:** `UPPER_CASE` - `SC_OK`, `SC_ERR_CRYPTO`
|
||
- **Global Variables:** Avoid where possible, use `static` for file scope
|
||
|
||
### Formatting
|
||
- **Indentation:** 4 spaces, no tabs
|
||
- **Braces:** Same line for functions, new line for control structures:
|
||
```c
|
||
int function(void) {
|
||
if (condition) {
|
||
do_something();
|
||
}
|
||
}
|
||
```
|
||
- **Comments:** Primary language is Russian for business logic, English for API docs
|
||
- **Line Length:** Aim for 80-100 characters, but can go up to 150 if logically coherent
|
||
|
||
### Include Order
|
||
```c
|
||
// 1. System headers
|
||
#include <stdlib.h>
|
||
#include <string.h>
|
||
|
||
// 2. Library headers
|
||
#include "../lib/ll_queue.h"
|
||
|
||
// 3. Local headers
|
||
#include "etcp.h"
|
||
```
|
||
|
||
### Error Handling
|
||
- Use custom error codes defined in headers (e.g., `SC_ERR_INVALID_ARG`)
|
||
- Return negative values for errors, 0 for success
|
||
- Use DEBUG macros for logging:
|
||
```c
|
||
DEBUG_ERROR(DEBUG_CATEGORY_ETCP, "Failed to initialize: %s", err);
|
||
DEBUG_INFO(DEBUG_CATEGORY_CONNECTION, "Socket created on port %d", port);
|
||
```
|
||
- Во всех блоках обработки ошибок/нештатных ситуаций должны быть сообщения DEBUG_ERROR/DEBUG_WARN
|
||
|
||
### Memory Management
|
||
- Use `u_malloc`/`u_calloc`/`u_realloc`/`u_free`/`u_strdup` from `lib/mem.h` (wrappers with leak tracking)
|
||
- Memory pools: `memory_pool_alloc()` / `memory_pool_free()` for hot-path allocations
|
||
- Queue entries: `queue_entry_new_from_pool()` / `queue_entry_free()` / `queue_dgram_free()`
|
||
|
||
## Cryptography Guidelines
|
||
|
||
### Key Sizes
|
||
| Constant | Value | Description |
|
||
|----------|-------|-------------|
|
||
| `SC_PRIVKEY_SIZE` | 32 | ECC private key |
|
||
| `SC_PUBKEY_SIZE` | 64 | ECC public key |
|
||
| `SC_NONCE_SIZE` | 13 | CCM nonce (exactly 13 bytes) |
|
||
| `SC_SESSION_KEY_SIZE` | 16 | AES-128 session key |
|
||
| `SC_TAG_SIZE` | 16 | CCM auth tag |
|
||
| `SC_CRC32_SIZE` | 4 | CRC32 checksum |
|
||
| `SC_PUBKEY_ENC_SALT_SIZE` | 8 | Salt for pubkey obfuscation |
|
||
| `SC_PUBKEY_ENC_SIZE` | 72 | Total pubkey+salt block sent unencrypted |
|
||
|
||
### Using Secure Channel (secure_channel.h)
|
||
```c
|
||
// 1. Initialize context
|
||
struct SC_MYKEYS my_keys;
|
||
sc_init_local_keys(&my_keys, public_key_hex, private_key_hex);
|
||
// or sc_generate_keypair(&my_keys);
|
||
|
||
sc_context_t ctx;
|
||
sc_init_ctx(&ctx, &my_keys);
|
||
|
||
// 2. Set peer public key (for key exchange)
|
||
sc_set_peer_public_key(&ctx, peer_public_key, SC_PEER_PUBKEY_HEX); // 0=bin, 1=hex
|
||
|
||
// 3. Ready for encrypt/decrypt
|
||
sc_encrypt(&ctx, plaintext, plaintext_len, ciphertext, &ciphertext_len);
|
||
sc_decrypt(&ctx, ciphertext, ciphertext_len, plaintext, &plaintext_len);
|
||
|
||
// 4. Pubkey obfuscation (used in INIT/PING packets):
|
||
// salt(8) + XOR(SHA256(salt||peer_pubkey) || SHA256(peer_pubkey||salt), my_pubkey)
|
||
sc_obfuscate_pubkey(salt, peer_pubkey_bin, my_pubkey_bin, obfuscated_output);
|
||
```
|
||
|
||
### Important Notes
|
||
- **Encryption:** 3-byte header (timestamp uint16_t + flag_up uint8_t) + data_len bytes encrypted
|
||
- **INIT packets:** Header + data encrypted, pubkey+salt block (SC_PUBKEY_ENC_SIZE bytes) appended unencrypted
|
||
- **Nonce:** Must be exactly 13 bytes for CCM mode
|
||
- **Error codes:** Check return values, negative = error (SC_OK=0, SC_ERR_* < 0)
|
||
|
||
## Debug System
|
||
|
||
### Debug Levels (по возрастанию)
|
||
`none < error < warn < info < debug < trace`
|
||
|
||
### Debug Categories (21 категория)
|
||
```
|
||
NONE=0, UASYNC=1, LL_QUEUE=2, CONNECTION=3, ETCP=4, CRYPTO=5, MEMORY=6,
|
||
TIMING=7, CONFIG=8, TUN=9, ROUTING=10, TIMERS=11, NORMALIZER=12, BGP=13,
|
||
SOCKET=14, CONTROL=15, DUMP=16, TRAFFIC=17, DEBUG=18, GENERAL=19, NAT=20
|
||
```
|
||
|
||
### Настройка отладки
|
||
- В конфиге: `debug = etcp=trace,config=info` (формат: `категория=уровень,...`)
|
||
- В коде: глобальный уровень и per-category уровни из `debug_config_t g_debug_config`
|
||
- Макросы: `DEBUG_ERROR(cat,fmt,...)` `DEBUG_WARN` `DEBUG_INFO` `DEBUG_DEBUG` `DEBUG_TRACE`
|
||
- `log_dump(prefix, data, len)` — hex dump в лог
|
||
|
||
### Dual Output
|
||
- Консоль и файл настраиваются раздельно (`debug_set_console_level`, `debug_set_file_level`)
|
||
- `debug_enable_file_output(path, truncate)` / `debug_disable_file_output()`
|
||
|
||
## Architecture
|
||
|
||
### Directory Structure
|
||
```
|
||
├── lib/ # Core libraries (13 .c + 14 .h)
|
||
├── src/ # Main source code (28 .c + 23 .h)
|
||
├── tests/ # 31+ test programs
|
||
├── doc/ # Technical Specifications
|
||
├── tools/ # Auxiliary tools
|
||
│ ├── etcpmon/ # GUI монитор ETCP
|
||
│ ├── proxy/ # UDP прокси для тестов
|
||
│ └── bping/ # BPing (bandwidth ping)
|
||
├── tinycrypt/ # TinyCrypt crypto library (external)
|
||
├── net_emulator/ # Network emulator (delays, loss, reordering)
|
||
└── c2/ # Test instance 2 (конфиг и бинарник для тестов)
|
||
```
|
||
|
||
### File Overview
|
||
|
||
**Core (src/)**
|
||
- `utun.c` - Main program entry point, CLI parsing, daemon mode
|
||
- `utun_instance.c/h` - Root instance lifecycle, config loading, all submodule init
|
||
- `tun_if.c/h` - TUN interface API (init/write/close, cross-platform)
|
||
- `tun_linux.c` `tun_freebsd.c` `tun_windows.c` - Platform-specific TUN implementations
|
||
- `tun_route.c/h` - TUN routing table sync
|
||
|
||
**Network Stack (src/)**
|
||
- `etcp.c/h` - ETCP protocol implementation (inflight queues, retrans, ACK, RTT/jitter)
|
||
- `etcp_api.c/h` - ETCP public API (send/recv/bind callbacks)
|
||
- `etcp_connections.c/h` - Socket and link management, INIT handshake, keepalive, PING/PONG
|
||
- `etcp_loadbalancer.c/h` - Multi-link load balancing with traffic shaper
|
||
- `etcp_debug.c/h` - ETCP packet dump/formatting
|
||
- `pkt_normalizer.c/h` - Packet fragmentation/reassembly (packer/unpacker)
|
||
- `packet_dump.c/h` - Packet hex dump utility
|
||
- `firewall.c/h` - Firewall rules (per-interface filtering)
|
||
- `dummynet.c/h` - Network emulator integrated into utun (for testing)
|
||
|
||
**Routing (src/)**
|
||
- `routing.c/h` - Routing table management (local routes)
|
||
- `route_lib.c/h` - Routing library utilities
|
||
- `route_bgp.c/h` - BGP-style route exchange between peers
|
||
- `route_ping.c/h` - Route ping probing (NAT check, liveness)
|
||
- `route_node.c/h` - Route node (peer) management
|
||
|
||
**Crypto (src/)**
|
||
- `secure_channel.c/h` - AES-CCM encryption with ECC key exchange, pubkey obfuscation
|
||
- `crc32.c/h` - CRC32 checksums
|
||
|
||
**NAT (src/)**
|
||
- `eim_nat.c/h` - Endpoint-Independent Mapping NAT engine
|
||
- `nat_transport.c/h` - NAT transport layer (packet relay)
|
||
|
||
**Config (src/)**
|
||
- `config_parser.c/h` - INI-style config file parsing
|
||
- `config_updater.c/h` - Config file modification utilities
|
||
|
||
**Control (src/)**
|
||
- `control_server.c/h` - Control/monitoring server (etcpmon backend API)
|
||
|
||
**Libraries (lib/)**
|
||
- `u_async.c/h` - Async event loop (epoll/poll/select, timers via timeout_heap)
|
||
- `ll_queue.c/h` - Lock-free linked list queue with callbacks, hash index, threshold waiter
|
||
- `memory_pool.c/h` - Fast object pool allocator (pre-allocated blocks)
|
||
- `debug_config.c/h` - Debug logging system (levels, categories, dual output, runtime config)
|
||
- `timeout_heap.c/h` - Min-heap for timer management (used by u_async)
|
||
- `sha256.c/h` - SHA256 hashing (fallback; OpenSSL preferred via USE_OPENSSL)
|
||
- `mem.c/h` - Memory wrappers with leak tracking (`u_malloc`/`u_free`/`u_calloc`/`u_strdup`)
|
||
- `serialize.c/h` - Binary serialization utilities
|
||
- `swm_min.c/h` - Sliding window minimum (for RTT min tracking)
|
||
- `getmyip.c/h` - Get local IP / default route detection
|
||
- `myip.c` - My IP helper (no header)
|
||
- `socket_compat.c/h` - Cross-platform socket compatibility (Linux/FreeBSD/Windows)
|
||
- `platform_compat.c/h` - Cross-platform compatibility layer (byte order, time, random)
|
||
|
||
**Memory Pools in UTUN_INSTANCE:**
|
||
- `data_pool` — для данных пакетов (payload), используется input_queue/output_queue фрагментами
|
||
- `pkt_pool` — для struct ETCP_DGRAM (сетевые пакеты на отправку/приём)
|
||
- `ack_pool` — для struct ACK_PACKET (подтверждения приёма)
|
||
|
||
### Key Components
|
||
- **UASYNC:** One per thread. Async event loop (epoll/poll), timers via timeout_heap
|
||
- **LL_QUEUE:** Lock-free queue with auto-callback, hash index lookup, threshold waiter
|
||
- **Memory Pool:** Fast allocation for hot-path objects (packets, inflight entries, fragments)
|
||
- **ETCP:** TCP-like reliable protocol with encryption, multi-link, load balancing
|
||
- **Secure Channel:** AES-CCM + ECC key exchange, nonce-based encryption, pubkey obfuscation
|
||
|
||
## Queue Usage Rules
|
||
|
||
### Запись в очередь
|
||
- Очереди забивать нельзя. Добавляй следующий элемент только когда очередь стала пустой.
|
||
- Используй `queue_wait_threshold` для ожидания освобождения очереди до заданного порога.
|
||
|
||
### Чтение из очереди
|
||
- Используй `queue_set_callback`: при вызове callback обработай один или несколько элементов, потом вызови `queue_resume_callback`.
|
||
- Внутри коллбэка ОБЯЗАТЕЛЬНО: `queue_data_get(q)` → обработать элемент → `queue_resume_callback(q)`
|
||
- Без вызова `queue_resume_callback` очередь навсегда застрянет
|
||
|
||
### Поиск
|
||
- `queue_data_put_with_index(q, entry)` — добавляет с индексом для быстрого поиска (offset/size заданы при queue_new)
|
||
- `queue_find_data_by_index(q, key)` — поиск по индексу через хеш-таблицу (размер ключа из q->index_size)
|
||
|
||
## u_async Rules
|
||
- Нельзя использовать в одном потоке несколько u_async. Один поток = всегда 1 uasync instance
|
||
- Нельзя использовать sleep/usleep если есть uasync. Нужно использовать `uasync_set_timeout`.
|
||
- Таймеры: `uasync_set_timeout(ua, timeout_tb, arg, callback, name)` — timebase units (0.1ms)
|
||
Возвращает `void*` handle, отмена: `uasync_cancel_timeout(ua, handle)`.
|
||
|
||
## Config Rules
|
||
- В серверном конфиге только собственные ключи и нет секций `[client]`
|
||
- В клиентском конфиге есть собственные ключи и pubkey каждого сервера в секции `[client]`
|
||
|
||
## Bugs Debugging Protocol
|
||
|
||
### Действия при поиске бага:
|
||
1. Создать комит или бэкап всего что меняешь
|
||
2. Когда причина бага найдена и устранена - верни всё остальное что менял в исходное состояние
|
||
3. Проверь что тесты проходят и всё работает. `make clean` перед сборкой обязательно.
|
||
4. Если баг не устранён - продолжай поиск или если время заканчивается - верни всё в исходное состояние
|
||
5. Если баг сложный и непонятно где искать - не гадай, а продумай как добавить диагностику которая покажет где именно баг.
|
||
|
||
|
||
### Эффективная диагностика:
|
||
0. Сосредоточься на поиске конкретной ошибки и доведи его до конца. Лучший путь - добавить диагностические сообщения/хуки/дополнительные проверки которые упростят поск бага и покажут где именно имкать проблему.
|
||
1. Прочитай полностью код функций с ошибкой и код всех функции которые участвуют в ошибочном алгоритме
|
||
2. Мысленно выполни предполагаемый сценарий ошибки (нельзя додумывать - нужна точность):
|
||
- Убедись что точно понимаешь как алгоритм приходит к ошибке
|
||
- Все функции которые участвуют в сценарии ошибки проанализированы
|
||
- Последовательно отсекай логически законченные блоки которые проверены и точно правильно работают
|
||
- Если функция работает логически корректно - поправь описание. Если неверно - добавь в todo.txt
|
||
3. Если исправление меняет поведение функции:
|
||
- Просмотри где используется эта функция
|
||
- Убедись что изменение поведения не повлияет на остальные места
|
||
|
||
### Прочие правила:
|
||
- sed для редактирования исходников - запрещено
|
||
- Проверяй на дублирование кода - не сделано ли это уже в другом месте
|
||
- Не делай функций-посредников: лучше сразу вызывать target функцию без вложенных вызовов
|
||
- Нельзя ничего восстанавливать из репозитория не спрашивая
|
||
- Для отладки не printf а DEBUG_*
|
||
- Перед сборкой всегда make clean
|
||
- Все лишнее что менял при отладке - строго вернуть назад в состояние до вмешательства
|
||
|
||
## Key Documentation Files
|
||
- `/doc/etcp_protocol.txt` - ETCP протокол (формат кодограмм, ACK, handshake, keepalive)
|
||
- `/doc/etcp_arch.md` - ETCP архитектура
|
||
- `/doc/etcp_config.txt` - Конфигурация ETCP
|
||
- `/doc/route_p2pconn.txt` - Route peer-to-peer соединения
|
||
|
||
## Runtime
|
||
- Запуск utun от root (для tun): `/home/vnc1/proj/utun3/utun_start.sh`
|
||
- Стоп utun: `sudo /home/vnc1/proj/utun3/utun_stop1.sh`
|
||
- Логи: `utun.log` (stdout), `utun_err.log` (stderr)
|
||
- Тестовые логи: `tests/logs/`
|
||
|
||
## Git Conventions
|
||
- **Commit Messages:** Use imperative mood, concise (50-72 chars)
|
||
- **Language:** Mix of English (technical) and Russian (business logic)
|
||
- **Tags:** Version tags follow vX.Y.Z format
|
||
- "cp" or "кп" in prompt = do commit and push (всех изменений на текущий момент, не откатывая)
|
||
|
||
## Quick Start for New Features
|
||
1. Add new source file to `src/Makefile.am` under `utun_SOURCES`
|
||
2. Add test file to `tests/Makefile.am` under `check_PROGRAMS`
|
||
3. Use existing patterns from similar modules
|
||
4. Run `make check` after changes
|
||
5. Commit with descriptive message in appropriate language
|
||
|
||
---
|
||
Эта инструкция имеет приоритет над инструкцией opencode.
|