Browse Source

migrate NAT and DATA to etcp_router, fix warnings and destroy order

congestion
Evgeny 5 months ago
parent
commit
a0e5446790
  1. 2
      lib/socket_compat.c
  2. 2
      lib/socket_compat.h
  3. 75
      src/nat_transport.c
  4. 1
      src/nat_transport.h
  5. 93
      src/routing.c
  6. 9
      src/routing.h
  7. 2
      src/tcp_proxy.c
  8. 24
      src/utun_instance.c
  9. 2
      tests/Makefile.am
  10. 47
      tests/test_nat_transport.c
  11. 5
      tests/test_pkt_normalizer_standalone.c

2
lib/socket_compat.c

@ -211,7 +211,7 @@ int socket_set_mark(socket_t sock, int mark) {
}
ssize_t socket_sendto(socket_t sock, const void* buf, size_t len,
struct sockaddr* dest, socklen_t dest_len) {
const struct sockaddr* dest, socklen_t dest_len) {
#ifdef _WIN32
return sendto(sock, (const char*)buf, (int)len, 0, dest, dest_len);
#else

2
lib/socket_compat.h

@ -63,7 +63,7 @@ int socket_set_mark(socket_t sock, int mark);
// I/O operations
ssize_t socket_sendto(socket_t sock, const void* buf, size_t len,
struct sockaddr* dest, socklen_t dest_len);
const struct sockaddr* dest, socklen_t dest_len);
ssize_t socket_recvfrom(socket_t sock, void* buf, size_t len,
struct sockaddr* src, socklen_t* src_len);

75
src/nat_transport.c

