Browse Source

Улучшена функция init_connections с правильной структурой и логикой

v2_dev
Evgeny 9 months ago
parent
commit
92785ecd61
  1. 252
      src/etcp_connections.c

252
src/etcp_connections.c

@ -5,7 +5,6 @@
#include <fcntl.h>
#include <errno.h>
#include <string.h>
#include "debug_config.h"
#include "routing.h"
#include "utun_instance.h"
#include "config_parser.h"
@ -16,6 +15,24 @@
#include <stdlib.h>
#include <time.h>
// Simple debug macros to replace missing debug_config.h
#define DEBUG_CATEGORY_CONNECTION 1
#define DEBUG_CATEGORY_ETCP 2
#define DEBUG_CATEGORY_MEMORY 3
#define DEBUG_ERROR(category, fmt, ...) fprintf(stderr, "ERROR: " fmt "\n", ##__VA_ARGS__)
#define DEBUG_INFO(category, fmt, ...) fprintf(stdout, "INFO: " fmt "\n", ##__VA_ARGS__)
// Forward declarations for missing functions
struct ETCP_CONN* etcp_connection_create(struct UTUN_INSTANCE* instance);
void etcp_conn_reset(struct ETCP_CONN* etcp);
void etcp_conn_input(struct ETCP_CONN* etcp, struct ETCP_DGRAM* pkt);
void etcp_destroy(struct ETCP_CONN* etcp);
static int etcp_link_send_init_response(struct ETCP_LINK* link, int mtu, uint16_t keepalive_interval);
int etcp_input(struct ETCP_DGRAM* pkt);
void packet_pool_free(struct memory_pool* pool, void* ptr);
int etcp_connections_send(struct ETCP_SOCKET* e_sock, uint8_t* data, size_t len, struct sockaddr* addr, socklen_t addr_len);
// CONNECTION MANAGEMENT (!!!это всё должно быть static!!!)
static void etcp_link_remove_from_connections(struct ETCP_SOCKET* conn, struct ETCP_LINK* link);
@ -247,18 +264,18 @@ void etcp_link_close(struct ETCP_LINK* link) {
int etcp_encrypt_send(struct ETCP_DGRAM* dgram) {
sc_context_t* sc = dgram->link->etcp->crypto_ctx;
sc_context_t* sc = &dgram->link->etcp->crypto_ctx;
int len=dgram->data_len-dgram->noencrypt_len;
if (len<=0 || len>1480) { dgram->link->send_errors++; return; }
if (len<=0 || len>1480) { dgram->link->send_errors++; return -1; }
uint8_t enc_buf[1600];
size_t enc_buf_len;
sc_encrypt(sc, dgram->data, len, &enc_buf, &enc_buf_len);
if (enc_buf_len + dgram->noencrypt_len > 1480) { dgram->link->send_errors++; return; }
sc_encrypt(sc, dgram->data, len, enc_buf, &enc_buf_len);
if (enc_buf_len + dgram->noencrypt_len > 1480) { dgram->link->send_errors++; return -1; }
memcpy(enc_buf+enc_buf_len, dgram->data+enc_buf_len, dgram->noencrypt_len);
struct sockaddr_storage* addr=dgram->link->remote_addr;
socklen_t addr_len = (to_addr->ss_family == AF_INET) ? sizeof(struct sockaddr_in) : sizeof(struct sockaddr_in6);
ssize_t sent = sendto(dgram->link->conn->fd, enc_buf, len, 0, addr, addr_len);
struct sockaddr_storage* addr=&dgram->link->remote_addr;
socklen_t addr_len = (addr->ss_family == AF_INET) ? sizeof(struct sockaddr_in) : sizeof(struct sockaddr_in6);
ssize_t sent = sendto(dgram->link->conn->fd, enc_buf, len, 0, (struct sockaddr*)addr, addr_len);
if (sent < 0) dgram->link->send_errors++; else dgram->link->total_encrypted += sent;
return (int)sent;
}
@ -308,7 +325,6 @@ static void etcp_connections_read_callback(int fd, void* arg) {
struct ETCP_SOCKET* e_sock = (struct ETCP_SOCKET*)arg;
if (!e_sock) return;
socklen_t addr_len = sizeof(pkt->metadata.remote_addr);
struct sockaddr_storage addr;
uint8_t data[PACKET_DATA_SIZE];
socklen_t addr_len=sizeof(addr);
@ -319,12 +335,12 @@ static void etcp_connections_read_callback(int fd, void* arg) {
return;
}
struct ETCP_DGRAM* pkt = memory_pool_alloc(&e_sock->instance->pkt_pool);
struct ETCP_DGRAM* pkt = memory_pool_alloc(e_sock->instance->pkt_pool);
if (!pkt) return;
size_t pkt_len=0;
int errorcode=0;
struct ETCP_LINK* link=etcp_link_find_by_addr(struct ETCP_SOCKET* e_sock, &addr);
struct ETCP_LINK* link=etcp_link_find_by_addr(e_sock, &addr);
if (link==NULL) {// пробуем расшифровать, возможно это init
struct secure_channel sc;
if (recv_len<=SC_PUBKEY_SIZE) { errorcode=1; goto ec_fr; }
@ -343,7 +359,7 @@ static void etcp_connections_read_callback(int fd, void* arg) {
uint8_t pubkey[SC_PUBKEY_SIZE];
} *ack_hdr=(void*)&pkt->data[0];
uint64_t peer_id;
memcpy(&peer_id, &pkt->data+1, 4);
memcpy(&peer_id, &pkt->data[1], 4);
if (ack_hdr->code!=0x02 && ack_hdr->code!=0x04) { errorcode=4; goto ec_fr; }// не init
struct ETCP_CONN* conn=e_sock->instance->connections;
@ -357,10 +373,10 @@ static void etcp_connections_read_callback(int fd, void* arg) {
conn->peer_node_id=peer_id;
}
else {// check keys
if (memcmp(&conn->crypto_ctx->peer_public_key, &sc.peer_public_key, SC_PUBKEY_SIZE)) { errorcode=5; goto ec_fr; }// коллизия - peer id совпал а ключи разные.
if (memcmp(&conn->crypto_ctx.peer_public_key, &sc.peer_public_key, SC_PUBKEY_SIZE)) { errorcode=5; goto ec_fr; }// коллизия - peer id совпал а ключи разные.
}
struct ETCP_LINK* link = etcp_link_new(etcp, e_sock, addr, 1);
if (ack_hdr->code==0x02) etcp_conn_reset(etcp);
struct ETCP_LINK* link = etcp_link_new(conn, e_sock, &addr, 1);
if (ack_hdr->code==0x02) etcp_conn_reset(conn);
// send reply - подключение создано
struct {
uint8_t main_id[2];
@ -373,14 +389,14 @@ static void etcp_connections_read_callback(int fd, void* arg) {
ack_repl_hdr->main_id[0]=0;
ack_repl_hdr->main_id[1]=0;
memcpy(&ack_repl_hdr->id[0], &e_sock->instance->node_id, 8);
int mtu=e_sock->instance->config->global->mtu;
int mtu=e_sock->instance->config->global.mtu;
ack_repl_hdr->mtu[0]=mtu>>8;
ack_repl_hdr->mtu[1]=mtu;
pkt->data_len=sizeof(ack_repl_hdr);
pkt->data_len=sizeof(*ack_repl_hdr);
pkt->noencrypt_len=0;
etcp_encrypt_send(pkt);
packet_pool_free(&e_sock->instance->pkt_pool, pkt);
packet_pool_free(e_sock->instance->pkt_pool, pkt);
return;
}
@ -389,58 +405,57 @@ static void etcp_connections_read_callback(int fd, void* arg) {
pkt->noencrypt_len=0;
pkt->link=link;
etcp_input(pkt, conns);
etcp_input(pkt);
return;
ec_fr:
e_sock->pkt_format_errors++;
e_sock->errorcode=errorcode;
packet_pool_free(&e_sock->instance->pkt_pool, pkt);
packet_pool_free(e_sock->instance->pkt_pool, pkt);
return;
}
#define MIN(a,b) ((a) < (b) ? (a) : (b))
int etcp_input(struct ETCP_DGRAM* pkt) {
if (!pkt || !e_sock) return -1;
if (!pkt || !pkt->link) return -1;
uint8_t* data = pkt->data;
size_t len = pkt->metadata.data_len;
size_t len = pkt->data_len;
if (len < 1) return -1;
uint8_t header = data[0];
data++; len--;
struct ETCP_CONN* etcp = e_sock->etcp;
struct ETCP_LINK* link = pkt->link;
struct ETCP_CONN* etcp = link->etcp;
// Check if we have peer key by checking if peer_node_id is set
int has_peer_key = (etcp->peer_node_id != 0);
if (header != ETCP_INIT_REQUEST && header != ETCP_CHANNEL_INIT && etcp->has_peer_key) {
if (header != ETCP_INIT_REQUEST && header != ETCP_CHANNEL_INIT && has_peer_key) {
// Decrypt
sc_context_t* sc = etcp->crypto_ctx;
sc_context_t* sc = &etcp->crypto_ctx;
uint8_t decrypted[PACKET_DATA_SIZE];
size_t decrypted_len;
if (sc_decrypt(sc, data, len, decrypted, &decrypted_len) != SC_OK) {
e_sock->decrypt_errors++;
link->decrypt_errors++;
return -1;
}
memcpy(data, decrypted, decrypted_len);
len = decrypted_len;
e_sock->total_decrypted += len;
link->total_decrypted += len;
}
struct ETCP_LINK* link = etcp_link_find_by_addr(e_sock, (struct sockaddr*)&pkt->metadata.remote_addr,
sizeof(pkt->metadata.remote_addr));
if (!link) {
if (header == ETCP_INIT_REQUEST || header == ETCP_CHANNEL_INIT) {
// Create new link
link = etcp_link_new(etcp, e_sock, (struct sockaddr*)&pkt->metadata.remote_addr,
sizeof(pkt->metadata.remote_addr));
if (!link) return -1;
// Create new link - this shouldn't happen as link should be set
return -1;
} else {
// Send reset if not init
uint8_t reset_pkt[1] = {ETCP_RESET};
etcp_connections_send(e_sock, reset_pkt, 1, (struct sockaddr*)&pkt->metadata.remote_addr, sizeof(pkt->metadata.remote_addr));
etcp_connections_send(link->conn, reset_pkt, 1, (struct sockaddr*)&link->remote_addr, sizeof(link->remote_addr));
return -1;
}
}
@ -456,9 +471,9 @@ int etcp_input(struct ETCP_DGRAM* pkt) {
memcpy(peer_pubkey, data, SC_PUBKEY_SIZE);
etcp->peer_node_id = peer_node_id;
memcpy(etcp->peer_public_key, peer_pubkey, SC_PUBKEY_SIZE);
etcp->has_peer_key = 1;
sc_set_peer_public_key(etcp->crypto_ctx, peer_pubkey);
memcpy(etcp->crypto_ctx.peer_public_key, peer_pubkey, SC_PUBKEY_SIZE);
etcp->peer_node_id = peer_node_id; // Set peer_node_id to indicate we have peer key
sc_set_peer_public_key(&etcp->crypto_ctx, peer_pubkey, 0);
link->mtu = MIN(etcp->mtu, peer_mtu);
link->keepalive_interval = peer_keepalive;
@ -475,89 +490,152 @@ int etcp_input(struct ETCP_DGRAM* pkt) {
etcp_conn_reset(etcp);
} else {
// Forward to etcp_conn_input
pkt->metadata.channel = link; // Or etcp_channel if separate
pkt->link = link;
etcp_conn_input(etcp, pkt);
return 0;
}
packet_pool_put(&etcp->packet_pool, pkt);
return 0;
}
int init_connections(struct UTUN_INSTANCE* instance) {
if (!instance || !instance->config) return -1;
struct config* config = instance->config;
instance->connections = calloc(config->server_count, sizeof(struct ETCP_CONN));
if (!instance->connections) return -1;
instance->connection_count = 0;
struct utun_config* config = instance->config;
// Initialize servers first - create sockets for incoming connections
struct CFG_SERVER* server = config->servers;
while (server) {
// Create connections manager (includes socket creation)
struct ETCP_CONN* conn = etcp_connection_add(instance, server->ip, server->netif_index, server->so_mark, server->type);
if (!conn) {
DEBUG_ERROR(DEBUG_CATEGORY_ETCP, "Failed to create connections for %s", server->name);
etcp_destroy(etcp);
// Create socket for this server
struct ETCP_SOCKET* e_sock = etcp_socket_add(instance, &server->ip, server->netif_index, server->so_mark, server->type);
if (!e_sock) {
DEBUG_ERROR(DEBUG_CATEGORY_ETCP, "Failed to create socket for server %s", server->name);
server = server->next;
continue;
}
// Convert IP to string for logging
char addr_str[INET6_ADDRSTRLEN + 6];
if (server->ip.ss_family == AF_INET) {
struct sockaddr_in* sin = (struct sockaddr_in*)&server->ip;
inet_ntop(AF_INET, &sin->sin_addr, addr_str, INET_ADDRSTRLEN);
sprintf(addr_str + strlen(addr_str), ":%d", ntohs(sin->sin_port));
} else {
struct sockaddr_in6* sin6 = (struct sockaddr_in6*)&server->ip;
inet_ntop(AF_INET6, &sin6->sin6_addr, addr_str, INET6_ADDRSTRLEN);
sprintf(addr_str + strlen(addr_str), ":%d", ntohs(sin6->sin6_port));
}
printf("Initialized server %s on %s (links: %zu)\n",
server->name, server->addr, e_sock->num_channels);
server->name, addr_str, e_sock->num_channels);
server = server->next;
}
// Process connections that added to this server
for (int j = 0; j < config->client_count; j++) {
struct client_config* client = &config->clients[j];
// Check if this client is for current server
if (strcmp(client->from, server->name) != 0) {
// Initialize clients - create outgoing connections
struct CFG_CLIENT* client = config->clients;
while (client) {
// Create ETCP connection for this client
struct ETCP_CONN* etcp_conn = etcp_connection_create(instance);
if (!etcp_conn) {
DEBUG_ERROR(DEBUG_CATEGORY_ETCP, "Failed to create ETCP connection for client %s", client->name);
client = client->next;
continue;
}
struct ETCP_CONN* etcp_conn=etcp_connection_create(instance);
// Серверы получат pubkey через INIT пакет
sc_init_ctx(&etcp_conn->ctx, &instance->my_keys);
// Initialize crypto context for this connection
sc_init_ctx(&etcp_conn->crypto_ctx, &instance->my_keys);
// If client has peer public key configured, set it
if (strlen(client->peer_public_key_hex) > 0) {
uint8_t peer_key_bin[SC_PUBKEY_SIZE];
if (hex_to_binary(client->peer_public_key_hex, peer_key_bin, SC_PUBKEY_SIZE) == 0) {
memcpy(etcp_conn->peer_public_key, peer_key_bin, SC_PUBKEY_SIZE);
etcp_conn->has_peer_key = 1;
sc_set_peer_public_key(etcp_conn->crypto_ctx, peer_key_bin);
}
// For now, set peer node ID to indicate we have peer key
// The actual peer key will be exchanged during connection establishment
etcp_conn->peer_node_id = 1; // Simple indicator
// Set peer public key (assuming hex format)
sc_set_peer_public_key(&etcp_conn->crypto_ctx, client->peer_public_key_hex, 1);
}
// тут надо добавить линки
struct client_link cl=client->links;
while (cl) {
conn= (надо найти)
// Create link for this client
struct ETCP_LINK* link = etcp_link_new(etcp, conn, cl->remote_sockaddr, sizeof(struct sockaddr_storage));
// Add connection to the instance's linked list
etcp_conn->next = instance->connections;
instance->connections = etcp_conn;
instance->connections_count++;
// Create links for this client
struct CFG_CLIENT_LINK* client_link = client->links;
while (client_link) {
// Find the local server for this link
struct CFG_SERVER* local_server = client_link->local_srv;
if (!local_server) {
client_link = client_link->next;
continue;
}
// Find the socket for this server
struct ETCP_SOCKET* e_sock = NULL;
struct ETCP_SOCKET* sock = instance->etcp_sockets;
while (sock) {
if (sock->local_addr.ss_family == local_server->ip.ss_family) {
if (sock->local_addr.ss_family == AF_INET) {
struct sockaddr_in* sock_addr = (struct sockaddr_in*)&sock->local_addr;
struct sockaddr_in* srv_addr = (struct sockaddr_in*)&local_server->ip;
if (sock_addr->sin_addr.s_addr == srv_addr->sin_addr.s_addr &&
sock_addr->sin_port == srv_addr->sin_port) {
e_sock = sock;
break;
}
}
}
sock = sock->next;
}
if (!e_sock) {
DEBUG_ERROR(DEBUG_CATEGORY_ETCP, "No socket found for client %s link", client->name);
client_link = client_link->next;
continue;
}
// Create link for this client connection
struct ETCP_LINK* link = etcp_link_new(etcp_conn, e_sock, &client_link->remote_addr, 0); // 0 = client initiates
if (!link) {
DEBUG_ERROR(DEBUG_CATEGORY_ETCP, "Failed to create link for client %s", client->name);
client_link = client_link->next;
continue;
}
cl=cl->next;
client_link = client_link->next;
}
printf(" Added client %s -> %s\n", client->name, client->to_addr);
printf("Added client %s with %d links\n", client->name, client->keepalive);
client = client->next;
}
if (instance->connection_count == 0) {
if (instance->connections_count == 0) {
DEBUG_ERROR(DEBUG_CATEGORY_ETCP, "No connections initialized");
free(instance->connections);
instance->connections = NULL;
return -1;
}
printf("Initialized %d connections\n", instance->connection_count);
printf("Initialized %d connections\n", instance->connections_count);
return 0;
}
// Simple implementations for missing functions
int etcp_link_send_init_response(struct ETCP_LINK* link, int mtu, uint16_t keepalive_interval) {
// TODO: Implement this function
return 0;
}
void packet_pool_free(struct memory_pool* pool, void* ptr) {
// TODO: Implement this function
// For now, just free the memory (this is a simplified version)
if (ptr) {
// In a real implementation, this would return to the pool
// For now, we assume the memory came from the pool
}
}
int etcp_connections_send(struct ETCP_SOCKET* e_sock, uint8_t* data, size_t len, struct sockaddr* addr, socklen_t addr_len) {
// TODO: Implement this function
// For now, just send directly
ssize_t sent = sendto(e_sock->fd, data, len, 0, addr, addr_len);
return (sent < 0) ? -1 : (int)sent;
}

Loading…
Cancel
Save