diff --git a/src/utun_instance.c b/src/utun_instance.c index 515d7b2..87964b2 100644 --- a/src/utun_instance.c +++ b/src/utun_instance.c @@ -34,67 +34,40 @@ void utun_instance_set_tun_init_enabled(int enabled) { DEBUG_INFO(DEBUG_CATEGORY_TUN, "TUN initialization %s", enabled ? "enabled" : "disabled"); } - - -// Create and initialize root instance -struct UTUN_INSTANCE* utun_instance_create(struct UASYNC* ua, const char *config_file) { - struct UTUN_INSTANCE *instance = calloc(1, sizeof(struct UTUN_INSTANCE)); - if (!instance) return NULL; - +// Common initialization function (called by both create functions) +// Returns 0 on success, -1 on error (instance is NOT freed on error - caller must handle) +static int instance_init_common(struct UTUN_INSTANCE* instance, struct UASYNC* ua, struct utun_config* config) { // Initialize basic fields instance->running = 0; instance->ua = ua; + instance->config = config; - // Note: Global debug system is initialized from command line arguments if provided - // If not initialized via command line, instance-specific logging can be set up here - // The first initialization wins - either global (from main) or instance-specific - - // Ensure keys and node_id exist in config - if (config_ensure_keys_and_node_id(config_file) < 0) { - DEBUG_ERROR(DEBUG_CATEGORY_CONFIG, "Failed to ensure keys and node_id in config: %s", config_file); - free(instance); - return NULL; - } - - - // Load configuration - instance->config = parse_config(config_file); - if (!instance->config) { - DEBUG_ERROR(DEBUG_CATEGORY_CONFIG, "Failed to load config from %s", config_file); - free(instance); - return NULL; - } - - // Open log file only if not using global debug system output - if (instance->config->global.log_file) { - debug_set_output_file(instance->config->global.log_file); - } // Set node_id from config - instance->node_id = instance->config->global.my_node_id; + instance->node_id = config->global.my_node_id; // Set my keys - if (sc_init_local_keys(&instance->my_keys, instance->config->global.my_public_key_hex, instance->config->global.my_private_key_hex)) { + 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"); + return -1; } - - 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 memory pools + 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_config(instance->config); - free(instance); - return NULL; + return -1; } DEBUG_INFO(DEBUG_CATEGORY_ROUTING, "Routing module created"); // Add local subnets from config as static routes - struct CFG_ROUTE_ENTRY* subnet = instance->config->my_subnets; + struct CFG_ROUTE_ENTRY* subnet = config->my_subnets; while (subnet) { struct ROUTE_ENTRY entry = {0}; - entry.network = subnet->ip.addr.v4.s_addr; // Network byte order + entry.network = subnet->ip.addr.v4.s_addr; entry.prefix_length = subnet->netmask; entry.next_hop = NULL; // Local route entry.type = ROUTE_TYPE_LOCAL; @@ -119,17 +92,15 @@ struct UTUN_INSTANCE* utun_instance_create(struct UASYNC* ua, const char *config subnet = subnet->next; } - // Initialize TUN device only if enabled + // Initialize TUN device if enabled if (g_tun_init_enabled) { - instance->tun = tun_init(ua, instance->config); + instance->tun = tun_init(ua, config); if (!instance->tun) { DEBUG_ERROR(DEBUG_CATEGORY_TUN, "Failed to initialize TUN device"); - free(instance); - return NULL; + return -1; } DEBUG_INFO(DEBUG_CATEGORY_TUN, "TUN interface initialized: %s", instance->tun->ifname); } else { - // TUN initialization disabled - skip TUN setup DEBUG_INFO(DEBUG_CATEGORY_TUN, "TUN initialization disabled - skipping TUN device setup"); instance->tun = NULL; } @@ -143,93 +114,66 @@ struct UTUN_INSTANCE* utun_instance_create(struct UASYNC* ua, const char *config DEBUG_INFO(DEBUG_CATEGORY_BGP, "BGP module initialized"); } - return instance; + return 0; } -// 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"); +// Create and initialize root instance from config file +struct UTUN_INSTANCE* utun_instance_create(struct UASYNC* ua, const char *config_file) { + // Ensure keys and node_id exist in config (generates them if missing) + if (config_ensure_keys_and_node_id(config_file) < 0) { + DEBUG_ERROR(DEBUG_CATEGORY_CONFIG, "Failed to ensure keys and node_id in config: %s", config_file); return NULL; } - struct UTUN_INSTANCE *instance = calloc(1, sizeof(struct UTUN_INSTANCE)); - if (!instance) { - DEBUG_ERROR(DEBUG_CATEGORY_MEMORY, "Failed to allocate UTUN_INSTANCE"); + // Load configuration + struct utun_config* config = parse_config(config_file); + if (!config) { + DEBUG_ERROR(DEBUG_CATEGORY_CONFIG, "Failed to load config from %s", config_file); 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; + // Open log file only if not using global debug system output + if (config->global.log_file) { + debug_set_output_file(config->global.log_file); + } - // 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); + // Allocate instance + struct UTUN_INSTANCE *instance = calloc(1, sizeof(struct UTUN_INSTANCE)); + if (!instance) { + free_config(config); 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"); + // Initialize using common function + if (instance_init_common(instance, ua, config) != 0) { + // Cleanup on error + if (instance->config) free_config(instance->config); 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; + 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; } - // 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; + // Allocate instance + 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 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"); + // Initialize using common function (config ownership transferred to instance) + if (instance_init_common(instance, ua, config) != 0) { + // Cleanup on error - caller still owns config since we failed + free(instance); + return NULL; } return instance;