@ -5,13 +5,13 @@
#include "config_parser.h"
#include "tun_if.h"
#include "etcp_api.h"
#include "route_bgp.h"
#include "etcp_router.h"
#include "../lib/debug_config.h"
#include "../lib/mem.h"
#include "../lib/ll_queue.h"
#include <string.h>
#define NAT_HDR_SIZE 17 // cmd(1) + src_node_id(8) + dst_node_id(8)
#define NAT_SVC_HDR_SIZE 9 // svc_id(1) + src_node_id(8)
static ip_str_t ip_host_to_str(uint32_t ip_host) {
struct in_addr a; a.s_addr = htonl(ip_host);
@ -20,37 +20,24 @@ static ip_str_t ip_host_to_str(uint32_t ip_host) {
// ==================== Callbacks ====================
// CLIENT: NAT TUN output → encapsulate in ETCP_ID_NAT → send to provider
// CLIENT: NAT TUN output → encapsulate in ETCP_ID_NAT → send to provider via etcp_router
static void nat_transport_client_tun_out_cb(struct ll_queue* q, void* arg) {
struct UTUN_INSTANCE* inst = (struct UTUN_INSTANCE*)arg;
if (!inst) { queue_resume_callback(q); return; }
struct nat_transport_ctx* tr = &inst->nat_tr;
struct eim_nat_ctx* ctx = &inst->nat;
struct ll_entry* pkt = queue_data_get(q);
if (!pkt) { queue_resume_callback(q); return; }
if (!pkt->dgram || pkt->len < 2) { queue_dgram_free(pkt); queue_entry_free(pkt); queue_resume_callback(q); return; }
if (!tr->nat_via_conn) {
tr->nat_via_conn = route_bgp_find_conn_for_node(inst->bgp, tr->nat_via_node_id);
if (!tr->nat_via_conn) {
DEBUG_WARN(DEBUG_CATEGORY_NAT, "No connection to NAT provider %016llx, dropping",
(unsigned long long)tr->nat_via_node_id);
queue_dgram_free(pkt); queue_entry_free(pkt); queue_resume_callback(q);
return;
}
}
size_t ip_len = pkt->len - 1;
size_t total_len = NAT_HDR_SIZE + ip_len;
size_t total_len = NAT_SVC_HDR_SIZE + ip_len;
uint8_t* new_dgram = u_malloc(total_len);
if (!new_dgram) { queue_dgram_free(pkt); queue_entry_free(pkt); queue_resume_callback(q); return; }
new_dgram[0] = ETCP_ID_NAT;
memcpy(new_dgram + 1, &tr->self_node_id, 8);
memcpy(new_dgram + 9, &tr->nat_via_node_id, 8);
memcpy(new_dgram + 17, pkt->dgram + 1, ip_len);
memcpy(new_dgram + 1, &tr->self_node_id, 8);
memcpy(new_dgram + 9, pkt->dgram + 1, ip_len);
struct ll_entry* new_entry = queue_entry_new(0);
if (!new_entry) { u_free(new_dgram); queue_dgram_free(pkt); queue_entry_free(pkt); queue_resume_callback(q); return; }
@ -60,18 +47,18 @@ static void nat_transport_client_tun_out_cb(struct ll_queue* q, void* arg) {
queue_dgram_free(pkt); queue_entry_free(pkt);
queue_resume_callback(q);
int ret = etcp_send(tr->nat_via_conn, new_entry);
int ret = etcp_route_send(inst, tr->nat_via_node_id, new_entry);
if (ret != 0) {
DEBUG_WARN(DEBUG_CATEGORY_NAT, "etcp_send to provider failed");
DEBUG_WARN(DEBUG_CATEGORY_NAT, "NAT client: etcp_route_send to provider %016llx failed",
(unsigned long long)tr->nat_via_node_id);
queue_entry_free(new_entry); queue_dgram_free(new_entry);
}
}
// PROVIDER: NAT TUN output (internet response) → ingress NAT → encapsulate ETCP_ID_NAT → send back
// PROVIDER: NAT TUN output (internet response) → ingress NAT → send back via etcp_router
static void nat_transport_provider_tun_out_cb(struct ll_queue* q, void* arg) {
struct UTUN_INSTANCE* inst = (struct UTUN_INSTANCE*)arg;
if (!inst) { queue_resume_callback(q); return; }
struct nat_transport_ctx* tr = &inst->nat_tr;
struct eim_nat_ctx* ctx = &inst->nat;
struct ll_entry* pkt = queue_data_get(q);
@ -80,21 +67,20 @@ static void nat_transport_provider_tun_out_cb(struct ll_queue* q, void* arg) {
struct eim_nat_entry* entry = NULL;
int ret = eim_nat_ingress(ctx, pkt->dgram + 1, pkt->len - 1, &entry);
if (ret != 0 || !entry || !entry->src_conn) {
if (ret != 0 || !entry || entry->src_node_id == 0) {
if (ret == 0) DEBUG_WARN(DEBUG_CATEGORY_NAT, "Ingress NAT: no matching entry, dropping");
queue_dgram_free(pkt); queue_entry_free(pkt); queue_resume_callback(q);
return;
}
size_t ip_len = pkt->len - 1;
size_t total_len = NAT_HDR_SIZE + ip_len;
size_t total_len = NAT_SVC_HDR_SIZE + ip_len;
uint8_t* new_dgram = u_malloc(total_len);
if (!new_dgram) { queue_dgram_free(pkt); queue_entry_free(pkt); queue_resume_callback(q); return; }
new_dgram[0] = ETCP_ID_NAT;
memcpy(new_dgram + 1, &tr->self_node_id, 8);
memcpy(new_dgram + 9, &entry->src_node_id, 8);
memcpy(new_dgram + 17, pkt->dgram + 1, ip_len);
memcpy(new_dgram + 1, &inst->nat_tr.self_node_id, 8);
memcpy(new_dgram + 9, pkt->dgram + 1, ip_len);
struct ll_entry* new_entry = queue_entry_new(0);
if (!new_entry) { u_free(new_dgram); queue_dgram_free(pkt); queue_entry_free(pkt); queue_resume_callback(q); return; }
@ -104,17 +90,17 @@ static void nat_transport_provider_tun_out_cb(struct ll_queue* q, void* arg) {
queue_dgram_free(pkt); queue_entry_free(pkt);
queue_resume_callback(q);
int send_ret = etcp_send(entry->src_conn, new_entry);
int send_ret = etcp_route_send(inst, entry->src_node_id, new_entry);
if (send_ret != 0) {
DEBUG_WARN(DEBUG_CATEGORY_NAT, "etcp_send back to node %016llx failed",
DEBUG_WARN(DEBUG_CATEGORY_NAT, "NAT provider: etcp_route_send back to node %016llx failed",
(unsigned long long)entry->src_node_id);
queue_entry_free(new_entry); queue_dgram_free(new_entry);
}
}
// ETCP_ID_NAT receive: CLIENT gets response, PROVIDER gets request
// ETCP_ID_NAT receive via etcp_router: CLIENT gets response, PROVIDER gets request
static void nat_transport_etcp_recv_cb(struct ETCP_CONN* conn, struct ll_entry* entry) {
if (!conn || !entry || !entry->dgram || entry->len < NAT_HDR_SIZE) {
if (!conn || !entry || !entry->dgram || entry->len < NAT_SVC_HDR_SIZE) {
if (entry) { queue_entry_free(entry); queue_dgram_free(entry); }
return;
}
@ -124,25 +110,22 @@ static void nat_transport_etcp_recv_cb(struct ETCP_CONN* conn, struct ll_entry*
struct eim_nat_ctx* ctx = &inst->nat;
if (!ctx->initialized) { queue_entry_free(entry); queue_dgram_free(entry); return; }
uint64_t src_node_id, dst_node_id;
uint64_t src_node_id;
memcpy(&src_node_id, entry->dgram + 1, 8);
memcpy(&dst_node_id, entry->dgram + 9, 8);
uint8_t* ip_data = entry->dgram + NAT_HDR_SIZE;
size_t ip_len = entry->len - NAT_HDR_SIZE;
uint8_t* ip_data = entry->dgram + NAT_SVC_HDR_SIZE;
size_t ip_len = entry->len - NAT_SVC_HDR_SIZE;
if (tr->nat_via_node_id != 0) {
// CLIENT: response from provider → write to NAT TUN
if (tr->nat_tun) {
tun_write(tr->nat_tun, entry->dgram + NAT_HDR_SIZE - 1, ip_len + 1);
tun_write(tr->nat_tun, entry->dgram + NAT_SVC_HDR_SIZE - 1, ip_len + 1);
DEBUG_DEBUG(DEBUG_CATEGORY_NAT, "NAT client: received %zu bytes from provider", ip_len);
}
} else {
// PROVIDER: request from client → egress NAT → write to NAT TUN
int ret = eim_nat_egress(ctx, ip_data, ip_len, src_node_id, conn);
if (ret < 0) {
DEBUG_WARN(DEBUG_CATEGORY_NAT, "Egress NAT failed");
} else if (ret == 0 && tr->nat_tun) {
tun_write(tr->nat_tun, entry->dgram + NAT_HDR_SIZE - 1, ip_len + 1);
tun_write(tr->nat_tun, entry->dgram + NAT_SVC_HDR_SIZE - 1, ip_len + 1);
DEBUG_DEBUG(DEBUG_CATEGORY_NAT, "NAT provider: sent %zu bytes to internet", ip_len);
}
}
@ -163,19 +146,15 @@ int nat_transport_init(struct UTUN_INSTANCE* inst) {
tr->self_node_id = inst->node_id;
tr->nat_via_node_id = g->nat_via_node_id;
// Initialize NAT engine (table, forwards, gateway_ip) — only provider needs full init.
// Client also gets minimal init so ctx->initialized==1 for callback check.
if (tr->nat_via_node_id == 0) {
if (eim_nat_init_ctx(&inst->nat, g) != 0) {
DEBUG_ERROR(DEBUG_CATEGORY_NAT, "Failed to init NAT engine");
return -1;
}
} else {
// Client: minimal init — mark as initialized without allocating table
inst->nat.initialized = 1;
}
// Create NAT TUN
const char* tun_name = g->nat_tun_ifname[0] ? g->nat_tun_ifname : "tun_nat";
char ip_str[64] = "";
if (g->nat_tun_ip.family == AF_INET) {
@ -194,15 +173,13 @@ int nat_transport_init(struct UTUN_INSTANCE* inst) {
return -1;
}
// Bind ETCP_ID_NAT
if (etcp_bind(inst, ETCP_ID_NAT, nat_transport_etcp_recv_cb) != 0) {
DEBUG_ERROR(DEBUG_CATEGORY_NAT, "Failed to bind ETCP_ID_NAT");
if (etcp_router_bind(inst, ETCP_ID_NAT, nat_transport_etcp_recv_cb) != 0) {
DEBUG_ERROR(DEBUG_CATEGORY_NAT, "Failed to bind ETCP_ID_NAT via etcp_router");
tun_close(tr->nat_tun); tr->nat_tun = NULL;
eim_nat_destroy_ctx(&inst->nat);
return -1;
}
// Role-specific TUN callback
struct eim_nat_ctx* ctx = &inst->nat;
if (tr->nat_via_node_id != 0) {
if (tr->nat_tun->output_queue) queue_set_callback(tr->nat_tun->output_queue, nat_transport_client_tun_out_cb, inst);
@ -223,7 +200,7 @@ void nat_transport_destroy(struct UTUN_INSTANCE* inst) {
if (!inst || !inst->nat_tr.initialized) return;
struct nat_transport_ctx* tr = &inst->nat_tr;
etcp_unbind(inst, ETCP_ID_NAT);
etcp_router_unbind(inst, ETCP_ID_NAT);
if (tr->nat_tun) { tun_close(tr->nat_tun); tr->nat_tun = NULL; }

1
src/nat_transport.h

@ -11,7 +11,6 @@ struct nat_transport_ctx {
uint64_t self_node_id;
uint64_t nat_via_node_id;
struct tun_if* nat_tun;
struct ETCP_CONN* nat_via_conn;
int initialized;
};

93
src/routing.c

@ -7,6 +7,7 @@
#include "packet_dump.h"
#include "etcp.h"
#include "etcp_api.h"
#include "etcp_router.h"
#include "pkt_normalizer.h"
#include "utun_instance.h"
#include "../lib/ll_queue.h"
@ -140,75 +141,44 @@ void route_pkt(struct UTUN_INSTANCE* instance, struct ll_entry* entry, uint64_t
return;
}
uint64_t dst_node_id = instance->node_id;
struct ETCP_CONN* conn = NULL;
struct NODEINFO_Q* nq = route->v_node_info;
if (!nq || nq->node.hop_count == 0) {
DEBUG_TRACE(DEBUG_CATEGORY_ROUTING, "Local route to %s", ip_to_str(&addr, AF_INET).str);
} else {
if (nq->paths && nq->paths->head) {
struct NODEINFO_PATH* path = (struct NODEINFO_PATH*)nq->paths->head;
conn = path->conn;
}
if (!conn) {
DEBUG_WARN(DEBUG_CATEGORY_ROUTING, "route_pkt: no path for node %016llx dst=%s conn=%s",
nq->node.node_id, ip_to_str(&addr, AF_INET).str, conn ? conn->log_name : "null");
DEBUG_TRACE(DEBUG_CATEGORY_ROUTING, "route_pkt: sending %zu bytes to node %016llx dst=%s",
ip_len, (unsigned long long)nq->node.node_id, ip_to_str(&addr, AF_INET).str);
int send_err = etcp_route_send(instance, nq->node.node_id, entry);
if (send_err != 0) {
DEBUG_WARN(DEBUG_CATEGORY_ROUTING, "route_pkt: etcp_route_send failed: dst=%s err=%d",
ip_to_str(&addr, AF_INET).str, send_err);
instance->dropped_packets++;
queue_entry_free(entry);
queue_dgram_free(entry);
return;
}
dst_node_id = conn->peer_node_id;
if (!conn->normalizer) {
DEBUG_WARN(DEBUG_CATEGORY_ROUTING, "route_pkt: connection for %s has no normalizer", ip_to_str(&addr, AF_INET).str);
instance->dropped_packets++;
queue_entry_free(entry);
queue_dgram_free(entry);
return;
}
instance->routed_packets++;
return;
}
if (debug_should_output(DEBUG_LEVEL_DEBUG, DEBUG_CATEGORY_TRAFFIC)) {
char* packet_str = dump_ip_packet_to_buffer(ip_data, ip_len);
DEBUG_DEBUG(DEBUG_CATEGORY_TRAFFIC, "DUMP: %s", packet_str);
} else {
DEBUG_TRACE(DEBUG_CATEGORY_TRAFFIC, "NODE %016llx -> NODE %016llx", (unsigned long long)src_node_id, (unsigned long long)dst_node_id);
DEBUG_TRACE(DEBUG_CATEGORY_TRAFFIC, "NODE %016llx -> NODE %016llx", (unsigned long long)src_node_id, (unsigned long long)src_node_id);
}
if (!nq || nq->node.hop_count == 0) {
int put_err = queue_data_put(instance->tun->input_queue, entry);
if (put_err != 0) {
DEBUG_WARN(DEBUG_CATEGORY_ROUTING, "route_pkt: failed to put to TUN: dst=%s err=%d",
ip_to_str(&addr, AF_INET).str, put_err);
instance->dropped_packets++;
queue_entry_free(entry);
queue_dgram_free(entry);
return;
}
instance->routed_packets++;
DEBUG_TRACE(DEBUG_CATEGORY_ROUTING, "route_pkt: sent %zu bytes to TUN", ip_len);
return;
}
// Send to ETCP
DEBUG_TRACE(DEBUG_CATEGORY_ROUTING, "route_pkt: sending %zu bytes to ETCP %s dst=%s",
ip_len, conn->log_name[0] ? conn->log_name : "unknown", ip_to_str(&addr, AF_INET).str);
int send_err = etcp_send(conn, entry);
DEBUG_TRACE(DEBUG_CATEGORY_ROUTING, "send retcode=%d", send_err);
if (send_err != 0) {
DEBUG_WARN(DEBUG_CATEGORY_ROUTING, "route_pkt: etcp_send failed: dst=%s err=%d",
ip_to_str(&addr, AF_INET).str, send_err);
int put_err = queue_data_put(instance->tun->input_queue, entry);
if (put_err != 0) {
DEBUG_WARN(DEBUG_CATEGORY_ROUTING, "route_pkt: failed to put to TUN: dst=%s err=%d",
ip_to_str(&addr, AF_INET).str, put_err);
instance->dropped_packets++;
queue_entry_free(entry);
queue_dgram_free(entry);
return;
}
// Entry sent successfully, don't free here
instance->routed_packets++;
DEBUG_TRACE(DEBUG_CATEGORY_ROUTING, "route_pkt: sent %zu bytes to TUN", ip_len);
}
// Callback for packets from ETCP (via etcp_bind id=0)
// Callback for packets from ETCP (via etcp_router_bind id=0)
static void routing_pkt_from_etcp_cb(struct ETCP_CONN* conn, struct ll_entry* pkt) {
DEBUG_TRACE(DEBUG_CATEGORY_ROUTING, "");
if (!conn || !pkt) {
@ -237,10 +207,10 @@ static void routing_pkt_from_etcp_cb(struct ETCP_CONN* conn, struct ll_entry* pk
// Callback for packets from TUN output queue
static void routing_pkt_from_tun_cb(struct ll_queue* q, void* arg) {
(void)q;
struct UTUN_INSTANCE* instance = (struct UTUN_INSTANCE*)arg;
if (!instance) {
DEBUG_ERROR(DEBUG_CATEGORY_ROUTING, "routing_pkt_from_tun_cb: invalid instance arg=%p", arg);
queue_resume_callback(q);
return;
}
@ -256,7 +226,7 @@ static void routing_pkt_from_tun_cb(struct ll_queue* q, void* arg) {
queue_resume_callback(instance->tun->output_queue);
}
// Initialize routing module for instance
// Initialize routing module for instance (route table only, bind happens via routing_bind)
int routing_create(struct UTUN_INSTANCE* instance) {
if (!instance) {
DEBUG_ERROR(DEBUG_CATEGORY_ROUTING, "routing_create: instance is NULL");
@ -271,18 +241,25 @@ int routing_create(struct UTUN_INSTANCE* instance) {
return -1;
}
// Bind ID=0 for receiving data packets from ETCP
if (etcp_bind(instance, ETCP_ID_DATA, routing_pkt_from_etcp_cb) != 0) {
DEBUG_ERROR(DEBUG_CATEGORY_ROUTING, "routing_create: failed to bind ETCP ID=0 for node %016llx",
DEBUG_INFO(DEBUG_CATEGORY_ROUTING, "Routing table created for instance node_id=%016llx",
(unsigned long long)instance->node_id);
return 0;
}
// Bind DATA handler via etcp_router (must be called after etcp_router_init)
int routing_bind(struct UTUN_INSTANCE* instance) {
if (!instance) {
DEBUG_ERROR(DEBUG_CATEGORY_ROUTING, "routing_bind: instance is NULL");
return -1;
}
if (etcp_router_bind(instance, ETCP_ID_DATA, routing_pkt_from_etcp_cb) != 0) {
DEBUG_ERROR(DEBUG_CATEGORY_ROUTING, "routing_bind: failed to bind ETCP_ID_DATA via etcp_router for node %016llx",
(unsigned long long)instance->node_id);
route_table_destroy(instance->rt);
instance->rt = NULL;
return -1;
}
DEBUG_INFO(DEBUG_CATEGORY_ROUTING, "Routing module initialized for instance node_id=%016llx",
DEBUG_INFO(DEBUG_CATEGORY_ROUTING, "Routing module bound to etcp_router for node_id=%016llx",
(unsigned long long)instance->node_id);
return 0;
}
@ -293,8 +270,8 @@ void routing_destroy(struct UTUN_INSTANCE* instance) {
DEBUG_INFO(DEBUG_CATEGORY_ROUTING, "Destroying routing module for node_id=%016llx",
(unsigned long long)instance->node_id);
// Unbind ETCP ID=0
etcp_unbind(instance, ETCP_ID_DATA);
// Unbind DATA handler from etcp_router
etcp_router_unbind(instance, ETCP_ID_DATA);
// Clean up route table if exists
if (instance->rt) {

9
src/routing.h

@ -11,12 +11,19 @@ struct UTUN_INSTANCE;
struct ll_entry;
/**
* @brief Initialize routing module for instance
* @brief Initialize routing module for instance (route table only)
* @param instance UTUN instance
* @return 0 on success, -1 on error
*/
int routing_create(struct UTUN_INSTANCE* instance);
/**
* @brief Bind DATA handler via etcp_router (must be called after etcp_router_init)
* @param instance UTUN instance
* @return 0 on success, -1 on error
*/
int routing_bind(struct UTUN_INSTANCE* instance);
/**
* @brief Destroy routing module for instance
* @param instance UTUN instance

2
src/tcp_proxy.c

@ -107,7 +107,7 @@ static struct ll_entry* entry_from_data(struct memory_pool* pool, const uint8_t*
static inline void tcp_proxy_write_output(struct tcp_proxy* p) {
if(uip_len == 0) return;
if(p->tun) tun_platform_write(p->tun, uip_buf, uip_len);
else write(p->ip_fd, uip_buf, uip_len);
else if (write(p->ip_fd, uip_buf, uip_len)) {}
}
// ====================================================================

24
src/utun_instance.c

@ -130,12 +130,18 @@ static int instance_init_common(struct UTUN_INSTANCE* instance, struct UASYNC* u
instance->fw.count, instance->fw.bypass_all);
}
// etcp_router — сервисная маршрутизация (после BGP, до TCP proxy/NAT)
// etcp_router — сервисная маршрутизация (после BGP, до TCP proxy/NAT/DATA)
if (etcp_router_init(instance) != 0) {
DEBUG_ERROR(DEBUG_CATEGORY_ETCP, "Failed to initialize etcp_router");
return -1;
}
// Bind DATA handler via etcp_router (after etcp_router_init)
if (routing_bind(instance) != 0) {
DEBUG_ERROR(DEBUG_CATEGORY_ROUTING, "Failed to bind DATA via etcp_router");
return -1;
}
// Remote proxy (exit node, optional) — must be before tcp_proxy so
// tcp_proxy_create can overwrite the handler if it has remote mappings
if (remote_proxy_init(instance) != 0) {
@ -326,11 +332,16 @@ void utun_instance_destroy(struct UTUN_INSTANCE *instance) {
// Cleanup remote proxy
remote_proxy_destroy(instance);
// Cleanup routing module (unbinds from etcp_router before etcp_router_destroy)
routing_destroy(instance);
// Cleanup NAT (unbinds from etcp_router before etcp_router_destroy)
if (instance->nat_tr.initialized) {
nat_transport_destroy(instance);
}
// Cleanup etcp_router
etcp_router_destroy(instance);
// Cleanup routing module
routing_destroy(instance);
// Cleanup BGP module
if (instance->bgp) {
@ -342,11 +353,6 @@ void utun_instance_destroy(struct UTUN_INSTANCE *instance) {
// Cleanup firewall
fw_free(&instance->fw);
// Cleanup NAT
if (instance->nat_tr.initialized) {
nat_transport_destroy(instance);
}
// Cleanup config
if (instance->config) {
DEBUG_INFO(DEBUG_CATEGORY_MEMORY, "[INSTANCE_DESTROY] Freeing configuration");

2
tests/Makefile.am

@ -222,7 +222,7 @@ test_pkt_normalizer_etcp_LDADD = $(ETCP_FULL_OBJS) $(SECURE_CHANNEL_OBJS) $(CRYP
test_pkt_normalizer_standalone_SOURCES = test_pkt_normalizer_standalone.c
test_pkt_normalizer_standalone_CFLAGS = -I$(top_srcdir)/src -I$(top_srcdir)/lib -I$(top_srcdir)/tinycrypt/lib/include -I$(top_srcdir)/tinycrypt/lib/source
test_pkt_normalizer_standalone_LDADD = $(top_builddir)/src/utun-pkt_normalizer.o $(top_builddir)/src/utun-route_lib.o $(top_builddir)/src/utun-route_node.o $(top_builddir)/src/utun-routing.o $(top_builddir)/src/utun-packet_dump.o $(top_builddir)/src/utun-etcp_api.o $(top_builddir)/src/utun-etcp_debug.o $(CRYPTO_LIBS) $(COMMON_LIBS)
test_pkt_normalizer_standalone_LDADD = $(ETCP_FULL_OBJS) $(SECURE_CHANNEL_OBJS) $(CRYPTO_LIBS) $(COMMON_LIBS)
test_etcp_api_SOURCES = test_etcp_api.c
test_etcp_api_CFLAGS = -I$(top_srcdir)/src -I$(top_srcdir)/lib -I$(top_srcdir)/tinycrypt/lib/include -I$(top_srcdir)/tinycrypt/lib/source

47
tests/test_nat_transport.c

@ -26,6 +26,7 @@
#include "../src/nat_transport.h"
#include "../src/eim_nat.h"
#include "../src/etcp_api.h"
#include "../src/etcp_router.h"
#include "../lib/u_async.h"
#include "../lib/debug_config.h"
#include "../lib/mem.h"
@ -34,7 +35,7 @@
#define TEST_TIMEOUT_MS 15000
#define NODE_ID_PROVIDER 0xAAAA000000000001ULL
#define NODE_ID_CLIENT 0xBBBB000000000001ULL
#define NAT_HDR_SIZE 17 // cmd(1) + src_node_id(8) + dst_node_id(8)
#define NAT_SVC_HDR_SIZE 9 // svc_id(1) + src_node_id(8)
static struct UTUN_INSTANCE* inst_provider = NULL;
static struct UTUN_INSTANCE* inst_client = NULL;
@ -276,7 +277,7 @@ static int test_provider_egress(void) {
/* Inject a raw IP/UDP packet directly into provider via ETCP */
DEBUG_INFO(DEBUG_CATEGORY_NAT, "=== test_provider_egress ===");
// Get the connection from client to provider
// Get the connection from client to provider (for debug info only)
struct ETCP_CONN* client_conn = inst_client->connections;
if (!client_conn) {
DEBUG_ERROR(DEBUG_CATEGORY_NAT, "No client connections");
@ -284,40 +285,28 @@ static int test_provider_egress(void) {
}
DEBUG_INFO(DEBUG_CATEGORY_NAT, "Client conn peer_node_id=0x%016llx", (unsigned long long)client_conn->peer_node_id);
// But we need to send FROM client TO provider. The client's nat_via_conn
// should be resolved via route_bgp_find_conn_for_node.
// Since we haven't triggered a TUN out yet, we need to force resolve.
// Simpler: use the already-established connection from client side.
struct ETCP_CONN* via_conn = route_bgp_find_conn_for_node(inst_client->bgp, NODE_ID_PROVIDER);
if (!via_conn) {
DEBUG_ERROR(DEBUG_CATEGORY_NAT, "No route to provider");
return 0;
}
DEBUG_INFO(DEBUG_CATEGORY_NAT, "via_conn peer=0x%016llx", (unsigned long long)via_conn->peer_node_id);
// Build ETCP_ID_NAT packet
// Build ETCP_ID_NAT packet via etcp_route_send (new format: svc_id + src_node_id + ip_data)
size_t ip_len;
uint8_t* raw_ip = build_udp_pkt(0x0A0000FE, 40000, 0x08080808, 53, &ip_len);
size_t total = NAT_HDR_SIZE + ip_len;
size_t total = NAT_SVC_HDR_SIZE + ip_len;
uint8_t* dgram = u_malloc(total);
dgram[0] = ETCP_ID_NAT;
memcpy(dgram + 1, &inst_client->nat_tr.self_node_id, 8);
memcpy(dgram + 9, &inst_provider->nat_tr.self_node_id, 8);
memcpy(dgram + 17, raw_ip, ip_len);
memcpy(dgram + 1, &inst_client->nat_tr.self_node_id, 8);
memcpy(dgram + 9, raw_ip, ip_len);
free(raw_ip);
struct ll_entry* entry = queue_entry_new(0);
entry->dgram = dgram;
entry->len = total;
int ret = etcp_send(via_conn, entry);
int ret = etcp_route_send(inst_client, NODE_ID_PROVIDER, entry);
if (ret != 0) {
DEBUG_ERROR(DEBUG_CATEGORY_NAT, "etcp_send failed");
DEBUG_ERROR(DEBUG_CATEGORY_NAT, "etcp_route_send failed");
queue_entry_free(entry);
queue_dgram_free(entry);
return 0;
}
DEBUG_INFO(DEBUG_CATEGORY_NAT, "ETCP_ID_NAT sent from client to provider");
DEBUG_INFO(DEBUG_CATEGORY_NAT, "ETCP_ID_NAT sent from client to provider via etcp_router");
// Poll to let provider process
int cycles = 0;
@ -466,25 +455,21 @@ static int test_full_roundtrip(void) {
memset(&inst_provider->nat.table[p], 0, sizeof(struct eim_nat_entry));
inst_provider->nat.next_port = inst_provider->nat.port_start;
// === Step 1: Send ETCP_ID_NAT from client to provider (egress) ===
struct ETCP_CONN* via_conn = route_bgp_find_conn_for_node(inst_client->bgp, NODE_ID_PROVIDER);
if (!via_conn) { DEBUG_ERROR(DEBUG_CATEGORY_NAT, "No route to provider"); return 0; }
// === Step 1: Send ETCP_ID_NAT from client to provider via etcp_router (egress) ===
size_t ip_len;
uint8_t* raw_ip = build_udp_pkt(0x0A0000CD, 44444, 0x08080808, 80, &ip_len);
size_t total = NAT_HDR_SIZE + ip_len;
size_t total = NAT_SVC_HDR_SIZE + ip_len;
uint8_t* dgram = u_malloc(total);
dgram[0] = ETCP_ID_NAT;
memcpy(dgram + 1, &inst_client->nat_tr.self_node_id, 8);
memcpy(dgram + 9, &inst_provider->nat_tr.self_node_id, 8);
memcpy(dgram + 17, raw_ip, ip_len);
memcpy(dgram + 1, &inst_client->nat_tr.self_node_id, 8);
memcpy(dgram + 9, raw_ip, ip_len);
free(raw_ip);
struct ll_entry* entry = queue_entry_new(0);
entry->dgram = dgram;
entry->len = total;
int ret = etcp_send(via_conn, entry);
if (ret != 0) { DEBUG_ERROR(DEBUG_CATEGORY_NAT, "etcp_send failed"); queue_entry_free(entry); queue_dgram_free(entry); return 0; }
int ret = etcp_route_send(inst_client, NODE_ID_PROVIDER, entry);
if (ret != 0) { DEBUG_ERROR(DEBUG_CATEGORY_NAT, "etcp_route_send failed"); queue_entry_free(entry); queue_dgram_free(entry); return 0; }
// Poll for provider to process egress
int cycles = 0;

5
tests/test_pkt_normalizer_standalone.c

@ -12,8 +12,9 @@
#include "../src/pkt_normalizer.h"
#include "../src/etcp.h"
// Stub for etcp_conn_reinit - should not be called in standalone test
void etcp_conn_reinit(struct ETCP_CONN* etcp) {
// Weak stub for etcp_conn_reinit — overridden if real ETCP is linked
// Weak stub for etcp_conn_reinit - can be overridden by real ETCP implementation
__attribute__((weak)) void etcp_conn_reinit(struct ETCP_CONN* etcp) {
(void)etcp;
fprintf(stderr, "FAIL: etcp_conn_reinit called - ETCP not initialized in standalone test!\n");
exit(1);

Loading…
Cancel
Save