Browse Source

Rewrite test_routing_mesh to use programmatic config creation

Replaced file-based config creation with direct struct population.
This eliminates temporary files and makes the test cleaner.

Key changes:
- Added helper functions for creating config structures
- Create CFG_SERVER, CFG_CLIENT, CFG_CLIENT_LINK programmatically
- Use utun_instance_create_from_config() instead of file-based creation
- No temp directories or file cleanup needed

The test now builds configs in memory using helper functions like
make_sockaddr(), create_server(), create_client(), etc.
nodeinfo-routing-update
Evgeny 8 months ago
parent
commit
1cc475e9b0
  1. 405
      tests/test_routing_mesh.c

405
tests/test_routing_mesh.c

@ -1,9 +1,10 @@
// test_routing_mesh.c - Test routing between 3 instances in mesh topology // test_routing_mesh.c - Test routing between 3 instances in mesh topology
// Based on test_etcp_two_instances.c approach - using config files // Uses programmatic config creation (no temp files)
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <arpa/inet.h>
#include "test_utils.h" #include "test_utils.h"
#include "../lib/platform_compat.h" #include "../lib/platform_compat.h"
#include "../src/etcp.h" #include "../src/etcp.h"
@ -27,10 +28,6 @@
#define KEY_B_PRIV "4813d31d28b7e9829247f488c6be7672f2bdf61b2508333128e386d1759afed2" #define KEY_B_PRIV "4813d31d28b7e9829247f488c6be7672f2bdf61b2508333128e386d1759afed2"
#define KEY_B_PUB "c594f33c91f3a2222795c2c110c527bf214ad1009197ce14556cb13df3c461b3c373bed8f205a8dd1fc0c364f90bf471d7c6f5db49564c33e4235d268569ac71" #define KEY_B_PUB "c594f33c91f3a2222795c2c110c527bf214ad1009197ce14556cb13df3c461b3c373bed8f205a8dd1fc0c364f90bf471d7c6f5db49564c33e4235d268569ac71"
// Instance C keys (need valid keys - generate them)
static char key_c_priv[65];
static char key_c_pub[129];
static struct UTUN_INSTANCE* inst_a = NULL; static struct UTUN_INSTANCE* inst_a = NULL;
static struct UTUN_INSTANCE* inst_b = NULL; static struct UTUN_INSTANCE* inst_b = NULL;
static struct UTUN_INSTANCE* inst_c = NULL; static struct UTUN_INSTANCE* inst_c = NULL;
@ -38,172 +35,222 @@ static struct UASYNC* ua = NULL;
static int test_phase = 0; static int test_phase = 0;
static void* timeout_id = NULL; static void* timeout_id = NULL;
static char temp_dir[] = "/tmp/utun_mesh_test_XXXXXX"; // Helper: fill sockaddr_storage from IP:port string
static char config_a[256], config_b[256], config_c[256]; static int make_sockaddr(const char* ip_port, struct sockaddr_storage* ss) {
char buf[64];
strncpy(buf, ip_port, sizeof(buf)-1);
buf[sizeof(buf)-1] = '\0';
char* colon = strrchr(buf, ':');
if (!colon) return -1;
*colon = '\0';
int port = atoi(colon + 1);
struct sockaddr_in* sin = (struct sockaddr_in*)ss;
sin->sin_family = AF_INET;
sin->sin_port = htons(port);
if (inet_pton(AF_INET, buf, &sin->sin_addr) != 1) return -1;
return 0;
}
// Config A: servers for B and C to connect to // Helper: create CFG_SERVER
static const char* config_a_content = static struct CFG_SERVER* create_server(const char* name, const char* ip_port, uint8_t type) {
"[global]\n" struct CFG_SERVER* srv = calloc(1, sizeof(struct CFG_SERVER));
"my_node_id=0xAAAAAAAAAAAAAAAA\n" if (!srv) return NULL;
"my_private_key=" KEY_A_PRIV "\n" strncpy(srv->name, name, MAX_CONN_NAME_LEN-1);
"my_public_key=" KEY_A_PUB "\n" if (make_sockaddr(ip_port, &srv->ip) < 0) {
"tun_ip=10.99.1.1/24\n" free(srv);
"tun_ifname=tun_a\n" return NULL;
"tun_test_mode=1\n" }
"\n" srv->type = type;
"[routing]\n" return srv;
"my_subnet=192.168.10.0/24\n" }
"my_subnet=192.168.11.0/24\n"
"\n"
"[server: b]\n"
"addr=127.0.0.1:9101\n"
"type=public\n"
"\n"
"[server: c]\n"
"addr=127.0.0.1:9102\n"
"type=public\n";
// Config B: servers for A and C to connect to // Helper: create CFG_CLIENT_LINK
static const char* config_b_content = static struct CFG_CLIENT_LINK* create_link(struct CFG_SERVER* local_srv, const char* remote_ip_port) {
"[global]\n" struct CFG_CLIENT_LINK* link = calloc(1, sizeof(struct CFG_CLIENT_LINK));
"my_node_id=0xBBBBBBBBBBBBBBBB\n" if (!link) return NULL;
"my_private_key=" KEY_B_PRIV "\n" link->local_srv = local_srv;
"my_public_key=" KEY_B_PUB "\n" strncpy(link->server_name, local_srv->name, MAX_CONN_NAME_LEN-1);
"tun_ip=10.99.2.1/24\n" if (make_sockaddr(remote_ip_port, &link->remote_addr) < 0) {
"tun_ifname=tun_b\n" free(link);
"tun_test_mode=1\n" return NULL;
"\n" }
"[routing]\n" return link;
"my_subnet=192.168.20.0/24\n" }
"my_subnet=192.168.21.0/24\n"
"\n"
"[server: a]\n"
"addr=127.0.0.1:9201\n"
"type=public\n"
"\n"
"[server: c]\n"
"addr=127.0.0.1:9202\n"
"type=public\n";
// Config C: servers for A and B to connect to // Helper: create CFG_CLIENT
static const char* config_c_content_template = static struct CFG_CLIENT* create_client(const char* name, const char* peer_key, int keepalive) {
"[global]\n" struct CFG_CLIENT* cli = calloc(1, sizeof(struct CFG_CLIENT));
"my_node_id=0xCCCCCCCCCCCCCCCC\n" if (!cli) return NULL;
"my_private_key=%s\n" strncpy(cli->name, name, MAX_CONN_NAME_LEN-1);
"my_public_key=%s\n" strncpy(cli->peer_public_key_hex, peer_key, MAX_KEY_LEN-1);
"tun_ip=10.99.3.1/24\n" cli->keepalive = keepalive;
"tun_ifname=tun_c\n" return cli;
"tun_test_mode=1\n" }
"\n"
"[routing]\n"
"my_subnet=192.168.30.0/24\n"
"my_subnet=192.168.31.0/24\n"
"\n"
"[server: a]\n"
"addr=127.0.0.1:9302\n"
"type=public\n"
"\n"
"[server: b]\n"
"addr=127.0.0.1:9303\n"
"type=public\n";
// Client sections to add to configs for mesh topology // Helper: add link to client
static const char* client_a_content = static void client_add_link(struct CFG_CLIENT* cli, struct CFG_CLIENT_LINK* link) {
"\n[client: to_b]\n" link->next = cli->links;
"keepalive=1\n" cli->links = link;
"peer_public_key=" KEY_B_PUB "\n" }
"link=b:127.0.0.1:9201\n"
"\n[client: to_c]\n"
"keepalive=1\n"
"peer_public_key=%s\n" // Will be filled with C's key
"link=c:127.0.0.1:9302\n";
static const char* client_b_content = // Helper: add server to list (at end to preserve order)
"\n[client: to_a]\n" static void add_server(struct utun_config* cfg, struct CFG_SERVER* srv) {
"keepalive=1\n" if (!cfg->servers) {
"peer_public_key=" KEY_A_PUB "\n" cfg->servers = srv;
"link=a:127.0.0.1:9101\n" } else {
"\n[client: to_c]\n" struct CFG_SERVER* tail = cfg->servers;
"keepalive=1\n" while (tail->next) tail = tail->next;
"peer_public_key=%s\n" // Will be filled with C's key tail->next = srv;
"link=c:127.0.0.1:9303\n"; }
}
// Helper: find server by name
static struct CFG_SERVER* find_server(struct utun_config* cfg, const char* name) {
struct CFG_SERVER* srv = cfg->servers;
while (srv) {
if (strcmp(srv->name, name) == 0) return srv;
srv = srv->next;
}
return NULL;
}
static const char* client_c_content_template = // Helper: add client to list
"\n[client: to_a]\n" static void add_client(struct utun_config* cfg, struct CFG_CLIENT* cli) {
"keepalive=1\n" cli->next = cfg->clients;
"peer_public_key=" KEY_A_PUB "\n" cfg->clients = cli;
"link=a:127.0.0.1:9102\n" }
"\n[client: to_b]\n"
"keepalive=1\n"
"peer_public_key=" KEY_B_PUB "\n"
"link=b:127.0.0.1:9202\n";
static int create_temp_configs(void) { // Helper: add subnet
if (test_mkdtemp(temp_dir) != 0) { static void add_subnet(struct CFG_ROUTE_ENTRY** list, const char* cidr) {
fprintf(stderr, "Failed to create temp directory\n"); struct CFG_ROUTE_ENTRY* entry = calloc(1, sizeof(struct CFG_ROUTE_ENTRY));
return -1; if (!entry) return;
char buf[32];
strncpy(buf, cidr, sizeof(buf)-1);
char* slash = strchr(buf, '/');
if (slash) {
*slash = '\0';
entry->netmask = atoi(slash + 1);
} }
entry->ip.family = AF_INET;
inet_pton(AF_INET, buf, &entry->ip.addr.v4);
entry->next = *list;
*list = entry;
}
// Create config for instance A
static struct utun_config* create_config_a(const char* key_c_pub) {
struct utun_config* cfg = calloc(1, sizeof(struct utun_config));
if (!cfg) return NULL;
snprintf(config_a, sizeof(config_a), "%s/a.conf", temp_dir); // Global settings
snprintf(config_b, sizeof(config_b), "%s/b.conf", temp_dir); strncpy(cfg->global.my_private_key_hex, KEY_A_PRIV, MAX_KEY_LEN-1);
snprintf(config_c, sizeof(config_c), "%s/c.conf", temp_dir); strncpy(cfg->global.my_public_key_hex, KEY_A_PUB, MAX_KEY_LEN-1);
cfg->global.my_node_id = 0xAAAAAAAAAAAAAAAAULL;
strncpy(cfg->global.tun_ifname, "tun_a", 15);
inet_pton(AF_INET, "10.99.1.1", &cfg->global.tun_ip.addr.v4);
cfg->global.tun_ip.family = AF_INET;
cfg->global.tun_test_mode = 1;
cfg->global.mtu = 1500;
// Generate keys for C // Servers (for others to connect to)
struct SC_MYKEYS keys_c; add_server(cfg, create_server("b", "127.0.0.1:9101", CFG_SERVER_TYPE_PUBLIC));
if (sc_generate_keypair(&keys_c) != SC_OK) { add_server(cfg, create_server("c", "127.0.0.1:9102", CFG_SERVER_TYPE_PUBLIC));
fprintf(stderr, "Failed to generate keys for C\n");
return -1;
}
// Convert to hex // Clients (to connect to others) - find server by name for correct mapping
const char* hex_chars = "0123456789abcdef"; struct CFG_CLIENT* cli_b = create_client("to_b", KEY_B_PUB, 1);
for (int i = 0; i < 32; i++) { client_add_link(cli_b, create_link(find_server(cfg, "b"), "127.0.0.1:9201")); // connect to B's server
key_c_priv[i*2] = hex_chars[(keys_c.private_key[i] >> 4) & 0xF]; add_client(cfg, cli_b);
key_c_priv[i*2+1] = hex_chars[keys_c.private_key[i] & 0xF];
}
key_c_priv[64] = '\0';
for (int i = 0; i < 64; i++) { struct CFG_CLIENT* cli_c = create_client("to_c", key_c_pub, 1);
key_c_pub[i*2] = hex_chars[(keys_c.public_key[i] >> 4) & 0xF]; client_add_link(cli_c, create_link(find_server(cfg, "c"), "127.0.0.1:9302")); // connect to C's server
key_c_pub[i*2+1] = hex_chars[keys_c.public_key[i] & 0xF]; add_client(cfg, cli_c);
}
key_c_pub[128] = '\0';
printf("Generated C keys:\n"); // Subnets
printf(" priv: %.16s...\n", key_c_priv); add_subnet(&cfg->my_subnets, "192.168.10.0/24");
printf(" pub: %.16s...\n", key_c_pub); add_subnet(&cfg->my_subnets, "192.168.11.0/24");
// Write config A with C's public key
FILE* f = fopen(config_a, "w");
if (!f) return -1;
fprintf(f, "%s", config_a_content);
fprintf(f, client_a_content, key_c_pub);
fclose(f);
// Write config B with C's public key
f = fopen(config_b, "w");
if (!f) return -1;
fprintf(f, "%s", config_b_content);
fprintf(f, client_b_content, key_c_pub);
fclose(f);
// Write config C with generated keys
char c_config[4096];
snprintf(c_config, sizeof(c_config), config_c_content_template, key_c_priv, key_c_pub);
f = fopen(config_c, "w");
if (!f) return -1;
fprintf(f, "%s", c_config);
fprintf(f, "%s", client_c_content_template);
fclose(f);
return 0; return cfg;
} }
static void cleanup_temp_configs(void) { // Create config for instance B
if (config_a[0]) unlink(config_a); static struct utun_config* create_config_b(const char* key_c_pub) {
if (config_b[0]) unlink(config_b); struct utun_config* cfg = calloc(1, sizeof(struct utun_config));
if (config_c[0]) unlink(config_c); if (!cfg) return NULL;
if (temp_dir[0]) rmdir(temp_dir);
// Global settings
strncpy(cfg->global.my_private_key_hex, KEY_B_PRIV, MAX_KEY_LEN-1);
strncpy(cfg->global.my_public_key_hex, KEY_B_PUB, MAX_KEY_LEN-1);
cfg->global.my_node_id = 0xBBBBBBBBBBBBBBBBULL;
strncpy(cfg->global.tun_ifname, "tun_b", 15);
inet_pton(AF_INET, "10.99.2.1", &cfg->global.tun_ip.addr.v4);
cfg->global.tun_ip.family = AF_INET;
cfg->global.tun_test_mode = 1;
cfg->global.mtu = 1500;
// Servers
add_server(cfg, create_server("a", "127.0.0.1:9201", CFG_SERVER_TYPE_PUBLIC));
add_server(cfg, create_server("c", "127.0.0.1:9202", CFG_SERVER_TYPE_PUBLIC));
// Clients - find server by name for correct mapping
struct CFG_CLIENT* cli_a = create_client("to_a", KEY_A_PUB, 1);
client_add_link(cli_a, create_link(find_server(cfg, "a"), "127.0.0.1:9101"));
add_client(cfg, cli_a);
struct CFG_CLIENT* cli_c = create_client("to_c", key_c_pub, 1);
client_add_link(cli_c, create_link(find_server(cfg, "c"), "127.0.0.1:9303"));
add_client(cfg, cli_c);
// Subnets
add_subnet(&cfg->my_subnets, "192.168.20.0/24");
add_subnet(&cfg->my_subnets, "192.168.21.0/24");
return cfg;
}
// Create config for instance C
static struct utun_config* create_config_c(const char* key_c_priv, const char* key_c_pub) {
struct utun_config* cfg = calloc(1, sizeof(struct utun_config));
if (!cfg) return NULL;
// Global settings
strncpy(cfg->global.my_private_key_hex, key_c_priv, MAX_KEY_LEN-1);
strncpy(cfg->global.my_public_key_hex, key_c_pub, MAX_KEY_LEN-1);
cfg->global.my_node_id = 0xCCCCCCCCCCCCCCCCULL;
strncpy(cfg->global.tun_ifname, "tun_c", 15);
inet_pton(AF_INET, "10.99.3.1", &cfg->global.tun_ip.addr.v4);
cfg->global.tun_ip.family = AF_INET;
cfg->global.tun_test_mode = 1;
cfg->global.mtu = 1500;
// Servers
add_server(cfg, create_server("a", "127.0.0.1:9302", CFG_SERVER_TYPE_PUBLIC));
add_server(cfg, create_server("b", "127.0.0.1:9303", CFG_SERVER_TYPE_PUBLIC));
// Clients - find server by name for correct mapping
struct CFG_CLIENT* cli_a = create_client("to_a", KEY_A_PUB, 1);
client_add_link(cli_a, create_link(find_server(cfg, "a"), "127.0.0.1:9102"));
add_client(cfg, cli_a);
struct CFG_CLIENT* cli_b = create_client("to_b", KEY_B_PUB, 1);
client_add_link(cli_b, create_link(find_server(cfg, "b"), "127.0.0.1:9202"));
add_client(cfg, cli_b);
// Subnets
add_subnet(&cfg->my_subnets, "192.168.30.0/24");
add_subnet(&cfg->my_subnets, "192.168.31.0/24");
return cfg;
}
// Free config (simplified - just free top level, rest will be cleaned on exit)
static void free_config_manual(struct utun_config* cfg) {
(void)cfg; // Config structures cleaned up by utun_instance_destroy
// Note: utun_instance_create_from_config makes copies of config data,
// so we don't need to keep the config structures after instance creation
} }
static int count_initialized_links(struct UTUN_INSTANCE* inst) { static int count_initialized_links(struct UTUN_INSTANCE* inst) {
@ -247,9 +294,41 @@ static void timeout_handler(void* arg) {
int main(void) { int main(void) {
printf("========================================\n"); printf("========================================\n");
printf(" Routing Mesh Test (3 instances)\n"); printf(" Routing Mesh Test (3 instances)\n");
printf(" (programmatic config, no temp files)\n");
printf("========================================\n\n"); printf("========================================\n\n");
if (create_temp_configs() != 0) { // Generate keys for C
struct SC_MYKEYS keys_c;
if (sc_generate_keypair(&keys_c) != SC_OK) {
fprintf(stderr, "Failed to generate keys for C\n");
return 1;
}
// Convert to hex
char key_c_priv[65], key_c_pub[129];
const char* hex_chars = "0123456789abcdef";
for (int i = 0; i < 32; i++) {
key_c_priv[i*2] = hex_chars[(keys_c.private_key[i] >> 4) & 0xF];
key_c_priv[i*2+1] = hex_chars[keys_c.private_key[i] & 0xF];
}
key_c_priv[64] = '\0';
for (int i = 0; i < 64; i++) {
key_c_pub[i*2] = hex_chars[(keys_c.public_key[i] >> 4) & 0xF];
key_c_pub[i*2+1] = hex_chars[keys_c.public_key[i] & 0xF];
}
key_c_pub[128] = '\0';
printf("Generated C keys:\n");
printf(" priv: %.16s...\n", key_c_priv);
printf(" pub: %.16s...\n\n", key_c_pub);
// Create configs programmatically
struct utun_config* cfg_a = create_config_a(key_c_pub);
struct utun_config* cfg_b = create_config_b(key_c_pub);
struct utun_config* cfg_c = create_config_c(key_c_priv, key_c_pub);
if (!cfg_a || !cfg_b || !cfg_c) {
fprintf(stderr, "Failed to create configs\n"); fprintf(stderr, "Failed to create configs\n");
return 1; return 1;
} }
@ -263,11 +342,11 @@ int main(void) {
return 1; return 1;
} }
printf("[INIT] Creating instances from config files...\n"); printf("[INIT] Creating instances from programmatic config...\n");
inst_a = utun_instance_create(ua, config_a); inst_a = utun_instance_create_from_config(ua, cfg_a);
inst_b = utun_instance_create(ua, config_b); inst_b = utun_instance_create_from_config(ua, cfg_b);
inst_c = utun_instance_create(ua, config_c); inst_c = utun_instance_create_from_config(ua, cfg_c);
if (!inst_a || !inst_b || !inst_c) { if (!inst_a || !inst_b || !inst_c) {
fprintf(stderr, "Failed to create instances\n"); fprintf(stderr, "Failed to create instances\n");
@ -302,7 +381,11 @@ int main(void) {
if (inst_b) utun_instance_destroy(inst_b); if (inst_b) utun_instance_destroy(inst_b);
if (inst_c) utun_instance_destroy(inst_c); if (inst_c) utun_instance_destroy(inst_c);
if (ua) uasync_destroy(ua, 0); if (ua) uasync_destroy(ua, 0);
cleanup_temp_configs();
// Free configs
free_config_manual(cfg_a);
free_config_manual(cfg_b);
free_config_manual(cfg_c);
if (test_phase == 1) { if (test_phase == 1) {
printf("\n✓ TEST PASSED\n"); printf("\n✓ TEST PASSED\n");

Loading…
Cancel
Save