Browse Source

доработки роутинга

nodeinfo-routing-update
jeka 4 weeks ago
parent
commit
b8820e47b3
  1. 2
      src/etcp_api.h
  2. 171
      src/routing.c
  3. 109
      src/tun_if.c
  4. 4
      src/tun_if.h
  5. 21
      src/tun_windows.c

2
src/etcp_api.h

@ -46,7 +46,7 @@ struct ETCP_BINDINGS {
}; };
/** /**
* @brief Отправить пакет в очередь normalizer * @brief Отправить пакет в очередь normalizer. первый байт кодограммы - cmd (на приёмной стороне bind выберет обработчик по cmd).
* *
* @param conn ETCP соединение * @param conn ETCP соединение
* @param entry Элемент очереди с данными для отправки * @param entry Элемент очереди с данными для отправки

171
src/routing.c

@ -51,11 +51,10 @@ static uint32_t extract_dst_ip(uint8_t* data, size_t len) {
return ntohl(dst_ip); // Convert to host byte order return ntohl(dst_ip); // Convert to host byte order
} }
// Callback for packets from ETCP (via etcp_bind id=0) // entry format: <id 1 byte> <ip_packet ...>
// Format: <id 1 byte> <ip_packet ...> static void route_pkt(struct UTUN_INSTANCE* instance, struct ll_entry* entry) {
static void routing_pkt_from_etcp_cb(struct ETCP_CONN* conn, struct ll_entry* entry) { if (!instance || !entry) {
if (!conn || !entry) { DEBUG_ERROR(DEBUG_CATEGORY_ROUTING, "route_pkt: invalid arguments");
DEBUG_ERROR(DEBUG_CATEGORY_ROUTING, "routing_pkt_from_etcp_cb: invalid arguments");
if (entry) { if (entry) {
queue_entry_free(entry); queue_entry_free(entry);
queue_dgram_free(entry); queue_dgram_free(entry);
@ -63,143 +62,143 @@ static void routing_pkt_from_etcp_cb(struct ETCP_CONN* conn, struct ll_entry* en
return; return;
} }
struct UTUN_INSTANCE* instance = conn->instance; if (!instance->rt) {
if (!instance) { DEBUG_ERROR(DEBUG_CATEGORY_ROUTING, "route_pkt: no route table");
DEBUG_ERROR(DEBUG_CATEGORY_ROUTING, "routing_pkt_from_etcp_cb: connection has no instance");
queue_entry_free(entry); queue_entry_free(entry);
queue_dgram_free(entry); queue_dgram_free(entry);
return; return;
} }
if (!instance->tun) { if (!instance->tun) {
DEBUG_ERROR(DEBUG_CATEGORY_ROUTING, "routing_pkt_from_etcp_cb: no TUN interface"); DEBUG_ERROR(DEBUG_CATEGORY_ROUTING, "route_pkt: no TUN interface");
queue_entry_free(entry); queue_entry_free(entry);
queue_dgram_free(entry); queue_dgram_free(entry);
return; return;
} }
// Check packet data // Check packet data (skip cmd byte)
if (!entry->dgram || entry->len < 2) { if (!entry->dgram || entry->len < 2) {
DEBUG_WARN(DEBUG_CATEGORY_ROUTING, "routing_pkt_from_etcp_cb: packet too small or no data"); DEBUG_WARN(DEBUG_CATEGORY_ROUTING, "route_pkt: packet too small or no data");
queue_entry_free(entry); queue_entry_free(entry);
queue_dgram_free(entry); queue_dgram_free(entry);
return; return;
} }
// Skip ID byte, extract IP packet (offset 1) // Skip cmd byte, extract IP packet (offset 1)
uint8_t* ip_data = entry->dgram + 1; uint8_t* ip_data = entry->dgram + 1;
size_t ip_len = entry->len - 1; size_t ip_len = entry->len - 1;
// Check MTU // Check MTU
if (ip_len > TUN_MAX_PACKET_SIZE) { if (ip_len > TUN_MAX_PACKET_SIZE) {
DEBUG_WARN(DEBUG_CATEGORY_ROUTING, "Packet too large: %zu bytes (max %d)", DEBUG_WARN(DEBUG_CATEGORY_ROUTING, "route_pkt: packet too large: %zu bytes (max %d)",
ip_len, TUN_MAX_PACKET_SIZE); ip_len, TUN_MAX_PACKET_SIZE);
queue_entry_free(entry); queue_entry_free(entry);
queue_dgram_free(entry); queue_dgram_free(entry);
return; return;
} }
// Log destination IP // Extract destination IP
uint32_t dst_ip = extract_dst_ip(ip_data, ip_len); uint32_t dst_ip = extract_dst_ip(ip_data, ip_len);
if (dst_ip != 0) { if (dst_ip == 0) {
struct in_addr addr; DEBUG_WARN(DEBUG_CATEGORY_ROUTING, "route_pkt: failed to extract destination IP, dropping");
addr.s_addr = dst_ip; queue_entry_free(entry);
DEBUG_DEBUG(DEBUG_CATEGORY_ROUTING, "Packet from ETCP to %s", ip_to_str(&addr, AF_INET).str); queue_dgram_free(entry);
return;
} }
// Allocate ETCP_FRAGMENT for TUN input_queue struct in_addr addr;
struct ETCP_FRAGMENT* pkt = (struct ETCP_FRAGMENT*)queue_entry_new_from_pool(instance->tun->pool); addr.s_addr = htonl(dst_ip);
if (!pkt) { DEBUG_DEBUG(DEBUG_CATEGORY_ROUTING, "route_pkt: dst=%s len=%zu", ip_to_str(&addr, AF_INET).str, ip_len);
DEBUG_ERROR(DEBUG_CATEGORY_ROUTING, "Failed to allocate ETCP_FRAGMENT for TUN");
// Lookup route
struct ROUTE_ARRAY* routes = route_table_lookup(instance->rt, dst_ip);
if (!routes || routes->routes == 0) {
DEBUG_INFO(DEBUG_CATEGORY_ROUTING, "route_pkt: no route to %s, dropping", ip_to_str(&addr, AF_INET).str);
queue_entry_free(entry); queue_entry_free(entry);
queue_dgram_free(entry); queue_dgram_free(entry);
return; return;
} }
// Allocate packet data (TUN will free it) // Check route type
uint8_t* packet_data = u_malloc(ip_len); if (routes->entries[0]->type == ROUTE_TYPE_LOCAL) {
if (!packet_data) { // Local route - send to TUN (entry has [cmd=0][IP data], TUN skips cmd byte)
DEBUG_ERROR(DEBUG_CATEGORY_ROUTING, "Failed to allocate packet data"); if (queue_data_put(instance->tun->input_queue, entry, 0) != 0) {
memory_pool_free(instance->tun->pool, pkt); DEBUG_WARN(DEBUG_CATEGORY_ROUTING, "route_pkt: failed to put to TUN input_queue");
queue_entry_free(entry); queue_entry_free(entry);
queue_dgram_free(entry); queue_dgram_free(entry);
return; return;
} }
// Entry sent to TUN, don't free here
DEBUG_DEBUG(DEBUG_CATEGORY_ROUTING, "route_pkt: sent %zu bytes to TUN", ip_len);
return;
}
memcpy(packet_data, ip_data, ip_len); // Learned route - use next_hop
struct ETCP_CONN* conn = routes->entries[0]->next_hop;
pkt->seq = 0; if (!conn) {
pkt->timestamp = 0; DEBUG_WARN(DEBUG_CATEGORY_ROUTING, "route_pkt: route to %s has no next_hop, dropping", ip_to_str(&addr, AF_INET).str);
pkt->ll.dgram = packet_data; queue_entry_free(entry);
pkt->ll.len = ip_len; queue_dgram_free(entry);
return;
}
// Put to TUN input_queue if (!conn->normalizer) {
if (queue_data_put(instance->tun->input_queue, (struct ll_entry*)pkt, 0) != 0) { DEBUG_WARN(DEBUG_CATEGORY_ROUTING, "route_pkt: connection for %s has no normalizer, dropping", ip_to_str(&addr, AF_INET).str);
DEBUG_ERROR(DEBUG_CATEGORY_ROUTING, "Failed to put packet to TUN input_queue"); queue_entry_free(entry);
u_free(packet_data); queue_dgram_free(entry);
memory_pool_free(instance->tun->pool, pkt); return;
} else {
DEBUG_DEBUG(DEBUG_CATEGORY_ROUTING, "Forwarded %zu bytes from ETCP to TUN", ip_len);
} }
// Free original entry from ETCP // Send to ETCP
DEBUG_DEBUG(DEBUG_CATEGORY_ROUTING, "route_pkt: sending %zu bytes to ETCP %s", ip_len, conn->log_name);
if (etcp_send(conn, entry) != 0) {
DEBUG_WARN(DEBUG_CATEGORY_ROUTING, "route_pkt: etcp_send failed for %s", ip_to_str(&addr, AF_INET).str);
queue_entry_free(entry); queue_entry_free(entry);
queue_dgram_free(entry); queue_dgram_free(entry);
return;
}
// Entry sent successfully, don't free here
}
// Callback for packets from ETCP (via etcp_bind id=0)
static void routing_pkt_from_etcp_cb(struct ETCP_CONN* conn, struct ll_entry* pkt) {
if (!conn || !pkt) {
DEBUG_ERROR(DEBUG_CATEGORY_ROUTING, "routing_pkt_from_etcp_cb: invalid arguments");
if (pkt) {
queue_entry_free(pkt);
queue_dgram_free(pkt);
}
return;
}
struct UTUN_INSTANCE* instance = conn->instance;
if (!instance) {
DEBUG_ERROR(DEBUG_CATEGORY_ROUTING, "routing_pkt_from_etcp_cb: connection has no instance");
queue_entry_free(pkt);
queue_dgram_free(pkt);
return;
}
route_pkt(instance, pkt);
} }
// Callback for packets from TUN output queue // Callback for packets from TUN output queue
static void routing_pkt_from_tun_cb(struct ll_queue* q, void* arg) { static void routing_pkt_from_tun_cb(struct ll_queue* q, void* arg) {
(void)q; (void)q;
struct UTUN_INSTANCE* instance = (struct UTUN_INSTANCE*)arg; struct UTUN_INSTANCE* instance = (struct UTUN_INSTANCE*)arg;
if (!instance) { DEBUG_ERROR(DEBUG_CATEGORY_ROUTING, "routing_pkt_from_tun_cb: invalid instance"); return; } if (!instance) {
DEBUG_ERROR(DEBUG_CATEGORY_ROUTING, "routing_pkt_from_tun_cb: invalid instance");
if (!instance->rt) { DEBUG_ERROR(DEBUG_CATEGORY_ROUTING, "routing_pkt_from_tun_cb: no route table"); return; } return;
struct ETCP_FRAGMENT* pkt = (struct ETCP_FRAGMENT*)queue_data_get(instance->tun->output_queue);
if (!pkt) return;
do {
if (!pkt->ll.dgram || pkt->ll.len <= 0) break;
dump_ip_packet("TUN->routing", (const uint8_t*)pkt->ll.dgram, pkt->ll.len);
uint32_t dst_ip = extract_dst_ip(pkt->ll.dgram, pkt->ll.len);
if (dst_ip == 0) { DEBUG_WARN(DEBUG_CATEGORY_ROUTING, "Failed to extract destination IP, dropping packet"); break; }
struct in_addr addr;
addr.s_addr = htonl(dst_ip);
struct ROUTE_ARRAY* routes = route_table_lookup(instance->rt, dst_ip);
if (!routes || routes->routes == 0) { DEBUG_INFO(DEBUG_CATEGORY_ROUTING, "No route to %s, dropping packet", ip_to_str(&addr, AF_INET).str); break; }
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); break; }
if (!conn->normalizer) { DEBUG_WARN(DEBUG_CATEGORY_ROUTING, "Connection for %s has no normalizer, dropping packet", ip_to_str(&addr, AF_INET).str); break; }
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"); break; }
entry->dgram[0] = ETCP_ID_DATA;
memcpy(entry->dgram + 1, pkt->ll.dgram, pkt->ll.len);
entry->len = etcp_data_len;
DEBUG_DEBUG(DEBUG_CATEGORY_ROUTING, "Sending dgram to ETCP %s len=%d", conn->log_name, entry->len);
if (etcp_send(conn, entry) != 0) {
DEBUG_WARN(DEBUG_CATEGORY_ROUTING, "etcp_send failed for %s", ip_to_str(&addr, AF_INET).str);
queue_dgram_free(entry);
queue_entry_free(entry);
} }
} while (0); struct ll_entry* pkt = queue_data_get(instance->tun->output_queue);
if (!pkt) return;
if (pkt->ll.dgram) { // Route packet (unified function handles everything)
u_free(pkt->ll.dgram); route_pkt(instance, pkt);
pkt->ll.dgram = NULL;
}
memory_pool_free(instance->tun->pool, pkt);
// Resume callback for next packet
queue_resume_callback(instance->tun->output_queue); queue_resume_callback(instance->tun->output_queue);
} }

109
src/tun_if.c

@ -36,32 +36,30 @@ static void tun_read_callback(int fd, void* user_arg)
} }
if (nread == 0) return; if (nread == 0) return;
// Allocate packet data // Allocate packet data (+1 for prefix byte)
uint8_t* packet_data = u_malloc(nread); uint8_t* packet_data = u_malloc(nread + 1);
if (!packet_data) { if (!packet_data) {
DEBUG_ERROR(DEBUG_CATEGORY_TUN, "Failed to allocate packet data (size=%zd)", nread); DEBUG_ERROR(DEBUG_CATEGORY_TUN, "Failed to allocate packet data (size=%zd)", nread + 1);
tun->read_errors++; tun->read_errors++;
return; return;
} }
memcpy(packet_data, buffer, nread); packet_data[0] = 0; // Prefix byte
memcpy(packet_data + 1, buffer, nread);
// Allocate ETCP_FRAGMENT from pool struct ll_entry* pkt = queue_entry_new_from_pool(tun->pool);
struct ETCP_FRAGMENT* pkt = (struct ETCP_FRAGMENT*)queue_entry_new_from_pool(tun->pool);
if (!pkt) { if (!pkt) {
DEBUG_ERROR(DEBUG_CATEGORY_TUN, "Failed to allocate ETCP_FRAGMENT from pool"); DEBUG_ERROR(DEBUG_CATEGORY_TUN, "Failed to allocate struct ll_entry from pool");
u_free(packet_data); u_free(packet_data);
tun->read_errors++; tun->read_errors++;
return; return;
} }
// Initialize fragment // Initialize entry
pkt->seq = 0; pkt->dgram = packet_data;
pkt->timestamp = 0; pkt->len = nread + 1;
pkt->ll.dgram = packet_data;
pkt->ll.len = nread;
// Add to output queue (TUN → routing) // Add to output queue (TUN → routing)
if (queue_data_put(tun->output_queue, (struct ll_entry*)pkt, 0) != 0) { if (queue_data_put(tun->output_queue, pkt, 0) != 0) {
DEBUG_ERROR(DEBUG_CATEGORY_TUN, "Failed to add packet to output queue"); DEBUG_ERROR(DEBUG_CATEGORY_TUN, "Failed to add packet to output queue");
u_free(packet_data); u_free(packet_data);
memory_pool_free(tun->pool, pkt); memory_pool_free(tun->pool, pkt);
@ -70,10 +68,10 @@ static void tun_read_callback(int fd, void* user_arg)
} }
// Update statistics // Update statistics
tun->bytes_read += nread; tun->bytes_read += nread + 1;
tun->packets_read++; tun->packets_read++;
DEBUG_DEBUG(DEBUG_CATEGORY_TUN, "Read %zd bytes from TUN %s", nread, tun->ifname); DEBUG_DEBUG(DEBUG_CATEGORY_TUN, "Read %zd bytes from TUN %s", nread + 1, tun->ifname);
dump_ip_packet("TUN->", buffer, nread); dump_ip_packet("TUN->", packet_data + 1, nread);
} }
#endif #endif
@ -84,26 +82,27 @@ static void tun_input_queue_callback(struct ll_queue* q, void* arg)
{ {
(void)q; (void)q;
struct tun_if* tun = (struct tun_if*)arg; struct tun_if* tun = (struct tun_if*)arg;
struct ETCP_FRAGMENT* pkt = queue_data_get(tun->input_queue); struct ll_entry* pkt = queue_data_get(tun->input_queue);
if (!pkt) return; if (!pkt) return;
if (pkt->ll.dgram && pkt->ll.len > 0) { if (pkt->dgram && pkt->len > 1) {
if (pkt->ll.len > TUN_MAX_PACKET_SIZE) { if (pkt->len > TUN_MAX_PACKET_SIZE + 1) {
DEBUG_WARN(DEBUG_CATEGORY_TUN, "Packet too large: %zu bytes", pkt->ll.len); DEBUG_WARN(DEBUG_CATEGORY_TUN, "Packet too large: %zu bytes", pkt->len);
} else { } else {
ssize_t n = tun_platform_write(tun, pkt->ll.dgram, pkt->ll.len); // Skip prefix byte, write from second byte
ssize_t n = tun_platform_write(tun, pkt->dgram + 1, pkt->len - 1);
if (n < 0) { if (n < 0) {
DEBUG_ERROR(DEBUG_CATEGORY_TUN, "tun_platform_write failed"); DEBUG_ERROR(DEBUG_CATEGORY_TUN, "tun_platform_write failed");
tun->write_errors++; tun->write_errors++;
} else { } else {
tun->bytes_written += n; tun->bytes_written += n;
tun->packets_written++; tun->packets_written++;
dump_ip_packet("->TUN", pkt->ll.dgram, pkt->ll.len); dump_ip_packet("->TUN", pkt->dgram + 1, pkt->len - 1);
} }
} }
u_free(pkt->ll.dgram); queue_dgram_free(pkt);
} }
memory_pool_free(tun->pool, pkt); queue_entry_free(pkt);
queue_resume_callback(tun->input_queue); queue_resume_callback(tun->input_queue);
} }
@ -146,7 +145,7 @@ struct tun_if* tun_init(struct UASYNC* ua, struct utun_config* config)
strncpy(tun->ifname, "tun_test", sizeof(tun->ifname)-1); strncpy(tun->ifname, "tun_test", sizeof(tun->ifname)-1);
} }
tun->pool = memory_pool_init(sizeof(struct ETCP_FRAGMENT)); tun->pool = memory_pool_init(sizeof(struct ll_entry));
if (!tun->pool) goto fail; if (!tun->pool) goto fail;
tun->output_queue = queue_new(ua, 0); tun->output_queue = queue_new(ua, 0);
@ -222,16 +221,16 @@ void tun_close(struct tun_if* tun)
uasync_remove_socket(tun->ua, tun->socket_id); uasync_remove_socket(tun->ua, tun->socket_id);
} }
struct ETCP_FRAGMENT* pkt; struct ll_entry* pkt;
while ((pkt = (struct ETCP_FRAGMENT*)queue_data_get(tun->input_queue)) != NULL) { while ((pkt = queue_data_get(tun->input_queue)) != NULL) {
if (pkt->ll.dgram) u_free(pkt->ll.dgram); queue_dgram_free(pkt);
memory_pool_free(tun->pool, pkt); queue_entry_free(pkt);
} }
queue_free(tun->input_queue); queue_free(tun->input_queue);
while ((pkt = (struct ETCP_FRAGMENT*)queue_data_get(tun->output_queue)) != NULL) { while ((pkt = queue_data_get(tun->output_queue)) != NULL) {
if (pkt->ll.dgram) u_free(pkt->ll.dgram); queue_dgram_free(pkt);
memory_pool_free(tun->pool, pkt); queue_entry_free(pkt);
} }
queue_free(tun->output_queue); queue_free(tun->output_queue);
@ -242,17 +241,19 @@ void tun_close(struct tun_if* tun)
ssize_t tun_write(struct tun_if* tun, const uint8_t* buf, size_t len) ssize_t tun_write(struct tun_if* tun, const uint8_t* buf, size_t len)
{ {
if (!tun || !buf || len == 0) return -1; if (!tun || !buf || len <= 1) return -1;
if (tun->test_mode) { if (tun->test_mode) {
return tun_inject_packet(tun, buf, len) == 0 ? (ssize_t)len : -1; // Skip prefix byte for test mode injection
return tun_inject_packet(tun, buf + 1, len - 1) == 0 ? (ssize_t)(len - 1) : -1;
} }
ssize_t n = tun_platform_write(tun, buf, len); // Skip prefix byte, write from second byte
ssize_t n = tun_platform_write(tun, buf + 1, len - 1);
if (n > 0) { if (n > 0) {
tun->bytes_written += n; tun->bytes_written += n;
tun->packets_written++; tun->packets_written++;
dump_ip_packet("->TUN", buf, len); dump_ip_packet("->TUN", buf + 1, len - 1);
} else { } else {
tun->write_errors++; tun->write_errors++;
} }
@ -297,19 +298,19 @@ int tun_inject_packet(struct tun_if* tun, const uint8_t* buf, size_t len)
{ {
if (!tun || !buf || len == 0 || len > TUN_MAX_PACKET_SIZE) return -1; if (!tun || !buf || len == 0 || len > TUN_MAX_PACKET_SIZE) return -1;
uint8_t* data = u_malloc(len); // Allocate with +1 for prefix byte
uint8_t* data = u_malloc(len + 1);
if (!data) { tun->read_errors++; return -1; } if (!data) { tun->read_errors++; return -1; }
memcpy(data, buf, len); data[0] = 0; // Prefix byte
memcpy(data + 1, buf, len);
struct ETCP_FRAGMENT* pkt = (struct ETCP_FRAGMENT*)queue_entry_new_from_pool(tun->pool); struct ll_entry* pkt = queue_entry_new_from_pool(tun->pool);
if (!pkt) { u_free(data); tun->read_errors++; return -1; } if (!pkt) { u_free(data); tun->read_errors++; return -1; }
pkt->seq = 0; pkt->dgram = data;
pkt->timestamp = 0; pkt->len = len + 1;
pkt->ll.dgram = data;
pkt->ll.len = len;
int ret = queue_data_put(tun->output_queue, (struct ll_entry*)pkt, 0); int ret = queue_data_put(tun->output_queue, pkt, 0);
if (ret != 0) { if (ret != 0) {
u_free(data); u_free(data);
@ -318,7 +319,7 @@ int tun_inject_packet(struct tun_if* tun, const uint8_t* buf, size_t len)
return -1; return -1;
} }
tun->bytes_read += len; tun->bytes_read += len + 1;
tun->packets_read++; tun->packets_read++;
return 0; return 0;
} }
@ -327,22 +328,24 @@ ssize_t tun_read_packet(struct tun_if* tun, uint8_t* buf, size_t len)
{ {
if (!tun || !buf || len == 0) return -1; if (!tun || !buf || len == 0) return -1;
struct ETCP_FRAGMENT* pkt = (struct ETCP_FRAGMENT*)queue_data_get(tun->input_queue); struct ll_entry* pkt = queue_data_get(tun->input_queue);
if (!pkt) return 0; if (!pkt) return 0;
if (pkt->ll.len > len) { if (pkt->len > len) {
queue_data_put(tun->input_queue, (struct ll_entry*)pkt, 0); queue_data_put(tun->input_queue, pkt, 0);
return -1; return -1;
} }
memcpy(buf, pkt->ll.dgram, pkt->ll.len); // Add prefix byte at start
ssize_t ret = pkt->ll.len; buf[0] = 0;
memcpy(buf + 1, pkt->dgram, pkt->len);
ssize_t ret = pkt->len + 1;
u_free(pkt->ll.dgram); queue_dgram_free(pkt);
memory_pool_free(tun->pool, pkt); queue_entry_free(pkt);
tun->bytes_written += ret; tun->bytes_written += ret;
tun->packets_written++; tun->packets_written++;
dump_ip_packet("TUN->", buf, ret); dump_ip_packet("TUN->", buf + 1, pkt->len);
return ret; return ret;
} }

4
src/tun_if.h

@ -16,7 +16,7 @@ struct utun_config;
struct ll_queue; struct ll_queue;
struct ll_entry; struct ll_entry;
struct memory_pool; struct memory_pool;
struct ETCP_FRAGMENT; // используется внутри, определён в etcp.h //struct ETCP_FRAGMENT; // используется внутри, определён в etcp.h
// Структура для передачи данных из TUN потока в main thread // Структура для передачи данных из TUN потока в main thread
struct tun_packet_data { struct tun_packet_data {
@ -44,7 +44,7 @@ struct tun_if {
struct UASYNC* ua; struct UASYNC* ua;
void* socket_id; // uasync socket_id (NULL на Windows) void* socket_id; // uasync socket_id (NULL на Windows)
struct memory_pool* pool; // пул для ETCP_FRAGMENT struct memory_pool* pool; // пул для ll_entry
struct ll_queue* output_queue; // TUN → routing (пакеты из интерфейса) struct ll_queue* output_queue; // TUN → routing (пакеты из интерфейса)
struct ll_queue* input_queue; // routing → TUN (пакеты в интерфейс) struct ll_queue* input_queue; // routing → TUN (пакеты в интерфейс)

21
src/tun_windows.c

@ -4,8 +4,8 @@
#include "tun_if.h" #include "tun_if.h"
#include "packet_dump.h" #include "packet_dump.h"
#include "wintun.h" #include "wintun.h"
#include "ll_queue.h" // ← добавлено #include "ll_queue.h"
#include "etcp.h" // ← добавлено (struct ETCP_FRAGMENT) #include "etcp.h"
#include <windows.h> #include <windows.h>
#include <iphlpapi.h> #include <iphlpapi.h>
#include <ws2tcpip.h> #include <ws2tcpip.h>
@ -262,25 +262,26 @@ DWORD WINAPI tun_read_thread_proc(LPVOID arg)
continue; continue;
} }
/* === ОДНО копирование === */ /* === ОДНО копирование (+1 for prefix byte) === */
uint8_t* data = u_malloc(size); uint8_t* data = u_malloc(size + 1);
if (!data) { if (!data) {
WintunReleaseReceivePacket(session, wintun_pkt); WintunReleaseReceivePacket(session, wintun_pkt);
tun->read_errors++; tun->read_errors++;
continue; continue;
} }
memcpy(data, wintun_pkt, size); data[0] = 0; // Prefix byte
memcpy(data + 1, wintun_pkt, size);
WintunReleaseReceivePacket(session, wintun_pkt); /* сразу отдаём кольцо */ WintunReleaseReceivePacket(session, wintun_pkt); /* сразу отдаём кольцо */
struct ETCP_FRAGMENT* pkt = (struct ETCP_FRAGMENT*)queue_entry_new_from_pool(tun->pool); struct ll_entry* pkt = queue_entry_new_from_pool(tun->pool);
if (!pkt) { if (!pkt) {
u_free(data); u_free(data);
tun->read_errors++; tun->read_errors++;
continue; continue;
} }
pkt->ll.dgram = data; pkt->dgram = data;
pkt->ll.len = size; pkt->len = size + 1;
struct tun_packet_data* pd = u_malloc(sizeof(*pd)); struct tun_packet_data* pd = u_malloc(sizeof(*pd));
if (!pd) { if (!pd) {
@ -293,10 +294,10 @@ DWORD WINAPI tun_read_thread_proc(LPVOID arg)
pd->tun = tun; pd->tun = tun;
pd->entry = (struct ll_entry*)pkt; pd->entry = (struct ll_entry*)pkt;
tun->bytes_read += size; tun->bytes_read += size + 1;
tun->packets_read ++; tun->packets_read ++;
dump_ip_packet("TUN_THREAD->", data, size); // теперь data вместо buf dump_ip_packet("TUN_THREAD->", data + 1, size); // теперь data вместо buf
uasync_post(tun->ua, tun_packet_handler, pd); uasync_post(tun->ua, tun_packet_handler, pd);
// DEBUG_DEBUG(DEBUG_CATEGORY_TUN, "POST done"); // DEBUG_DEBUG(DEBUG_CATEGORY_TUN, "POST done");

Loading…
Cancel
Save