From 066a9aa89ecc148f8fe5fea651c41dbfce7fadae Mon Sep 17 00:00:00 2001 From: jeka Date: Fri, 6 Mar 2026 15:55:16 +0300 Subject: [PATCH] +memory check module fix double free @routing --- filelist.txt | 204 +++++++++++++++++++++++------ lib/Makefile.am | 1 + lib/ll_queue.h1 | 174 ------------------------ lib/memory_pool.c | 3 +- lib/timeout_heap.c | 10 +- lib/u_async.c | 6 + net_emulator/net_emulator.c | 7 +- src/Makefile.am | 5 +- src/config_parser.c | 2 +- src/routing.c | 22 +++- tests/Makefile.am | 4 +- tests/test_etcp_two_instances.c | 8 +- tests/test_u_async_comprehensive.c | 1 + 13 files changed, 218 insertions(+), 229 deletions(-) delete mode 100644 lib/ll_queue.h1 diff --git a/filelist.txt b/filelist.txt index 90b499f..6305f11 100644 --- a/filelist.txt +++ b/filelist.txt @@ -1,40 +1,164 @@ -lib/debug_config.c -lib/debug_config.h -lib/ll_queue.c -lib/ll_queue.h -lib/memory_pool.c -lib/memory_pool.h -lib/sha256.c -lib/sha256.h -lib/test_size.c -lib/timeout_heap.c -lib/timeout_heap.h -lib/u_async.c -lib/u_async.h -src/config_parser.c -src/config_parser.h -src/config_updater.c -src/config_updater.h -src/crc32.c -src/crc32.h -src/etcp.c -src/etcp.h -src/etcp_connections.c -src/etcp_connections.h -src/etcp_loadbalancer.c -src/etcp_loadbalancer.h -src/packet_dump.h -src/packet_dump.c -src/pkt_normalizer.c -src/pkt_normalizer.h -src/route_lib.c -src/route_lib.h -src/routing.c -src/routing.h -src/secure_channel.c -src/secure_channel.h -src/tun_if.c -src/tun_if.h -src/utun.c -src/utun_instance.c -src/utun_instance.h +config.h +lib\debug_config.c +lib\debug_config.h +lib\ll_queue.c +lib\ll_queue.h +lib\mem.c +lib\mem.h +lib\memory_pool.c +lib\memory_pool.h +lib\platform_compat.c +lib\platform_compat.h +lib\sha256.c +lib\sha256.h +lib\socket_compat.c +lib\socket_compat.h +lib\timeout_heap.c +lib\timeout_heap.h +lib\u_async.c +lib\u_async.h +lib\wintun.h +net_emulator\net_emulator.c +net_emulator\net_emulator.h +src\config_parser.c +src\config_parser.h +src\config_updater.c +src\config_updater.h +src\control_server.c +src\control_server.h +src\crc32.c +src\crc32.h +src\dummynet.c +src\dummynet.h +src\etcp.c +src\etcp.h +src\etcp_api.c +src\etcp_api.h +src\etcp_connections.c +src\etcp_connections.h +src\etcp_debug.c +src\etcp_debug.h +src\etcp_loadbalancer.c +src\etcp_loadbalancer.h +src\packet_dump.c +src\packet_dump.h +src\pkt_normalizer.c +src\pkt_normalizer.h +src\route_bgp.c +src\route_bgp.h +src\route_lib.c +src\route_lib.h +src\routing.c +src\routing.h +src\secure_channel.c +src\secure_channel.h +src\tun_if.c +src\tun_if.h +src\tun_linux.c +src\tun_route.c +src\tun_route.h +src\tun_windows.c +src\utun.c +src\utun_instance.c +src\utun_instance.h +tests\bench_timeout_heap.c +tests\bench_uasync_timeouts.c +tests\debug_full_test.c +tests\debug_performance.c +tests\debug_simple.c +tests\detailed_test.c +tests\simple_test.c +tests\test_bgp_route_exchange.c +tests\test_config_debug.c +tests\test_control_server.c +tests\test_control_simple.c +tests\test_crash_debug.c +tests\test_crypto.c +tests\test_debug_categories.c +tests\test_dummynet.c +tests\test_ecc_encrypt.c +tests\test_etcp_100_packets.c +tests\test_etcp_api.c +tests\test_etcp_crypto.c +tests\test_etcp_dummynet.c +tests\test_etcp_exit.c +tests\test_etcp_link_id.c +tests\test_etcp_minimal.c +tests\test_etcp_simple_traffic.c +tests\test_etcp_two_instances.c +tests\test_intensive_memory_pool.c +tests\test_intensive_memory_pool_new.c +tests\test_ll_queue.c +tests\test_memory_pool_and_config.c +tests\test_minimal.c +tests\test_minimal_exit.c +tests\test_offset.c +tests\test_packet_dump.c +tests\test_pkt_normalizer_etcp.c +tests\test_pkt_normalizer_standalone.c +tests\test_poll_exact.c +tests\test_poll_multi.c +tests\test_route_lib.c +tests\test_routing_mesh.c +tests\test_simple.c +tests\test_simple2.c +tests\test_socket.c +tests\test_utils.h +tests\test_u_async_comprehensive.c +tests\test_u_async_performance.c +tests\track_test.c +tests\working_crypto_test.c +tinycrypt\lib\include\tinycrypt\aes.h +tinycrypt\lib\include\tinycrypt\cbc_mode.h +tinycrypt\lib\include\tinycrypt\ccm_mode.h +tinycrypt\lib\include\tinycrypt\cmac_mode.h +tinycrypt\lib\include\tinycrypt\constants.h +tinycrypt\lib\include\tinycrypt\ctr_mode.h +tinycrypt\lib\include\tinycrypt\ctr_prng.h +tinycrypt\lib\include\tinycrypt\ecc.h +tinycrypt\lib\include\tinycrypt\ecc_dh.h +tinycrypt\lib\include\tinycrypt\ecc_dsa.h +tinycrypt\lib\include\tinycrypt\ecc_platform_specific.h +tinycrypt\lib\include\tinycrypt\hmac.h +tinycrypt\lib\include\tinycrypt\hmac_prng.h +tinycrypt\lib\include\tinycrypt\sha256.h +tinycrypt\lib\include\tinycrypt\utils.h +tinycrypt\lib\source\aes_decrypt.c +tinycrypt\lib\source\aes_encrypt.c +tinycrypt\lib\source\cbc_mode.c +tinycrypt\lib\source\ccm_mode.c +tinycrypt\lib\source\cmac_mode.c +tinycrypt\lib\source\ctr_mode.c +tinycrypt\lib\source\ctr_prng.c +tinycrypt\lib\source\ecc.c +tinycrypt\lib\source\ecc_dh.c +tinycrypt\lib\source\ecc_dsa.c +tinycrypt\lib\source\ecc_platform_specific.c +tinycrypt\lib\source\hmac.c +tinycrypt\lib\source\hmac_prng.c +tinycrypt\lib\source\sha256.c +tinycrypt\lib\source\utils.c +tinycrypt\tests\test_aes.c +tinycrypt\tests\test_cbc_mode.c +tinycrypt\tests\test_ccm_mode.c +tinycrypt\tests\test_client_server.c +tinycrypt\tests\test_cmac_mode.c +tinycrypt\tests\test_ctr_mode.c +tinycrypt\tests\test_ctr_prng.c +tinycrypt\tests\test_ecc_dh.c +tinycrypt\tests\test_ecc_dsa.c +tinycrypt\tests\test_ecc_utils.c +tinycrypt\tests\test_hmac.c +tinycrypt\tests\test_hmac_prng.c +tinycrypt\tests\test_sha256.c +tinycrypt\tests\include\test_ecc_utils.h +tinycrypt\tests\include\test_utils.h +tools\bping\bping.c +tools\etcpmon\etcpmon_client.c +tools\etcpmon\etcpmon_client.h +tools\etcpmon\etcpmon_graph.c +tools\etcpmon\etcpmon_graph.h +tools\etcpmon\etcpmon_gui.c +tools\etcpmon\etcpmon_gui.h +tools\etcpmon\etcpmon_main.c +tools\etcpmon\etcpmon_protocol.h diff --git a/lib/Makefile.am b/lib/Makefile.am index 70e180c..bd7cadc 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -23,6 +23,7 @@ libuasync_a_SOURCES = \ libuasync_a_CFLAGS = \ -D_ISOC99_SOURCE \ -DDEBUG_OUTPUT_STDERR \ + -g \ -I$(top_srcdir)/src \ -I$(top_srcdir)/lib diff --git a/lib/ll_queue.h1 b/lib/ll_queue.h1 deleted file mode 100644 index beac4df..0000000 --- a/lib/ll_queue.h1 +++ /dev/null @@ -1,174 +0,0 @@ -// ll_queue.h - Упрощенная архитектура: разделение создания элементов и работы с очередью -#ifndef LL_QUEUE_H -#define LL_QUEUE_H - -#include // для size_t -#include // для uint64_t -#include "memory_pool.h" // для struct memory_pool - -// Предварительные объявления -struct ll_queue; -struct ll_entry; -struct queue_waiter; -struct memory_pool; -struct UASYNC; - -// Автозабор элемента из очереди. вызывается когда в очереди что-то есть и коллбэк не занят обработкой. -// Параметры: указатель на очередь, указатель на структуру элемента (struct ll_entry*), пользовательский аргумент -// Когда коллбэк закончит обрабатывать элемент он должен вызвать queue_resume_callback - сообщить о готовности получить следующий элемент (приём очередным вызовом коллбэка в следующем цикле mainloop). -typedef void (*queue_callback_fn)(struct ll_queue* q, void* arg); - -// Структура элемента - переменный размер, данные расположены сразу после структуры -struct ll_entry { - struct ll_entry* next; // Указатель на следующий элемент в очереди - struct ll_entry* prev; // Указатель на предыдущий элемент в очереди - uint16_t size; // Размер доступной памяти после блока ll_entry - т.е. data[size]. используется для добавления доп. параметров - - uint16_t len; // размер пакета (dgram) - uint16_t memlen; // размер выделенной памяти (dgram) - uint16_t int_len; // размер (private, not use!) - uint8_t* dgram; // данные пакета - void (*dgram_free_fn)(uint8_t* data, void* arg); // функция освобождения блока - struct memory_pool* dgram_pool; // Пул, из которого выделен этот элемент (NULL, если выделен через malloc) - - uint32_t id; // Идентификатор для хеш-поиска - struct ll_entry* hash_next; // Следующий в хеш-цепочке - struct memory_pool* pool; // Пул, из которого выделен этот элемент (NULL, если выделен через malloc) - uint8_t data[0]; -}; - -// Ожидающий добавления элементов в очередь (пока очередь не освободться до нужного размера чтобы не забивать) -struct queue_waiter { - int max_packets; // Максимальное количество пакетов - size_t max_bytes; // Максимальное количество байт (0 = не проверять байты) - void (*callback)(struct ll_queue* q, void* arg); // Коллбэк для вызова - void* callback_arg; // Аргумент коллбэка -}; - -typedef void (*queue_threshold_callback_fn)(struct ll_queue* q, void* arg); - -// Структура очереди -struct ll_queue { - struct ll_entry* head; // Первый элемент (извлекается отсюда) - struct ll_entry* tail; // Последний элемент (добавляется сюда) - int count; // Текущее количество элементов - size_t total_bytes; // Общий размер данных всех элементов (байт) - int size_limit; // Максимальное количество (-1 = без ограничения) - - queue_callback_fn callback; // Функция коллбэка - void* callback_arg; // Пользовательский аргумент для коллбэка - int callback_suspended; - - void* resume_timeout_id; // ID таймаута uasync для отложенного возобновления - struct UASYNC* ua; // Экземпляр uasync для таймеров - - struct queue_waiter waiter; // Встроенный одиночный waiter - - // Хеш-таблица для быстрого поиска по ID - struct ll_entry** hash_table; - size_t hash_size; -}; - -// ==================== Управление очередью ==================== - -// Создать новую пустую очередь -// ua - экземпляр uasync для таймеров (обязательный параметр) -// hash_size - размер хеш-таблицы для быстрого поиска (0 = без хеш-таблицы) -// Возвращает: указатель на очередь или NULL при ошибке выделения памяти -struct ll_queue* queue_new(struct UASYNC* ua, size_t hash_size); - -// Освободить очередь и все её элементы -// ВАЖНО: освобождает только структуру очереди, элементы в очереди НЕ освобождаются! -// Элементы должны быть предварительно извлечены через queue_data_get() и освобождены через queue_data_free() -void queue_free(struct ll_queue* q); - -// Установить максимальное количество элементов в очереди -// При превышении лимита новый элемент автоматически освобождается -void queue_set_size_limit(struct ll_queue* q, int lim); - -// ==================== Асинхронное ожидание передачи ==================== - -// Зарегистрировать одноразовый коллбэк, который будет вызван когда очередь будет иметь -// не более max_packets пакетов и не более max_bytes байт (если max_bytes != 0). -// Если условие уже выполнено, коллбэк вызывается немедленно. -// Возвращает указатель на waiter для возможной отмены через queue_cancel_wait -struct queue_waiter* queue_wait_threshold(struct ll_queue* q, int max_packets, size_t max_bytes, - queue_threshold_callback_fn callback, void* arg); - -// Отменить ожидание (удалить waiter из списка) -void queue_cancel_wait(struct ll_queue* q, struct queue_waiter* waiter); - -// Получить общий размер данных в очереди (байт) -static inline size_t queue_total_bytes(struct ll_queue* q) { - if (!q) return 0; - return q->total_bytes; -} - -// ==================== Асинхронное ожидание приёма ==================== - -// Установить функцию и аргумент коллбэка для автозабора из очереди -// Коллбэк вызывается когда в очереди есть элемент и разрешен коллбэк -// обработчик должен обработать этот пакет (может использовать асинхронное ожидание). Когда будет готов к приёму следующего - должен вызвать resume_callback. обработка строго по одному пакету. -void queue_set_callback(struct ll_queue* q, queue_callback_fn cbk_fn, void* arg); - -// обрабатывается строго одина пакет за вызов -// Возобновить коллбэки после обработки элемента переданного в коллбэке (тянуть дополнительные элементы из очереди не предусмотернные api нельзя). -// эта функция должна вызываться всегда после того как cbk_fn обработала пакет (можно с ожиданием через async), иначе очередь застрянет. -// Если в очереди остались элементы, запланирует вызов коллбэка через uasync_set_timeout(0) -// Это предотвращает накопление рекурсии в стеке вызовов -void queue_resume_callback(struct ll_queue* q); - -// ==================== Управление элементами ==================== - -// выделить ll_entry и память под кодограмму -struct ll_entry* ll_alloc_lldgram(uint16_t len); - -// Создать новый элемент с областью данных указанного размера -// Память выделяется одним блоком: [struct ll_entry][область данных data_size байт] -// Возвращает: указатель на структуру элемента (struct ll_entry*) или NULL при ошибке выделения памяти -struct ll_entry* queue_entry_new(size_t data_size); - -// Создать новый элемент из пула (размер был определен при создании пула) -// Возвращает: указатель на структуру элемента (struct ll_entry*) или NULL при ошибке выделения памяти -struct ll_entry* queue_entry_new_from_pool(struct memory_pool* pool); - -// Освободить только entry (не влияет на очереди, dgram не освобождает) -void queue_entry_free(struct ll_entry* entry); - -// Освободить только entry->dgram (не влияет на очереди) -void queue_dgram_free(struct ll_entry* entry); -//void queue_data_free(void* data); - -// ==================== Операции с очередью ==================== - -// Добавить элемент в конец очереди (FIFO) -// Если очередь была пустой и коллбэки разрешены - вызывает коллбэк -// Возвращает: 0 при успехе, -1 если превышен лимит размера (элемент освобожден) -int queue_data_put(struct ll_queue* q, struct ll_entry* entry, uint32_t id); - -// Добавить элемент в начало очереди (LIFO, высокий приоритет) -// Если очередь была пустой и коллбэки разрешены - вызывает коллбэк -// Возвращает: 0 при успехе, -1 если превышен лимит размера (элемент освобожден) -int queue_data_put_first(struct ll_queue* q, struct ll_entry* entry, uint32_t id); - -// Извлечь элемент из начала очереди -// При извлечении приостанавливает коллбэки (callback_suspended = 1) чтобы предотвратить рекурсию -// Возвращает: указатель на структуру элемента (struct ll_entry*) или NULL если очередь пуста -// ПРИМЕЧАНИЕ: не освобождает память элемента -struct ll_entry* queue_data_get(struct ll_queue* q); - -// Получить текущее количество элементов в очереди -int queue_entry_count(struct ll_queue* q); - -// ==================== Поиск и удаление по ID ==================== - -// Найти элемент по ID -// Возвращает: указатель на структуру элемента (struct ll_entry*) или NULL если не найден -struct ll_entry* queue_find_data_by_id(struct ll_queue* q, uint32_t id); - -// Удалить элемент из очереди по указателю на структуру элемента -// Возвращает: 0 при успехе, -1 если элемент не найден -// ПРИМЕЧАНИЕ: НЕ изменяет ref_count элемента, просто удаляет из очереди -int queue_remove_data(struct ll_queue* q, struct ll_entry* entry); - -#endif // LL_QUEUE_H diff --git a/lib/memory_pool.c b/lib/memory_pool.c index f0e6ed5..50529cb 100644 --- a/lib/memory_pool.c +++ b/lib/memory_pool.c @@ -1,7 +1,8 @@ // memory_pool.c -#include "memory_pool.h" #include #include +#include +#include "memory_pool.h" #include "mem.h" // Инициализировать пул памяти diff --git a/lib/timeout_heap.c b/lib/timeout_heap.c index 6aaf24f..b46b2db 100644 --- a/lib/timeout_heap.c +++ b/lib/timeout_heap.c @@ -4,6 +4,7 @@ #include "debug_config.h" #include #include // For potential error printing, optional +#include "mem.h" // Helper macros for 1-based indices #define PARENT(i) ((i) / 2) @@ -11,13 +12,20 @@ #define RIGHT_CHILD(i) (2 * (i) + 1) TimeoutHeap *timeout_heap_create(size_t initial_capacity) { + DEBUG_INFO(DEBUG_CATEGORY_ETCP, "Creating TH1..."); TimeoutHeap *h = u_malloc(sizeof(TimeoutHeap)); - if (!h) return NULL; + if (!h) { + DEBUG_ERROR(DEBUG_CATEGORY_ETCP, "TH0 error..."); + return NULL; + } + DEBUG_INFO(DEBUG_CATEGORY_ETCP, "Creating TH2..."); h->heap = u_malloc(sizeof(TimeoutEntry) * initial_capacity); if (!h->heap) { + DEBUG_ERROR(DEBUG_CATEGORY_ETCP, "TH1 error..."); u_free(h); return NULL; } + DEBUG_INFO(DEBUG_CATEGORY_ETCP, "Creating TH3..."); h->size = 0; h->capacity = initial_capacity; h->freed_count = 0; diff --git a/lib/u_async.c b/lib/u_async.c index ae08e92..ab3d20f 100644 --- a/lib/u_async.c +++ b/lib/u_async.c @@ -1112,7 +1112,9 @@ struct UASYNC* uasync_create(void) { ua->wakeup_initialized = 0; ua->posted_tasks_head = NULL; + DEBUG_INFO(DEBUG_CATEGORY_ETCP, "Creating SA..."); ua->sockets = socket_array_create(16); + DEBUG_INFO(DEBUG_CATEGORY_ETCP, "Creating SA1..."); if (!ua->sockets) { if (ua->wakeup_initialized) { #ifdef _WIN32 @@ -1146,6 +1148,7 @@ struct UASYNC* uasync_create(void) { // Set callback to u_free timeout nodes and update counters timeout_heap_set_free_callback(ua->timeout_heap, ua, timeout_node_free_callback); + DEBUG_INFO(DEBUG_CATEGORY_ETCP, "Creating TH1..."); // Initialize epoll on Linux ua->epoll_fd = -1; ua->use_epoll = 0; @@ -1168,6 +1171,8 @@ struct UASYNC* uasync_create(void) { } #endif + DEBUG_INFO(DEBUG_CATEGORY_ETCP, "Creating TH2..."); + #ifdef _WIN32 // Windows: self-connected UDP socket for wakeup SOCKET r = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); @@ -1223,6 +1228,7 @@ struct UASYNC* uasync_create(void) { pthread_mutex_init(&ua->posted_lock, NULL); #endif + DEBUG_INFO(DEBUG_CATEGORY_ETCP, "Creating TH3..."); return ua; } diff --git a/net_emulator/net_emulator.c b/net_emulator/net_emulator.c index 949cee8..4a3de1a 100644 --- a/net_emulator/net_emulator.c +++ b/net_emulator/net_emulator.c @@ -2,6 +2,7 @@ #define _POSIX_C_SOURCE 200809L #include "net_emulator.h" #include "u_async.h" +#include "mem.h" #include #include #include @@ -347,7 +348,7 @@ static void socket_callback(int fd, void *user_arg) { g_packet_counter, delay_ms, selected_rule->probability_percent); // Allocate packet buffer for delayed sending - delayed_packet_t *packet = malloc(sizeof(delayed_packet_t)); + delayed_packet_t *packet = u_malloc(sizeof(delayed_packet_t)); if (!packet) { fprintf(stderr, "Failed to allocate packet buffer\n"); return; @@ -372,7 +373,7 @@ static void socket_callback(int fd, void *user_arg) { // Convert delay to u_async timebase (0.1ms) int delay_tb = delay_ms * 10; if (!ep->emulator || !ep->emulator->ua) { - free(packet); + u_free(packet); return; } uasync_set_timeout(ep->emulator->ua, delay_tb, packet, (timeout_callback_t)send_delayed_packet); @@ -393,7 +394,7 @@ static void send_delayed_packet(void *user_arg) { nsent, inet_ntoa(packet->to_addr.sin_addr), ntohs(packet->to_addr.sin_port)); } - free(packet); + u_free(packet); } // Initialize network emulator diff --git a/src/Makefile.am b/src/Makefile.am index 1568bf2..4c4db74 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -25,7 +25,7 @@ utun_CORE_SOURCES = \ # Platform-specific TUN sources if OS_WINDOWS utun_TUN_SOURCES = tun_windows.c -utun_TUN_LIBS = -liphlpapi -lws2_32 -ladvapi32 -lbcrypt +utun_TUN_LIBS = -liphlpapi -lws2_32 -ladvapi32 -lbcrypt -ldbghelp else utun_TUN_SOURCES = tun_linux.c utun_TUN_LIBS = @@ -59,6 +59,7 @@ utun_CORE_CFLAGS = \ -I$(top_srcdir)/lib \ -I$(top_srcdir)/tinycrypt/lib/include \ -I$(top_srcdir)/tinycrypt/lib/source \ + -g \ $(DEBUG_FLAGS) utun_CFLAGS = $(utun_CORE_CFLAGS) @@ -92,7 +93,7 @@ TINYCRYPT_OBJS = \ utun-utils.o # Rules to build TinyCrypt objects (for tests) -TINYCRYPT_CFLAGS = -I$(top_srcdir)/tinycrypt/lib/include -I$(top_srcdir)/tinycrypt/lib/source +TINYCRYPT_CFLAGS = -g -I$(top_srcdir)/tinycrypt/lib/include -I$(top_srcdir)/tinycrypt/lib/source utun-aes_encrypt.o: $(TINYCRYPT_SRCDIR)/aes_encrypt.c $(AM_V_CC)$(COMPILE) $(TINYCRYPT_CFLAGS) -c -o $@ $< diff --git a/src/config_parser.c b/src/config_parser.c index ea43f49..ec61166 100644 --- a/src/config_parser.c +++ b/src/config_parser.c @@ -38,7 +38,7 @@ static uint32_t parse_debug_categories(const char *value); /* Parse debug categories from comma-separated string */ static uint32_t parse_debug_categories(const char *value) { uint32_t categories = 0; - char *value_copy = strdup(value); + char *value_copy = u_strdup(value); if (!value_copy) return DEBUG_CATEGORY_ALL; // Default to all on error char *token = strtok(value_copy, ","); diff --git a/src/routing.c b/src/routing.c index 7ac4b07..35798c7 100644 --- a/src/routing.c +++ b/src/routing.c @@ -164,6 +164,8 @@ static void routing_pkt_from_tun_cb(struct ll_queue* q, void* arg) { struct ETCP_FRAGMENT* pkt = (struct ETCP_FRAGMENT*)queue_data_get(instance->tun->output_queue); if (!pkt) return; + bool pkt_freed = false; + if (pkt->ll.dgram && pkt->ll.len > 0) { dump_ip_packet("TUN->routing", (const uint8_t*)pkt->ll.dgram, pkt->ll.len); @@ -171,7 +173,9 @@ static void routing_pkt_from_tun_cb(struct ll_queue* q, void* arg) { if (dst_ip == 0) { DEBUG_WARN(DEBUG_CATEGORY_ROUTING, "Failed to extract destination IP, dropping packet"); u_free(pkt->ll.dgram); + pkt->ll.dgram = NULL; memory_pool_free(instance->tun->pool, pkt); + pkt_freed = true; } else { struct in_addr addr; addr.s_addr = htonl(dst_ip); @@ -180,24 +184,32 @@ static void routing_pkt_from_tun_cb(struct ll_queue* q, void* arg) { if (!routes || routes->routes == 0) { DEBUG_INFO(DEBUG_CATEGORY_ROUTING, "No route to %s, dropping packet", ip_to_str(&addr, AF_INET).str); u_free(pkt->ll.dgram); + pkt->ll.dgram = NULL; memory_pool_free(instance->tun->pool, pkt); + pkt_freed = true; } else { struct ETCP_CONN* conn = routes->entries[0]->next_hop; if (!conn) { DEBUG_WARN(DEBUG_CATEGORY_ROUTING, "Route to %s has no next_hop, dropping packet", ip_to_str(&addr, AF_INET).str); u_free(pkt->ll.dgram); + pkt->ll.dgram = NULL; memory_pool_free(instance->tun->pool, pkt); + pkt_freed = true; } else if (!conn->normalizer) { DEBUG_WARN(DEBUG_CATEGORY_ROUTING, "Connection for %s has no normalizer, dropping packet", ip_to_str(&addr, AF_INET).str); u_free(pkt->ll.dgram); + pkt->ll.dgram = NULL; memory_pool_free(instance->tun->pool, pkt); + pkt_freed = true; } else { size_t etcp_data_len = 1 + pkt->ll.len; struct ll_entry* entry = ll_alloc_lldgram(etcp_data_len); if (!entry) { DEBUG_ERROR(DEBUG_CATEGORY_ROUTING, "Failed to allocate entry for ETCP send"); u_free(pkt->ll.dgram); + pkt->ll.dgram = NULL; memory_pool_free(instance->tun->pool, pkt); + pkt_freed = true; } else { entry->dgram[0] = ETCP_ID_DATA; memcpy(entry->dgram + 1, pkt->ll.dgram, pkt->ll.len); @@ -210,19 +222,23 @@ static void routing_pkt_from_tun_cb(struct ll_queue* q, void* arg) { queue_dgram_free(entry); } - u_free(pkt->ll.dgram); - memory_pool_free(instance->tun->pool, pkt); + goto cleanup; } } } } } else { + memory_pool_free(instance->tun->pool, pkt); + pkt_freed = true; + } + +cleanup: + if (!pkt_freed) { if (pkt->ll.dgram) { u_free(pkt->ll.dgram); } memory_pool_free(instance->tun->pool, pkt); } - queue_resume_callback(instance->tun->output_queue); } diff --git a/tests/Makefile.am b/tests/Makefile.am index ab8c3d8..7b24087 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -27,7 +27,7 @@ check_PROGRAMS = \ bench_uasync_timeouts # Basic includes -AM_CFLAGS = -I$(top_srcdir)/src -I$(top_srcdir)/lib -I$(top_srcdir)/tinycrypt/lib/include -I$(top_srcdir)/tinycrypt/lib/source +AM_CFLAGS = -g -I$(top_srcdir)/src -I$(top_srcdir)/lib -I$(top_srcdir)/tinycrypt/lib/include -I$(top_srcdir)/tinycrypt/lib/source # TinyCrypt source files TINYCRYPT_SRCDIR = $(top_srcdir)/tinycrypt/lib/source @@ -81,7 +81,7 @@ ETCP_FULL_OBJS = \ # Windows-specific libraries (advapi32 for CryptGenRandom, ws2_32 for sockets) if OS_WINDOWS -WIN_LIBS = -lws2_32 -liphlpapi -ladvapi32 -lbcrypt +WIN_LIBS = -lws2_32 -liphlpapi -ladvapi32 -lbcrypt -ldbghelp else WIN_LIBS = endif diff --git a/tests/test_etcp_two_instances.c b/tests/test_etcp_two_instances.c index 4f742ca..0d3df13 100644 --- a/tests/test_etcp_two_instances.c +++ b/tests/test_etcp_two_instances.c @@ -263,12 +263,16 @@ int main() { // Create server instance DEBUG_INFO(DEBUG_CATEGORY_ETCP, "Creating server instance..."); ua = uasync_create(); + DEBUG_INFO(DEBUG_CATEGORY_ETCP, "Creating server instance ok..."); + server_instance = utun_instance_create(ua, server_config_path); if (!server_instance) { DEBUG_ERROR(DEBUG_CATEGORY_ETCP, "Failed to create server instance"); return 1; } - + + DEBUG_INFO(DEBUG_CATEGORY_ETCP, "UTUN instance ok..."); + // Initialize ETCP connections regardless of TUN state if (init_connections(server_instance) < 0) { DEBUG_ERROR(DEBUG_CATEGORY_ETCP, "Failed to initialize server connections"); @@ -321,7 +325,7 @@ int main() { } } } - + // Start monitoring DEBUG_INFO(DEBUG_CATEGORY_ETCP, "Starting connection monitoring...\n"); monitor_timeout_id = uasync_set_timeout(ua, 100, NULL, monitor_connections); diff --git a/tests/test_u_async_comprehensive.c b/tests/test_u_async_comprehensive.c index ae4a3b3..15b37ce 100644 --- a/tests/test_u_async_comprehensive.c +++ b/tests/test_u_async_comprehensive.c @@ -12,6 +12,7 @@ #include "u_async.h" #include "timeout_heap.h" #include "debug_config.h" +#include "../lib/mem.h" /* Test statistics */ static struct {