Добавлен тестовый режим для TUN интерфейса и тест роутинга mesh
- Добавлена опция tun_test_mode в конфиг для работы без реального TUN устройства - Добавлены функции для работы с очередями TUN в тестовом режиме - Добавлен API для программного создания instance из структуры конфига - Создан тест test_routing_mesh.c с 3-instance mesh топологией - Ключи генерируются автоматически и распределяются между instance
This commit is contained in:
1 parent
602d9174a4
commit
bee1e41b07
8 files changed
+1176
-33
No files matched your search
@@ -324,6 +324,10 @@ static int parse_global(const char *key, const char *value, struct global_config
|
||||
global->enable_colors = atoi(value);
|
||||
return 0;
|
||||
}
|
||||
if (strcmp(key, "tun_test_mode") == 0) {
|
||||
global->tun_test_mode = atoi(value);
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -610,6 +614,7 @@ void print_config(const struct utun_config *cfg) {
|
||||
printf(" TUN interface: %s\n", g->tun_ifname[0] ? g->tun_ifname : "auto");
|
||||
printf(" TUN IP: %s\n", ip_to_string(&g->tun_ip, ip_buffer, sizeof(ip_buffer)));
|
||||
printf(" MTU: %d\n", g->mtu);
|
||||
printf(" TUN test mode: %s\n", g->tun_test_mode ? "enabled" : "disabled");
|
||||
printf(" Net debug: %d\n", g->net_debug);
|
||||
|
||||
printf("\nServers:\n");
|
||||
|
||||
@@ -74,6 +74,8 @@ struct global_config {
|
||||
int enable_function_names; // enable function names in logs
|
||||
int enable_file_lines; // enable file:line in logs
|
||||
int enable_colors; // enable ANSI colors in logs
|
||||
|
||||
int tun_test_mode; // test mode: 1 = don't open real TUN, queues only
|
||||
};
|
||||
|
||||
struct utun_config {
|
||||
|
||||
+180
-33
@@ -111,6 +111,9 @@ struct tun_if* tun_init(struct UASYNC* ua, struct utun_config* config) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Check for test mode
|
||||
int test_mode = config->global.tun_test_mode;
|
||||
|
||||
// Allocate tun_if structure
|
||||
struct tun_if* tun = calloc(1, sizeof(struct tun_if));
|
||||
if (!tun) {
|
||||
@@ -122,6 +125,7 @@ struct tun_if* tun_init(struct UASYNC* ua, struct utun_config* config) {
|
||||
tun->fd = -1;
|
||||
tun->platform_handle = NULL;
|
||||
tun->adapter_handle = NULL;
|
||||
tun->test_mode = test_mode;
|
||||
|
||||
// Get interface name from config (or empty for auto)
|
||||
const char* ifname = config->global.tun_ifname;
|
||||
@@ -147,18 +151,28 @@ struct tun_if* tun_init(struct UASYNC* ua, struct utun_config* config) {
|
||||
// Get MTU
|
||||
int mtu = config->global.mtu > 0 ? config->global.mtu : TUN_MTU_DEFAULT;
|
||||
|
||||
// Platform-specific initialization
|
||||
if (tun_platform_init(tun, tun->ifname, tun_ip_str, mtu) != 0) {
|
||||
DEBUG_ERROR(DEBUG_CATEGORY_TUN, "Platform-specific TUN initialization failed");
|
||||
free(tun);
|
||||
return NULL;
|
||||
// Platform-specific initialization (skip in test mode)
|
||||
if (!test_mode) {
|
||||
if (tun_platform_init(tun, tun->ifname, tun_ip_str, mtu) != 0) {
|
||||
DEBUG_ERROR(DEBUG_CATEGORY_TUN, "Platform-specific TUN initialization failed");
|
||||
free(tun);
|
||||
return NULL;
|
||||
}
|
||||
} else {
|
||||
DEBUG_INFO(DEBUG_CATEGORY_TUN, "TUN test mode: skipping platform initialization");
|
||||
// In test mode, set a fake interface name if not provided
|
||||
if (tun->ifname[0] == '\0') {
|
||||
strncpy(tun->ifname, "tun_test", sizeof(tun->ifname) - 1);
|
||||
}
|
||||
}
|
||||
|
||||
// Create memory pool for ETCP_FRAGMENT
|
||||
tun->pool = memory_pool_init(sizeof(struct ETCP_FRAGMENT));
|
||||
if (!tun->pool) {
|
||||
DEBUG_ERROR(DEBUG_CATEGORY_TUN, "Failed to create memory pool");
|
||||
tun_platform_cleanup(tun);
|
||||
if (!test_mode) {
|
||||
tun_platform_cleanup(tun);
|
||||
}
|
||||
free(tun);
|
||||
return NULL;
|
||||
}
|
||||
@@ -168,7 +182,9 @@ struct tun_if* tun_init(struct UASYNC* ua, struct utun_config* config) {
|
||||
if (!tun->output_queue) {
|
||||
DEBUG_ERROR(DEBUG_CATEGORY_TUN, "Failed to create output queue");
|
||||
memory_pool_destroy(tun->pool);
|
||||
tun_platform_cleanup(tun);
|
||||
if (!test_mode) {
|
||||
tun_platform_cleanup(tun);
|
||||
}
|
||||
free(tun);
|
||||
return NULL;
|
||||
}
|
||||
@@ -179,7 +195,9 @@ struct tun_if* tun_init(struct UASYNC* ua, struct utun_config* config) {
|
||||
DEBUG_ERROR(DEBUG_CATEGORY_TUN, "Failed to create input queue");
|
||||
queue_free(tun->output_queue);
|
||||
memory_pool_destroy(tun->pool);
|
||||
tun_platform_cleanup(tun);
|
||||
if (!test_mode) {
|
||||
tun_platform_cleanup(tun);
|
||||
}
|
||||
free(tun);
|
||||
return NULL;
|
||||
}
|
||||
@@ -187,31 +205,38 @@ struct tun_if* tun_init(struct UASYNC* ua, struct utun_config* config) {
|
||||
// Set callback for input_queue - routing will put packets here
|
||||
queue_set_callback(tun->input_queue, tun_input_queue_callback, tun);
|
||||
|
||||
// Register TUN socket with uasync
|
||||
int poll_fd = tun_platform_get_poll_fd(tun);
|
||||
if (poll_fd < 0) {
|
||||
DEBUG_ERROR(DEBUG_CATEGORY_TUN, "Failed to get poll fd for TUN");
|
||||
queue_free(tun->output_queue);
|
||||
queue_free(tun->input_queue);
|
||||
memory_pool_destroy(tun->pool);
|
||||
tun_platform_cleanup(tun);
|
||||
free(tun);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
tun->socket_id = uasync_add_socket(ua, poll_fd, tun_read_callback, NULL, NULL, tun);
|
||||
if (!tun->socket_id) {
|
||||
DEBUG_ERROR(DEBUG_CATEGORY_TUN, "Failed to register TUN socket with uasync");
|
||||
queue_free(tun->output_queue);
|
||||
queue_free(tun->input_queue);
|
||||
memory_pool_destroy(tun->pool);
|
||||
tun_platform_cleanup(tun);
|
||||
free(tun);
|
||||
return NULL;
|
||||
// Register TUN socket with uasync (skip in test mode)
|
||||
if (!test_mode) {
|
||||
int poll_fd = tun_platform_get_poll_fd(tun);
|
||||
if (poll_fd < 0) {
|
||||
DEBUG_ERROR(DEBUG_CATEGORY_TUN, "Failed to get poll fd for TUN");
|
||||
queue_free(tun->output_queue);
|
||||
queue_free(tun->input_queue);
|
||||
memory_pool_destroy(tun->pool);
|
||||
tun_platform_cleanup(tun);
|
||||
free(tun);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
tun->socket_id = uasync_add_socket(ua, poll_fd, tun_read_callback, NULL, NULL, tun);
|
||||
if (!tun->socket_id) {
|
||||
DEBUG_ERROR(DEBUG_CATEGORY_TUN, "Failed to register TUN socket with uasync");
|
||||
queue_free(tun->output_queue);
|
||||
queue_free(tun->input_queue);
|
||||
memory_pool_destroy(tun->pool);
|
||||
tun_platform_cleanup(tun);
|
||||
free(tun);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
DEBUG_INFO(DEBUG_CATEGORY_TUN, "TUN interface initialized: %s (IP=%s, MTU=%d)",
|
||||
tun->ifname, tun_ip_str, mtu);
|
||||
if (test_mode) {
|
||||
DEBUG_INFO(DEBUG_CATEGORY_TUN, "TUN interface initialized in TEST MODE: %s (IP=%s, MTU=%d)",
|
||||
tun->ifname, tun_ip_str, mtu);
|
||||
} else {
|
||||
DEBUG_INFO(DEBUG_CATEGORY_TUN, "TUN interface initialized: %s (IP=%s, MTU=%d)",
|
||||
tun->ifname, tun_ip_str, mtu);
|
||||
}
|
||||
|
||||
return tun;
|
||||
}
|
||||
@@ -259,8 +284,10 @@ void tun_close(struct tun_if* tun) {
|
||||
tun->pool = NULL;
|
||||
}
|
||||
|
||||
// Platform-specific cleanup
|
||||
tun_platform_cleanup(tun);
|
||||
// Platform-specific cleanup (skip in test mode)
|
||||
if (!tun->test_mode) {
|
||||
tun_platform_cleanup(tun);
|
||||
}
|
||||
|
||||
free(tun);
|
||||
}
|
||||
@@ -271,6 +298,16 @@ ssize_t tun_write(struct tun_if* tun, const uint8_t* buf, size_t len) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// In test mode, inject packet into output_queue instead of writing to interface
|
||||
if (tun->test_mode) {
|
||||
if (tun_inject_packet(tun, buf, len) == 0) {
|
||||
return len;
|
||||
} else {
|
||||
tun->write_errors++;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
ssize_t nwritten = tun_platform_write(tun, buf, len);
|
||||
if (nwritten < 0) {
|
||||
DEBUG_ERROR(DEBUG_CATEGORY_TUN, "Failed to write to TUN device %s", tun->ifname);
|
||||
@@ -285,3 +322,113 @@ ssize_t tun_write(struct tun_if* tun, const uint8_t* buf, size_t len) {
|
||||
|
||||
return nwritten;
|
||||
}
|
||||
|
||||
struct ll_queue* tun_get_input_queue(struct tun_if* tun) {
|
||||
if (!tun) {
|
||||
return NULL;
|
||||
}
|
||||
return tun->input_queue;
|
||||
}
|
||||
|
||||
struct ll_queue* tun_get_output_queue(struct tun_if* tun) {
|
||||
if (!tun) {
|
||||
return NULL;
|
||||
}
|
||||
return tun->output_queue;
|
||||
}
|
||||
|
||||
int tun_is_test_mode(struct tun_if* tun) {
|
||||
if (!tun) {
|
||||
return -1;
|
||||
}
|
||||
return tun->test_mode;
|
||||
}
|
||||
|
||||
int tun_inject_packet(struct tun_if* tun, const uint8_t* buf, size_t len) {
|
||||
if (!tun || !buf || len == 0) {
|
||||
DEBUG_ERROR(DEBUG_CATEGORY_TUN, "tun_inject_packet: invalid arguments");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (len > TUN_MAX_PACKET_SIZE) {
|
||||
DEBUG_WARN(DEBUG_CATEGORY_TUN, "Packet too large: %zu bytes (max %d)",
|
||||
len, TUN_MAX_PACKET_SIZE);
|
||||
}
|
||||
|
||||
// Allocate packet data
|
||||
uint8_t* packet_data = malloc(len);
|
||||
if (!packet_data) {
|
||||
DEBUG_ERROR(DEBUG_CATEGORY_TUN, "tun_inject_packet: failed to allocate packet data");
|
||||
tun->read_errors++;
|
||||
return -1;
|
||||
}
|
||||
memcpy(packet_data, buf, len);
|
||||
|
||||
// Allocate ETCP_FRAGMENT from pool
|
||||
struct ETCP_FRAGMENT* pkt = (struct ETCP_FRAGMENT*)queue_entry_new_from_pool(tun->pool);
|
||||
if (!pkt) {
|
||||
DEBUG_ERROR(DEBUG_CATEGORY_TUN, "tun_inject_packet: failed to allocate ETCP_FRAGMENT");
|
||||
free(packet_data);
|
||||
tun->read_errors++;
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Initialize fragment
|
||||
pkt->seq = 0;
|
||||
pkt->timestamp = 0;
|
||||
pkt->ll.dgram = packet_data;
|
||||
pkt->ll.len = len;
|
||||
|
||||
// Add to output queue (packets from TUN to routing)
|
||||
if (queue_data_put(tun->output_queue, (struct ll_entry*)pkt, 0) != 0) {
|
||||
DEBUG_ERROR(DEBUG_CATEGORY_TUN, "tun_inject_packet: failed to add packet to output queue");
|
||||
free(packet_data);
|
||||
memory_pool_free(tun->pool, pkt);
|
||||
tun->read_errors++;
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Update statistics
|
||||
tun->bytes_read += len;
|
||||
tun->packets_read++;
|
||||
|
||||
DEBUG_DEBUG(DEBUG_CATEGORY_TUN, "Injected %zu bytes into TUN output queue %s", len, tun->ifname);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
ssize_t tun_read_packet(struct tun_if* tun, uint8_t* buf, size_t len) {
|
||||
if (!tun || !buf || len == 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
struct ETCP_FRAGMENT* pkt = (struct ETCP_FRAGMENT*)queue_data_get(tun->input_queue);
|
||||
if (!pkt) {
|
||||
return 0; // No packet available
|
||||
}
|
||||
|
||||
size_t pkt_len = pkt->ll.len;
|
||||
if (pkt_len > len) {
|
||||
DEBUG_WARN(DEBUG_CATEGORY_TUN, "tun_read_packet: buffer too small (%zu > %zu)",
|
||||
pkt_len, len);
|
||||
// Put packet back - cannot read partial
|
||||
// Note: This is a simplification; in real use, consider copying partial
|
||||
queue_data_put(tun->input_queue, (struct ll_entry*)pkt, 0);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Copy data to user buffer
|
||||
memcpy(buf, pkt->ll.dgram, pkt_len);
|
||||
|
||||
// Free packet
|
||||
free(pkt->ll.dgram);
|
||||
memory_pool_free(tun->pool, pkt);
|
||||
|
||||
// Update statistics
|
||||
tun->bytes_written += pkt_len;
|
||||
tun->packets_written++;
|
||||
|
||||
DEBUG_DEBUG(DEBUG_CATEGORY_TUN, "Read %zu bytes from TUN input queue %s", pkt_len, tun->ifname);
|
||||
|
||||
return pkt_len;
|
||||
}
|
||||
@@ -30,6 +30,7 @@ struct tun_if {
|
||||
struct memory_pool* pool; // Pool for ETCP_FRAGMENT structures
|
||||
struct ll_queue* output_queue; // Queue for incoming packets from TUN (to routing)
|
||||
struct ll_queue* input_queue; // Queue for outgoing packets to TUN (from routing)
|
||||
int test_mode; // Test mode flag: 1 = no real TUN, queues only
|
||||
// Statistics
|
||||
uint64_t bytes_read; // Bytes read from TUN
|
||||
uint64_t bytes_written; // Bytes written to TUN
|
||||
@@ -67,6 +68,98 @@ void tun_close(struct tun_if* tun);
|
||||
*/
|
||||
ssize_t tun_write(struct tun_if* tun, const uint8_t* buf, size_t len);
|
||||
|
||||
/**
|
||||
* @brief Get TUN input queue (for sending packets to TUN from routing)
|
||||
* @param tun TUN interface handle
|
||||
* @return Pointer to input queue, NULL if tun is NULL
|
||||
*
|
||||
* In normal mode: routing layer puts packets here, TUN reads and sends to interface
|
||||
* In test mode: tests can put packets here directly to simulate routing output
|
||||
*/
|
||||
struct ll_queue* tun_get_input_queue(struct tun_if* tun);
|
||||
|
||||
/**
|
||||
* @brief Get TUN output queue (for receiving packets from TUN to routing)
|
||||
* @param tun TUN interface handle
|
||||
* @return Pointer to output queue, NULL if tun is NULL
|
||||
*
|
||||
* In normal mode: TUN receives packets from interface and puts here for routing
|
||||
* In test mode: tests can read packets from here that were "sent" to TUN
|
||||
*/
|
||||
struct ll_queue* tun_get_output_queue(struct tun_if* tun);
|
||||
|
||||
/**
|
||||
* @brief Check if TUN interface is in test mode
|
||||
* @param tun TUN interface handle
|
||||
* @return 1 if test mode, 0 if normal mode, -1 if tun is NULL
|
||||
*/
|
||||
int tun_is_test_mode(struct tun_if* tun);
|
||||
|
||||
/**
|
||||
* @brief Write packet directly to TUN output queue (test mode helper)
|
||||
* @param tun TUN interface handle
|
||||
* @param buf Packet data
|
||||
* @param len Packet size
|
||||
* @return 0 on success, -1 on error
|
||||
*
|
||||
* This function simulates receiving a packet from the TUN interface.
|
||||
* The packet is placed in the output_queue where routing layer would normally find it.
|
||||
* Works in both test and normal modes.
|
||||
*/
|
||||
int tun_inject_packet(struct tun_if* tun, const uint8_t* buf, size_t len);
|
||||
|
||||
/**
|
||||
* @brief Read packet directly from TUN input queue (test mode helper)
|
||||
* @param tun TUN interface handle
|
||||
* @param buf Output buffer for packet data
|
||||
* @param len Output buffer size
|
||||
* @return Number of bytes read, 0 if no packet available, -1 on error
|
||||
*
|
||||
* This function simulates what the TUN interface would normally do:
|
||||
* take a packet from input_queue and return it.
|
||||
* Works in both test and normal modes.
|
||||
*/
|
||||
ssize_t tun_read_packet(struct tun_if* tun, uint8_t* buf, size_t len);
|
||||
|
||||
/**
|
||||
* @brief Test mode usage example and documentation
|
||||
*
|
||||
* To use TUN in test mode, set tun_test_mode=1 in the [global] section
|
||||
* of the configuration file:
|
||||
*
|
||||
* [global]
|
||||
* tun_test_mode=1
|
||||
* tun_ip=10.0.0.1/24
|
||||
*
|
||||
* Example test code:
|
||||
*
|
||||
* // Initialize TUN in test mode
|
||||
* struct tun_if* tun = tun_init(ua, config);
|
||||
* if (!tun || !tun_is_test_mode(tun)) {
|
||||
* // handle error
|
||||
* }
|
||||
*
|
||||
* // Simulate receiving packet from TUN (as if from network)
|
||||
* uint8_t packet[] = { ... }; // IP packet
|
||||
* tun_inject_packet(tun, packet, sizeof(packet));
|
||||
*
|
||||
* // Routing layer will find this packet in output_queue
|
||||
* struct ll_queue* out_q = tun_get_output_queue(tun);
|
||||
* struct ETCP_FRAGMENT* pkt = queue_data_get(out_q);
|
||||
*
|
||||
* // Simulate sending packet to TUN (as if from routing)
|
||||
* struct ll_queue* in_q = tun_get_input_queue(tun);
|
||||
* // Put packet in input_queue, TUN will process it
|
||||
*
|
||||
* In test mode:
|
||||
* - No real TUN device is created
|
||||
* - No system calls to configure network interface
|
||||
* - No socket is registered with uasync
|
||||
* - Memory pool and queues are still created normally
|
||||
* - All statistics are tracked normally
|
||||
* - tun_write() still works (writes to platform, but no real interface)
|
||||
*/
|
||||
|
||||
// Platform-specific internal functions (implemented in tun_linux.c / tun_windows.c)
|
||||
int tun_platform_init(struct tun_if* tun, const char* ifname, const char* ip_str, int mtu);
|
||||
void tun_platform_cleanup(struct tun_if* tun);
|
||||
|
||||
@@ -146,6 +146,95 @@ struct UTUN_INSTANCE* utun_instance_create(struct UASYNC* ua, const char *config
|
||||
return instance;
|
||||
}
|
||||
|
||||
// Create instance from existing config structure (config ownership transfers to instance)
|
||||
struct UTUN_INSTANCE* utun_instance_create_from_config(struct UASYNC* ua, struct utun_config* config) {
|
||||
if (!config) {
|
||||
DEBUG_ERROR(DEBUG_CATEGORY_CONFIG, "utun_instance_create_from_config: NULL config");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct UTUN_INSTANCE *instance = calloc(1, sizeof(struct UTUN_INSTANCE));
|
||||
if (!instance) {
|
||||
DEBUG_ERROR(DEBUG_CATEGORY_MEMORY, "Failed to allocate UTUN_INSTANCE");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Initialize basic fields
|
||||
instance->running = 0;
|
||||
instance->ua = ua;
|
||||
instance->config = config; // Transfer ownership
|
||||
|
||||
// Set node_id from config
|
||||
instance->node_id = config->global.my_node_id;
|
||||
|
||||
// Set my keys
|
||||
if (sc_init_local_keys(&instance->my_keys, config->global.my_public_key_hex, config->global.my_private_key_hex) != SC_OK) {
|
||||
DEBUG_ERROR(DEBUG_CATEGORY_MEMORY, "Failed to initialize local keys");
|
||||
free(instance);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
instance->ack_pool = memory_pool_init(sizeof(struct ACK_PACKET));
|
||||
instance->data_pool = memory_pool_init(PACKET_DATA_SIZE);
|
||||
instance->pkt_pool = memory_pool_init(sizeof(struct ETCP_DGRAM) + PACKET_DATA_SIZE);
|
||||
|
||||
// Create routing module
|
||||
if (routing_create(instance) != 0) {
|
||||
DEBUG_ERROR(DEBUG_CATEGORY_MEMORY, "Failed to create routing module");
|
||||
free(instance);
|
||||
return NULL;
|
||||
}
|
||||
DEBUG_INFO(DEBUG_CATEGORY_ROUTING, "Routing module created");
|
||||
|
||||
// Add local subnets from config as static routes
|
||||
struct CFG_ROUTE_ENTRY* subnet = config->my_subnets;
|
||||
while (subnet) {
|
||||
struct ROUTE_ENTRY entry = {0};
|
||||
entry.network = subnet->ip.addr.v4.s_addr;
|
||||
entry.prefix_length = subnet->netmask;
|
||||
entry.next_hop = NULL;
|
||||
entry.type = ROUTE_TYPE_LOCAL;
|
||||
entry.flags = ROUTE_FLAG_ACTIVE | ROUTE_FLAG_VALIDATED;
|
||||
entry.metrics.bandwidth_kbps = UINT32_MAX;
|
||||
entry.metrics.latency_ms = 0;
|
||||
entry.metrics.packet_loss_rate = 0;
|
||||
entry.metrics.hop_count = 0;
|
||||
|
||||
if (route_table_insert(instance->rt, &entry)) {
|
||||
char ip_str[INET_ADDRSTRLEN];
|
||||
inet_ntop(AF_INET, &entry.network, ip_str, sizeof(ip_str));
|
||||
DEBUG_INFO(DEBUG_CATEGORY_ROUTING, "Added local route: %s/%d",
|
||||
ip_str, entry.prefix_length);
|
||||
}
|
||||
|
||||
subnet = subnet->next;
|
||||
}
|
||||
|
||||
// Initialize TUN device if enabled
|
||||
if (g_tun_init_enabled) {
|
||||
instance->tun = tun_init(ua, config);
|
||||
if (!instance->tun) {
|
||||
DEBUG_ERROR(DEBUG_CATEGORY_TUN, "Failed to initialize TUN device");
|
||||
free(instance);
|
||||
return NULL;
|
||||
}
|
||||
DEBUG_INFO(DEBUG_CATEGORY_TUN, "TUN interface initialized: %s", instance->tun->ifname);
|
||||
} else {
|
||||
DEBUG_INFO(DEBUG_CATEGORY_TUN, "TUN initialization disabled - skipping TUN device setup");
|
||||
instance->tun = NULL;
|
||||
}
|
||||
|
||||
// Initialize BGP module
|
||||
instance->bgp = route_bgp_init(instance);
|
||||
if (!instance->bgp) {
|
||||
DEBUG_ERROR(DEBUG_CATEGORY_BGP, "Failed to initialize BGP module");
|
||||
} else {
|
||||
DEBUG_INFO(DEBUG_CATEGORY_BGP, "BGP module initialized");
|
||||
}
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
// Destroy instance and cleanup resources
|
||||
void utun_instance_destroy(struct UTUN_INSTANCE *instance) {
|
||||
if (!instance) return;
|
||||
|
||||
@@ -57,6 +57,7 @@ struct UTUN_INSTANCE {
|
||||
|
||||
// Functions
|
||||
struct UTUN_INSTANCE* utun_instance_create(struct UASYNC* ua, const char* config_file);
|
||||
struct UTUN_INSTANCE* utun_instance_create_from_config(struct UASYNC* ua, struct utun_config* config);
|
||||
void utun_instance_destroy(struct UTUN_INSTANCE* instance);
|
||||
int utun_instance_init(struct UTUN_INSTANCE *instance);
|
||||
void utun_instance_run(struct UTUN_INSTANCE *instance);
|
||||
|
||||
Reference in new issue
Block a user