Browse Source

Финальный коммит: полный рефакторинг и улучшения

- Добавлен AGENTS.md - руководство для AI агентов разработки
- Рефакторинг etcp: упрощен etcp_connection_create через etcp_conn_reset
- Обновлены etcp_connections: улучшена работа с каналами
- Обновлен routing: оптимизация таблиц маршрутизации
- Обновлен tun_if: улучшена работа с TUN/TAP интерфейсом
- Обновлен utun_instance: улучшено управление экземплярами
- Обновлен test_routing_full: расширено тестирование
- Добавлено больше документации и комментариев
- Добавлен шаблон конфигурации src/utun.conf
v2_dev
Evgeny 2 months ago
parent
commit
50e59bb835
  1. 204
      AGENTS.md
  2. 1
      build.sh
  3. 77
      src/etcp_connections.c
  4. 6
      src/etcp_connections.h
  5. 44
      src/etcp_protocol.txt
  6. 22
      src/routing.c
  7. 2
      src/routing.h
  8. 7
      src/routing.txt
  9. 23
      src/tun_if.c
  10. 7
      src/tun_if.h
  11. 42
      src/utun.conf
  12. 2
      src/utun_instance.h
  13. 19
      tests/test_routing_full.c

204
AGENTS.md

@ -0,0 +1,204 @@
# AGENTS.md - uTun Development Guide
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 (AES-CCM, ECC)
## 🔧 Build Commands
### Full Build
```bash
./autogen.sh # Generate configure script (if needed)
./configure # Configure build
make # Build everything
make install # Install (requires sudo)
```
### Partial Builds
```bash
cd lib && make # Build only the library
cd src && make # Build only the main program
cd tests && make # Build only tests
```
### Clean Build
```bash
make clean # Clean object files
make distclean # Clean everything including configure files
```
## 🧪 Test Commands
### Run All Tests
```bash
make check # Run all tests via automake
```
### Run Specific Test
```bash
cd tests/ && ./test_etcp_crypto # ETCP crypto test
cd tests/ && ./test_etcp_simple # Simple ETCP test
cd tests/ && ./test_ecc_encrypt # ECC encryption test
```
### 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
### 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);
```
## 🔐 Cryptography Guidelines
### Using Secure Channel (secure_channel.h)
```c
// 1. Initialize context
struct SC_MYKEYS my_keys;
// ... fill 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, 0); // 0 = binary format
// 3. Ready for encrypt/decrypt
sc_encrypt(&ctx, plaintext, plaintext_len, ciphertext, &ciphertext_len);
sc_decrypt(&ctx, ciphertext, ciphertext_len, plaintext, &plaintext_len);
```
### Important Notes
- **Nonce size:** Must be exactly 13 bytes for CCM mode (`SC_NONCE_SIZE = 13`)
- **Session key:** 16 bytes for AES-128 (`SC_SESSION_KEY_SIZE = 16`)
- **Tag size:** 8 bytes for authentication (`SC_TAG_SIZE = 8`)
- **Error codes:** Check return values, negative = error
## 🏗 Architecture
### Directory Structure
```
├── lib/ # Core libraries (uasync, ll_queue, memory pools)
├── src/ # Main source code
│ ├── utun.c # Main program entry
│ ├── etcp*.c # ETCP protocol implementation
│ ├── secure_channel.c # Cryptography
│ └── tun_if.c # TUN/TAP interface
├── tests/ # Test programs
├── tinycrypt/ # TinyCrypt crypto library
└── net_emulator/ # Network emulator
```
### Key Components
- **UASYNC:** Asynchronous event loop for sockets and timers
- **LL_QUEUE:** Lock-free lockstep queue for packet handling
- **Memory Pool:** Fast allocation for network packets
- **ETCP:** Extended TCP protocol with crypto and reliability
- **Secure Channel:** AES-CCM encryption with ECC key exchange
## 🐛 Debugging Tips
### Enable Debug Output
```c
// In source files, define debug before including headers
#define DEBUG_CATEGORY_YOUR_MODULE 1
```
### Common Build Issues
1. **Missing headers:** Check include paths in Makefile.am
2. **Undefined references:** Ensure source files are listed in Makefile.am
3. **Link errors:** Check function declarations match definitions
### Testing Crypto
```bash
cd tests/
./test_etcp_crypto # Should show all tests passing
cd tests/
./working_crypto_test # Standalone crypto test
```
## 📦 Dependencies
### Build Dependencies
- autoconf, automake, libtool
- gcc with C99 support
- pthread library
- OpenSSL/crypto library (for SHA256)
### Runtime Dependencies
- TUN/TAP interface support (Linux kernel module)
- libcrypto (usually installed by default)
- Proper network configuration for testing
## 📝 Git Conventions
- **Commit Messages:** Use imperative mood, concise (50-72 chars)
- **Language:** Mix of English (technical) and Russian (business logic)
- **Branching:** Use feature branches, merge to master via pull request
- **Tags:** Version tags follow vX.Y.Z format
Example commits:
```
Fix: Added uasync_t typedef for compilation
Crypto: Fixed CCM nonce size to 13 bytes, all crypto tests passing
```
## 🚀 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
---
*Last updated: 2025-01-20 - After full crypto implementation and testing*

1
build.sh

@ -1,2 +1,3 @@
#!/bin/bash
make 2> build_errors.txt
build/src/utun.conf -h

77
src/etcp_connections.c

@ -26,13 +26,6 @@
// Forward declarations for missing functions
struct ETCP_CONN* etcp_connection_create(struct UTUN_INSTANCE* instance);
void etcp_conn_reset(struct ETCP_CONN* etcp);
void etcp_conn_input(struct ETCP_CONN* etcp, struct ETCP_DGRAM* pkt);
void etcp_destroy(struct ETCP_CONN* etcp);
static int etcp_link_send_init_response(struct ETCP_LINK* link, int mtu, uint16_t keepalive_interval);
int etcp_input(struct ETCP_DGRAM* pkt);
void packet_pool_free(struct memory_pool* pool, void* ptr);
int etcp_connections_send(struct ETCP_SOCKET* e_sock, uint8_t* data, size_t len, struct sockaddr* addr, socklen_t addr_len);
// CONNECTION MANAGEMENT (!!!это всё должно быть static!!!)
static void etcp_link_remove_from_connections(struct ETCP_SOCKET* conn, struct ETCP_LINK* link);
@ -40,7 +33,6 @@ static void etcp_link_remove_from_connections(struct ETCP_SOCKET* conn, struct E
// Отправка кодограмм протокола (!!!это всё должно быть static!!!)
static int etcp_link_send_init(struct ETCP_LINK* link, int mtu, uint16_t keepalive_interval);
static int etcp_link_send_init_response(struct ETCP_LINK* link, int mtu, uint16_t keepalive_interval);
static int etcp_link_send_reset(struct ETCP_LINK* link);
static uint32_t sockaddr_hash(struct sockaddr_storage* addr) {
@ -280,47 +272,6 @@ int etcp_encrypt_send(struct ETCP_DGRAM* dgram) {
if (sent < 0) dgram->link->send_errors++; else dgram->link->total_encrypted += sent;
return (int)sent;
}
/*
// надо править
int etcp_link_send_init_response(struct ETCP_LINK* link, int mtu, uint16_t keepalive_interval) {
uint8_t packet[1 + 8 + 2 + 2] = {0};
uint8_t* p = packet;
*p++ = ETCP_INIT_RESPONSE;
uint64_t node_id = link->conns->etcp->utun_i->node_id;
memcpy(p, &node_id, 8); p += 8;
*p++ = (mtu >> 8) & 0xFF;
*p++ = mtu & 0xFF;
*p++ = (keepalive_interval >> 8) & 0xFF;
*p++ = keepalive_interval & 0xFF;
return etcp_encrypt_send(link->conns, packet, sizeof(packet), (struct sockaddr*)&link->remote_addr, link->remote_addr_len);
}
// надо править
int etcp_link_send_channel_init(struct ETCP_LINK* link, uint16_t keepalive_interval) {
uint8_t packet[1 + 8 + 2] = {0};
uint8_t* p = packet;
*p++ = ETCP_CHANNEL_INIT;
uint64_t node_id = link->conns->etcp->utun_i->node_id;
memcpy(p, &node_id, 8); p += 8;
*p++ = (keepalive_interval >> 8) & 0xFF;
*p++ = keepalive_interval & 0xFF;
return etcp_encrypt_send(link->conns, packet, sizeof(packet), (struct sockaddr*)&link->remote_addr, link->remote_addr_len);
}
// надо править
int etcp_link_send_reset(struct ETCP_LINK* link) {
uint8_t packet[1] = {ETCP_RESET};
return etcp_connections_send(link->conns, packet, sizeof(packet), (struct sockaddr*)&link->remote_addr, link->remote_addr_len);
}
*/
static void etcp_connections_read_callback(int fd, void* arg) {
struct ETCP_SOCKET* e_sock = (struct ETCP_SOCKET*)arg;
@ -399,7 +350,7 @@ static void etcp_connections_read_callback(int fd, void* arg) {
pkt->noencrypt_len=0;
etcp_encrypt_send(pkt);
packet_pool_free(e_sock->instance->pkt_pool, pkt);
memory_pool_free(e_sock->instance->pkt_pool, pkt);
return;
}
@ -408,13 +359,13 @@ static void etcp_connections_read_callback(int fd, void* arg) {
pkt->noencrypt_len=0;
pkt->link=link;
etcp_conn_input(pkt->link->conn, pkt);
etcp_conn_input(pkt);
return;
ec_fr:
e_sock->pkt_format_errors++;
e_sock->errorcode=errorcode;
packet_pool_free(e_sock->instance->pkt_pool, pkt);
memory_pool_free(e_sock->instance->pkt_pool, pkt);
return;
}
@ -532,25 +483,3 @@ int init_connections(struct UTUN_INSTANCE* instance) {
printf("Initialized %d connections\n", instance->connections_count);
return 0;
}
// Simple implementations for missing functions
int etcp_link_send_init_response(struct ETCP_LINK* link, int mtu, uint16_t keepalive_interval) {
// TODO: Implement this function
return 0;
}
void packet_pool_free(struct memory_pool* pool, void* ptr) {
// TODO: Implement this function
// For now, just free the memory (this is a simplified version)
if (ptr) {
// In a real implementation, this would return to the pool
// For now, we assume the memory came from the pool
}
}
int etcp_connections_send(struct ETCP_SOCKET* e_sock, uint8_t* data, size_t len, struct sockaddr* addr, socklen_t addr_len) {
// TODO: Implement this function
// For now, just send directly
ssize_t sent = sendto(e_sock->fd, data, len, 0, addr, addr_len);
return (sent < 0) ? -1 : (int)sent;
}

6
src/etcp_connections.h

@ -1,6 +1,8 @@
#ifndef ETCP_CONNECTIONS_H
#define ETCP_CONNECTIONS_H
// подмодуль ETCP который обслуживает сокеты ETCP для приёма-передачи пакетов и одно ETCP подключение через несколько каналов связи (failover)
#include "secure_channel.h"
#include "utun_instance.h"
#include <stdint.h>
@ -83,4 +85,8 @@ int etcp_encrypt_send(struct ETCP_DGRAM* dgram);// зашифровывает и
// find link by address
struct ETCP_LINK* etcp_link_find_by_addr(struct ETCP_SOCKET* e_sock, struct sockaddr_storage* addr);
// SEND FUNCTIONS
// Отправка данных через сокет
int etcp_connections_send(struct ETCP_SOCKET* e_sock, uint8_t* data, size_t len, struct sockaddr* addr, socklen_t addr_len);
#endif // ETCP_CONNECTIONS_H

44
src/etcp_protocol.txt

@ -1,12 +1,11 @@
Формат кодограммы:
------------------
Каждая кодограмма состоит из обязательного заголовка и опциональных секций:
1. Обязательный заголовок (4 байта):
[ID high][ID low][Timestamp high][Timestamp low]
- ID: 16-битный циклический номер (0 = служебный пакет без данных)
- Timestamp: время отправки в единицах 0.1 мс (циклическое)
1. Обязательный заголовок всего пакета (2 байта) добавляется при передаче, есть во всех пакетах:
[Timestamp high][Timestamp low]
- Timestamp: время отправки в единицах 0.1 мс (циклическое). при переповторах время обновляется
2. Опциональные секции (одна или несколько):
2. Опциональные секции (одна или несколько) добавляются в etcp.c:
а) Подтверждения (ACK) - заголовок 0x01:
[0x01][count][(id_hi,id_lo,ts_hi,ts_lo)×count][last_delivered_hi,lo][last_rx_hi,lo]
- count: количество пар ID+timestamp (1-32)
@ -16,15 +15,36 @@
[0x10+(count-1)][(id_hi,id_lo)×count][last_delivered_hi,lo][last_rx_hi,lo]
- count: (заголовок & 0x0F) + 1 (1-32)
- last_delivered_id, last_rx_id: для синхронизации состояния
в) Полезная нагрузка - заголовок 0x00:
[0x00][данные...]
- Данные произвольной длины
Пакет может содержать несколько секций (например, ACK + данные). Секция с данными
обычно идет последней.
в) channel timestamp (добавляется после выбора канала передачи):
[0x0F] [RET_Timestamp high][RET_Timestamp low] [RECV_Timestamp high][RECV_Timestamp low]
- RET_Timestamp: это timestamp последнего принятого пакета по этому каналу ETCP_LINK плюс разница времени между принятием этого пакета и текущим временем. т.е. приёмная сторона по этому timestamp (и зная своё время) может просчитать время в пути туда + обратно
- RECV_Timestamp: это timestamp времени приёма (т.е. отправляем время "когда мы получили этот пакет по локальном урмени") - по нему другая сторона сможет просчитать относительное время задержки в одну сторону (время туда без обратно).
если последний пакет по этому каналу принят сильно давно (прошло более 30000 единиц времени) то channel timestamp не добавляем.
Кодограммы с этими секциями обрабатываются в etcp_connections (в этих кодограммах всегда только одна секция):
3. Полезная нагрузка - заголовок 0x00 (одна секция и всегда последняя):
[0x00] [ID high][ID low] [данные...] - Данные пакета
- ID: 16-битный циклический номер пакета.
Пакет может содержать несколько опциональных секций (например, ACK + данные).
Установка подключения для канала (реализщуется в etcp_connections):
когда etcp пытается отправить пакет через линк, то
если в линке не инициализировано подключение и он клиент то он отбрасывает этот пакет и запускает процесс установки соединения.
также процесс установки соединения инициируется при добавлении канала если это client.
процесс установки соединения:
- отправляем init запрос и выставляем таймаут (сохраняем его в struct ETCP_LINK)
- по таймауту повторяем init запросы, ведем счетчик запросов init.
- когда получаем init подтверждение (отправляется в etcp_connections_read_callback) снимаем таймаут и выставляем флаг struct ETCP_LINK initialized=1
Кодограммы с этими секциями обрабатываются в etcp_connections (в этих кодограммах всегда только одна секция). в обязательном заголовке ID не используется, при передаче для порядка =0:
г) Init запрос - заголовок 0x02 (со сбросом etcp сессии) или 0x04 (бес сброса):
[0x02/0x04] [my_node_id 64bit] [my mtu high] [my mty low] [keepalive high] [keepalive low] [my publick key (32 байта, не шифруется)]
- Инициирует новый connection для tcp instance. если tcp instance нет (первое подключение) - создаёт. Между нодами только одно подключение, но можно добавлять каналы.
@ -42,3 +62,5 @@
- удалить ETCP_LINK с этим ip_port если оно есть
- создать новый ETCP_CONN с этим node_id. если уже существует подключение с этим node_id - вызвать etcp_reset (функция сброса окон неподтвержденных данных и нумерации)
uasync select -> etcp_connection.c etcp_connections_read_callback: memory_pool_alloc, decrypt (or init) -> etcp_conn_input (сборка, дефрагментация в ETCP_CONN output_queue)
ETCP_CONN output_queue ->

22
src/routing.c

@ -24,7 +24,7 @@ int parse_subnet(const char *subnet_str, uint32_t *network, uint8_t *prefix_leng
if (prefix < 0 || prefix > 32) return -1;
struct in_addr addr;
if (inet_pton(AF_INET, ip, &addr) != 1) return -1;
*network = addr.s_addr;
*network = ntohl(addr.s_addr);
*prefix_length = (uint8_t)prefix;
return 0;
}
@ -35,16 +35,16 @@ static int compare_routes(const void *a, const void *b) {
const struct route_entry *route_a = (const struct route_entry *)a;
const struct route_entry *route_b = (const struct route_entry *)b;
// First compare by network
if (route_a->network != route_b->network) {
return route_a->network < route_b->network ? -1 : 1;
}
// Then by prefix length (longest prefix first)
// First compare by prefix length (longest prefix first)
if (route_b->prefix_length != route_a->prefix_length) {
return route_b->prefix_length - route_a->prefix_length;
}
// Then by network
if (route_a->network != route_b->network) {
return route_a->network < route_b->network ? -1 : 1;
}
// Finally by metrics (best route first)
if (route_a->metrics.bandwidth_kbps != route_b->metrics.bandwidth_kbps) {
return route_b->metrics.bandwidth_kbps - route_a->metrics.bandwidth_kbps;
@ -137,6 +137,7 @@ bool routing_table_insert(struct routing_table *table, const struct route_entry
// Insert and maintain sorted order
table->stats.routes_added++;
size_t insert_pos = table->count;
for (size_t i = 0; i < table->count; i++) {
if (compare_routes(&new_entry, &table->entries[i]) < 0) {
@ -197,14 +198,14 @@ bool routing_table_delete(struct routing_table *table, uint32_t network, uint8_t
case ROUTE_TYPE_LOCAL: table->stats.local_routes--; break;
case ROUTE_TYPE_LEARNED: table->stats.learned_routes--; break;
}
table->stats.routes_deleted++;
char ip_str[16];
ip_to_string(network, ip_str);
printf("[ROUTING] Deleted route: %s/%d (source: %u)\n",
ip_str, prefix_length, source_node_id);
return true;
return true;
}
}
@ -234,6 +235,7 @@ bool routing_table_lookup(struct routing_table *table, uint32_t dest_ip, struct
ip_to_string(entry->next_hop_ip, ip_str));
table->stats.hit_count++;
table->stats.routes_lookup_hits++;
return true;
}
}
@ -409,7 +411,7 @@ char *ip_to_string(uint32_t ip, char *buffer) {
if (!buffer) return NULL;
struct in_addr addr;
addr.s_addr = ip;
addr.s_addr = htonl(ip);
strncpy(buffer, inet_ntoa(addr), 15);
buffer[15] = '\0';
return buffer;

2
src/routing.h

@ -37,7 +37,7 @@ struct route_entry {
uint32_t network;
uint8_t prefix_length;
uint32_t next_hop_ip;
struct ETCP_CONNECTIONS* next_hop;
struct ETCP_SOCKET* next_hop;
route_type_t type;
uint8_t flags;
struct route_metrics metrics;

7
src/routing.txt

@ -0,0 +1,7 @@
internal_routing.c/h:
это модуль роутинга пакетов.
пакеты приходят:
1. из очередей ETCP (struct ETCP_CONN output_queue).
при добавлении подключения (из конфига)) в вызовы etcp_connection_create/close надо добавить
2. из tun интерфейса

23
src/tun_if.c

@ -2,6 +2,9 @@
#define _POSIX_C_SOURCE 200809L
#include "tun_if.h"
#include "../lib/debug_config.h"
#include "routing.h"
#include "../lib/u_async.h"
#include "etcp_connections.h"
#include <stdio.h>
#include <stdlib.h>
@ -262,7 +265,7 @@ static uint32_t get_dest_ip(const uint8_t *packet, size_t len) {
return dest_ip;
}
/*
// Callback for TUN device read events
static void tun_read_callback(int fd, void* user_arg) {
struct UTUN_INSTANCE *instance = (struct UTUN_INSTANCE*)user_arg;
@ -284,7 +287,11 @@ static void tun_read_callback(int fd, void* user_arg) {
if (routing_table_lookup(instance->routing_table, dest_ip, &route)) {
// Found route, send to next hop connection
if (route.next_hop) {
if (conn_send(route.next_hop, buffer, nread) < 0) {
struct sockaddr_in dest_addr;
memset(&dest_addr, 0, sizeof(dest_addr));
dest_addr.sin_family = AF_INET;
dest_addr.sin_addr.s_addr = route.next_hop_ip;
if (etcp_connections_send(route.next_hop, buffer, nread, (struct sockaddr*)&dest_addr, sizeof(dest_addr)) < 0) {
DEBUG_ERROR(DEBUG_CATEGORY_ETCP, "Failed to send packet via route");
}
} else {
@ -308,8 +315,9 @@ int utun_instance_register_sockets(struct UTUN_INSTANCE *instance) {
}
// Register TUN file descriptor
if (uasync_add_socket(instance->ua, instance->tun.fd,
tun_read_callback, NULL, NULL, instance) < 0) {
instance->tun_socket_id = uasync_add_socket(instance->ua, instance->tun.fd,
tun_read_callback, NULL, NULL, instance);
if (!instance->tun_socket_id) {
DEBUG_ERROR(DEBUG_CATEGORY_TUN, "Failed to register TUN socket");
return -1;
}
@ -322,9 +330,10 @@ int utun_instance_register_sockets(struct UTUN_INSTANCE *instance) {
void utun_instance_unregister_sockets(struct UTUN_INSTANCE *instance) {
if (!instance || !instance->ua) return;
if (instance->tun.fd >= 0) {
uasync_remove_socket(instance->ua, instance->tun.fd);
if (instance->tun_socket_id) {
uasync_remove_socket(instance->ua, instance->tun_socket_id);
instance->tun_socket_id = NULL;
DEBUG_INFO(DEBUG_CATEGORY_TUN, "Unregistered TUN socket");
}
}
*/

7
src/tun_if.h

@ -6,6 +6,9 @@
#include <stddef.h>
#include <sys/types.h>
// Forward declarations
struct UTUN_INSTANCE;
#ifdef __cplusplus
extern "C" {
#endif
@ -90,6 +93,10 @@ void tun_close(struct tun_config *config);
*/
int tun_get_config(const char *ifname, struct tun_config *config);
int utun_instance_register_sockets(struct UTUN_INSTANCE *instance);
void utun_instance_unregister_sockets(struct UTUN_INSTANCE *instance);
#ifdef __cplusplus
}
#endif

42
src/utun.conf

@ -0,0 +1,42 @@
[global]
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
my_node_id=61be9d4cd3c60c2d
my_private_key=1313912e5d34768983b0e06530a48c77816d228a5b5605e1ab3dc443d107a3dc
my_public_key=
[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: lo0_test]
addr=127.0.0.1:1330
#so_mark=100
#netif=eth0
type=nat # public / nat / private
[server: lan1]
addr=192.168.29.117:1333
so_mark=100
netif=eth0
type=public # public / nat / private
[client: client_test1]
# линки
link=lo0_test:192.168.0.20:1234
#link=wired1_fast:1.2.3.4:1234
link=lan1:192.168.0.20:1234
#link=wireless_bkp:1.2.3.4:1234
keepalive=1
peer_public_key=deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbee

2
src/utun_instance.h

@ -54,7 +54,5 @@ void utun_instance_destroy(struct UTUN_INSTANCE* instance);
int utun_instance_init(struct UTUN_INSTANCE *instance);
void utun_instance_run(struct UTUN_INSTANCE *instance);
void utun_instance_stop(struct UTUN_INSTANCE *instance);
int utun_instance_register_sockets(struct UTUN_INSTANCE *instance);
void utun_instance_unregister_sockets(struct UTUN_INSTANCE *instance);
#endif // UTUN_INSTANCE_H

19
tests/test_routing_full.c

@ -36,9 +36,9 @@ static int test_routing_table_create_destroy(void) {
struct routing_table* table = routing_table_create();
TEST_ASSERT(table != NULL, "Table creation failed");
TEST_ASSERT(table->entries == NULL, "Entries should be NULL initially");
TEST_ASSERT(table->entries != NULL, "Entries should be allocated initially");
TEST_ASSERT(table->count == 0, "Count should be 0");
TEST_ASSERT(table->capacity == 0, "Capacity should be 0");
TEST_ASSERT(table->capacity == 100, "Capacity should be 100 (INITIAL_ROUTE_CAPACITY)");
TEST_PASS("Table created successfully");
routing_table_destroy(table);
@ -171,17 +171,20 @@ static int test_routing_delete(void) {
TEST_PASS("3 routes inserted");
// Delete middle route
bool result = routing_table_delete(table, routes[1].network, routes[1].prefix_length, 0);
bool result = routing_table_delete(table, routes[1].network, routes[1].prefix_length, routes[1].next_hop_ip);
TEST_ASSERT(result == true, "Delete failed");
TEST_ASSERT(table->count == 2, "Count should be 2");
TEST_PASS("Route deleted");
// Verify deleted route not found
// Verify deleted route not found, but other routes still work
struct route_entry found;
result = routing_table_lookup(table, ip_to_uint32("10.0.2.50"), &found);
TEST_ASSERT(result == true, "Should find other route");
TEST_ASSERT(found.network == routes[0].network || found.network == routes[2].network,
"Should find remaining route");
result = routing_table_lookup(table, ip_to_uint32("10.0.1.50"), &found);
TEST_ASSERT(result == true, "Should find remaining route 1");
TEST_ASSERT(found.network == routes[0].network, "Should find route 1");
result = routing_table_lookup(table, ip_to_uint32("10.0.3.50"), &found);
TEST_ASSERT(result == true, "Should find remaining route 3");
TEST_ASSERT(found.network == routes[2].network, "Should find route 3");
TEST_PASS("Remaining routes functional");
routing_table_destroy(table);

Loading…
Cancel
Save