Browse Source

Add IPv6 support for sockets and connections

- Add get_node_v6_sockets() function in route_node
- Add local_defaultroute_ip6 field to ETCP_SOCKET
- Fix IPv6 address logging in bind, init, new connection
- Fix socket lookup for IPv6 in init_connections
- Fix route_ping_handle_req to support both v4 and v6 sockets
congestion
Evgeny 6 months ago
parent
commit
09195b2f61
  1. 36
      src/etcp_connections.c
  2. 1
      src/etcp_connections.h
  3. 18
      src/route_node.c
  4. 9
      src/route_node.h
  5. 108
      src/route_ping.c

36
src/etcp_connections.c

@ -115,6 +115,9 @@ static void etcp_link_send_init(struct ETCP_LINK* link, uint8_t reset) {
if (link->remote_addr.ss_family == AF_INET) { if (link->remote_addr.ss_family == AF_INET) {
struct sockaddr_in* sin = (struct sockaddr_in*)&link->remote_addr; struct sockaddr_in* sin = (struct sockaddr_in*)&link->remote_addr;
DEBUG_INFO(DEBUG_CATEGORY_ETCP, "[ETCP] INIT sending to %s:%d, link=%p, rst_req=%d", ip_to_str(&sin->sin_addr, AF_INET).str, ntohs(sin->sin_port), link, reset); DEBUG_INFO(DEBUG_CATEGORY_ETCP, "[ETCP] INIT sending to %s:%d, link=%p, rst_req=%d", ip_to_str(&sin->sin_addr, AF_INET).str, ntohs(sin->sin_port), link, reset);
} else if (link->remote_addr.ss_family == AF_INET6) {
struct sockaddr_in6* sin6 = (struct sockaddr_in6*)&link->remote_addr;
DEBUG_INFO(DEBUG_CATEGORY_ETCP, "[ETCP] INIT sending to %s:%d, link=%p, rst_req=%d", ip_to_str(&sin6->sin6_addr, AF_INET6).str, ntohs(sin6->sin6_port), link, reset);
} }
etcp_encrypt_send(dgram); etcp_encrypt_send(dgram);
@ -518,15 +521,24 @@ struct ETCP_SOCKET* etcp_socket_add(struct UTUN_INSTANCE* instance, struct CFG_S
if (ip->ss_family == AF_INET) { if (ip->ss_family == AF_INET) {
struct sockaddr_in* sin = (struct sockaddr_in*)ip; struct sockaddr_in* sin = (struct sockaddr_in*)ip;
DEBUG_ERROR(DEBUG_CATEGORY_ETCP, "[ETCP] Failed to bind to %s:%d", ip_to_str(&sin->sin_addr, AF_INET).str, ntohs(sin->sin_port)); DEBUG_ERROR(DEBUG_CATEGORY_ETCP, "[ETCP] Failed to bind to %s:%d", ip_to_str(&sin->sin_addr, AF_INET).str, ntohs(sin->sin_port));
} else if (ip->ss_family == AF_INET6) {
struct sockaddr_in6* sin6 = (struct sockaddr_in6*)ip;
DEBUG_ERROR(DEBUG_CATEGORY_ETCP, "[ETCP] Failed to bind to %s:%d", ip_to_str(&sin6->sin6_addr, AF_INET6).str, ntohs(sin6->sin6_port));
} }
socket_close_wrapper(e_sock->fd); socket_close_wrapper(e_sock->fd);
u_free(e_sock); u_free(e_sock);
return NULL; return NULL;
} }
struct sockaddr_in* sin = (struct sockaddr_in*)ip; if (ip->ss_family == AF_INET) {
DEBUG_INFO(DEBUG_CATEGORY_ETCP, "[ETCP] Successfully bound socket to local address, family=%d %s:%d", ip->ss_family, ip_to_str(&sin->sin_addr, AF_INET).str, ntohs(sin->sin_port)); struct sockaddr_in* sin = (struct sockaddr_in*)ip;
DEBUG_INFO(DEBUG_CATEGORY_GENERAL, "Listen socket initialized: name=%s fd=%d addr=%s:%d", e_sock->name, e_sock->fd, ip_to_str(&sin->sin_addr, AF_INET).str, ntohs(sin->sin_port)); DEBUG_INFO(DEBUG_CATEGORY_ETCP, "[ETCP] Successfully bound socket to local address, family=AF_INET %s:%d", ip_to_str(&sin->sin_addr, AF_INET).str, ntohs(sin->sin_port));
DEBUG_INFO(DEBUG_CATEGORY_GENERAL, "Listen socket initialized: name=%s fd=%d addr=%s:%d", e_sock->name, e_sock->fd, ip_to_str(&sin->sin_addr, AF_INET).str, ntohs(sin->sin_port));
} else if (ip->ss_family == AF_INET6) {
struct sockaddr_in6* sin6 = (struct sockaddr_in6*)ip;
DEBUG_INFO(DEBUG_CATEGORY_ETCP, "[ETCP] Successfully bound socket to local address, family=AF_INET6 %s:%d", ip_to_str(&sin6->sin6_addr, AF_INET6).str, ntohs(sin6->sin6_port));
DEBUG_INFO(DEBUG_CATEGORY_GENERAL, "Listen socket initialized: name=%s fd=%d addr=%s:%d", e_sock->name, e_sock->fd, ip_to_str(&sin6->sin6_addr, AF_INET6).str, ntohs(sin6->sin6_port));
}
} }
e_sock->instance = instance; e_sock->instance = instance;
e_sock->errorcode = 0; e_sock->errorcode = 0;
@ -1235,7 +1247,7 @@ void etcp_connections_read_callback_socket(socket_t sock, void* arg) {
conn->peer_node_id=peer_id; conn->peer_node_id=peer_id;
etcp_update_log_name(conn); etcp_update_log_name(conn);
DEBUG_INFO(DEBUG_CATEGORY_GENERAL, "New connection received on socket %s: log_name=%s peer_id=%lu", e_sock->name, conn->log_name, (unsigned long)peer_id); DEBUG_INFO(DEBUG_CATEGORY_GENERAL, "New connection received on socket %s: log_name=%s peer_id=%lu", e_sock->name, conn->log_name, (unsigned long)peer_id);
DEBUG_DEBUG(DEBUG_CATEGORY_CONNECTION, "New connection from %s peer_id=%ld etcp=%p", ip_to_str(&((struct sockaddr_in *)&addr)->sin_addr.s_addr, addr.ss_family).str, peer_id, conn); DEBUG_DEBUG(DEBUG_CATEGORY_CONNECTION, "New connection from %s peer_id=%ld etcp=%p", ip_to_str(&addr, addr.ss_family).str, peer_id, conn);
conn->next = e_sock->instance->connections; conn->next = e_sock->instance->connections;
e_sock->instance->connections = conn; e_sock->instance->connections = conn;
e_sock->instance->connections_count++; e_sock->instance->connections_count++;
@ -1546,10 +1558,12 @@ int init_sockets(struct UTUN_INSTANCE* instance) {
struct ETCP_SOCKET* e_sock = etcp_socket_add(instance, server); struct ETCP_SOCKET* e_sock = etcp_socket_add(instance, server);
if (e_sock && default_ip != 0) { if (e_sock && default_ip != 0) {
struct in_addr addr;
addr.s_addr = default_ip;
DEBUG_INFO(DEBUG_CATEGORY_ETCP, "Server %s type %d ip=%s", server->name, server->type, ip_to_str(&addr, AF_INET).str);
e_sock->local_defaultroute_ip = default_ip; e_sock->local_defaultroute_ip = default_ip;
if (server->ip.ss_family == AF_INET) {
struct in_addr addr;
addr.s_addr = default_ip;
DEBUG_INFO(DEBUG_CATEGORY_ETCP, "Server %s type %d ip=%s", server->name, server->type, ip_to_str(&addr, AF_INET).str);
}
} }
if (!e_sock) { if (!e_sock) {
DEBUG_ERROR(DEBUG_CATEGORY_ETCP, "Failed to create socket for server %s", server->name); DEBUG_ERROR(DEBUG_CATEGORY_ETCP, "Failed to create socket for server %s", server->name);
@ -1669,6 +1683,14 @@ int init_connections(struct UTUN_INSTANCE* instance) {
e_sock = sock; e_sock = sock;
break; break;
} }
} else if (sock->local_addr.ss_family == AF_INET6) {
struct sockaddr_in6* sock_addr6 = (struct sockaddr_in6*)&sock->local_addr;
struct sockaddr_in6* srv_addr6 = (struct sockaddr_in6*)&local_server->ip;
if (memcmp(&sock_addr6->sin6_addr, &srv_addr6->sin6_addr, 16) == 0 &&
sock_addr6->sin6_port == srv_addr6->sin6_port) {
e_sock = sock;
break;
}
} }
} }
sock = sock->next; sock = sock->next;

1
src/etcp_connections.h

@ -69,6 +69,7 @@ struct ETCP_SOCKET {
void* socket_id; // Socket ID from uasync_add_socket void* socket_id; // Socket ID from uasync_add_socket
uint8_t type; // CFG_SERVER_TYPE_PUBLIC/NAT/PRIVATE uint8_t type; // CFG_SERVER_TYPE_PUBLIC/NAT/PRIVATE
uint32_t local_defaultroute_ip; // auto-detected IPv4 for public servers (network byte order) uint32_t local_defaultroute_ip; // auto-detected IPv4 for public servers (network byte order)
uint8_t local_defaultroute_ip6[16]; // auto-detected IPv6 for public servers
}; };
// ETCP Link - одно динамическое соединение (один путь) // ETCP Link - одно динамическое соединение (один путь)

18
src/route_node.c

@ -42,6 +42,24 @@ int get_node_v4_sockets(struct NODEINFO_Q *node, const struct NODEINFO_IPV4_SOCK
return (int)info->local_v4_sockets; return (int)info->local_v4_sockets;
} }
int get_node_v6_sockets(struct NODEINFO_Q *node, const struct NODEINFO_IPV6_SOCKET **out_sockets) {
if (!node || !out_sockets) {
return -1;
}
*out_sockets = NULL;
const struct NODEINFO *info = &node->node;
if (info->local_v6_sockets == 0) {
return 0;
}
const uint8_t *dynamic = (const uint8_t *)&node->node + sizeof(struct NODEINFO);
dynamic += info->node_name_len;
dynamic += info->local_v4_sockets * sizeof(struct NODEINFO_IPV4_SOCKET);
*out_sockets = (const struct NODEINFO_IPV6_SOCKET *)dynamic;
DEBUG_TRACE(DEBUG_CATEGORY_ROUTING, "get_node_v6_sockets: returned %u IPv6 sockets from node %p",
(unsigned)info->local_v6_sockets, (void*)node);
return (int)info->local_v6_sockets;
}
int get_node_routes(struct NODEINFO_Q *node, const struct NODEINFO_IPV4_SUBNET **out_subnets) { int get_node_routes(struct NODEINFO_Q *node, const struct NODEINFO_IPV4_SUBNET **out_subnets) {
if (!node || !out_subnets) { if (!node || !out_subnets) {
return -1; return -1;

9
src/route_node.h

@ -103,4 +103,13 @@ int get_node_routes(struct NODEINFO_Q *node, const struct NODEINFO_IPV4_SUBNET *
*/ */
int get_node_v4_sockets(struct NODEINFO_Q *node, const struct NODEINFO_IPV4_SOCKET **out_sockets); int get_node_v4_sockets(struct NODEINFO_Q *node, const struct NODEINFO_IPV4_SOCKET **out_sockets);
/**
* @brief Получает указатель на массив IPv6-сокетов узла.
*
* @param node Указатель на NODEINFO_Q
* @param out_sockets [out] указатель на первый элемент массива NODEINFO_IPV6_SOCKET
* @return количество сокетов (>= 0) или -1 при ошибке
*/
int get_node_v6_sockets(struct NODEINFO_Q *node, const struct NODEINFO_IPV6_SOCKET **out_sockets);
#endif // ROUTE_NODE_H #endif // ROUTE_NODE_H

108
src/route_ping.c

@ -296,10 +296,13 @@ void route_ping_handle_req(struct ROUTE_BGP* bgp, struct ETCP_CONN* from_conn, c
} }
return; return;
} }
const struct NODEINFO_IPV4_SOCKET* sockets; const struct NODEINFO_IPV4_SOCKET* sockets_v4 = NULL;
int sock_count = get_node_v4_sockets(target, &sockets); const struct NODEINFO_IPV6_SOCKET* sockets_v6 = NULL;
if (sock_count <= 0 || !sockets) { int sock_count_v4 = get_node_v4_sockets(target, &sockets_v4);
DEBUG_WARN(DEBUG_CATEGORY_BGP, "route_ping_handle_req: no IPv4 sockets for node %016llx", int sock_count_v6 = get_node_v6_sockets(target, &sockets_v6);
if ((sock_count_v4 <= 0 || !sockets_v4) && (sock_count_v6 <= 0 || !sockets_v6)) {
DEBUG_WARN(DEBUG_CATEGORY_BGP, "route_ping_handle_req: no sockets for node %016llx",
(unsigned long long)req_pkt->node_id); (unsigned long long)req_pkt->node_id);
struct route_ping_req* req = u_calloc(1, sizeof(struct route_ping_req)); struct route_ping_req* req = u_calloc(1, sizeof(struct route_ping_req));
if (req) { if (req) {
@ -311,15 +314,19 @@ void route_ping_handle_req(struct ROUTE_BGP* bgp, struct ETCP_CONN* from_conn, c
} }
return; return;
} }
// считаем подходящие локальные сокеты AF_INET
uint8_t local_count = 0; // считаем подходящие локальные сокеты (v4 + v6)
uint8_t local_v4_count = 0;
uint8_t local_v6_count = 0;
struct ETCP_SOCKET* ls = bgp->instance->etcp_sockets; struct ETCP_SOCKET* ls = bgp->instance->etcp_sockets;
while (ls) { while (ls) {
if (ls->local_addr.ss_family == AF_INET) local_count++; if (ls->local_addr.ss_family == AF_INET) local_v4_count++;
else if (ls->local_addr.ss_family == AF_INET6) local_v6_count++;
ls = ls->next; ls = ls->next;
} }
uint8_t local_count = local_v4_count + local_v6_count;
if (local_count == 0) { if (local_count == 0) {
DEBUG_WARN(DEBUG_CATEGORY_BGP, "route_ping_handle_req: no local IPv4 sockets"); DEBUG_WARN(DEBUG_CATEGORY_BGP, "route_ping_handle_req: no local sockets");
struct route_ping_req* req = u_calloc(1, sizeof(struct route_ping_req)); struct route_ping_req* req = u_calloc(1, sizeof(struct route_ping_req));
if (req) { if (req) {
req->reply_conn = from_conn; req->reply_conn = from_conn;
@ -340,47 +347,66 @@ void route_ping_handle_req(struct ROUTE_BGP* bgp, struct ETCP_CONN* from_conn, c
req->target_node = target; req->target_node = target;
req->timeout_ms = req_pkt->timeout_ms; req->timeout_ms = req_pkt->timeout_ms;
req->socket_count = local_count; req->socket_count = local_count;
// заполняем target_addr из первого сокета узла (можно расширить на все)
struct sockaddr_storage target_addr;
memset(&target_addr, 0, sizeof(target_addr));
struct sockaddr_in* sin = (struct sockaddr_in*)&target_addr;
sin->sin_family = AF_INET;
memcpy(&sin->sin_addr, sockets[0].addr, 4);
sin->sin_port = htons(sockets[0].port);
ls = bgp->instance->etcp_sockets; ls = bgp->instance->etcp_sockets;
uint8_t idx = 0; uint8_t idx = 0;
while (ls) { while (ls) {
struct sockaddr_storage target_addr;
memset(&target_addr, 0, sizeof(target_addr));
if (ls->local_addr.ss_family == AF_INET) { if (ls->local_addr.ss_family == AF_INET) {
req->sockets[idx].local_sock = ls; if (sock_count_v4 > 0 && sockets_v4) {
struct route_ping_series* series = u_calloc(1, sizeof(struct route_ping_series)); struct sockaddr_in* sin = (struct sockaddr_in*)&target_addr;
if (series) { sin->sin_family = AF_INET;
series->req = req; memcpy(&sin->sin_addr, sockets_v4[0].addr, 4);
series->sock_ctx = &req->sockets[idx]; sin->sin_port = htons(sockets_v4[0].port);
series->local_sock = ls; } else {
series->target_addr = target_addr; ls = ls->next;
memcpy(series->pubkey, target->node.public_key, SC_PUBKEY_SIZE); continue;
series->count_total = req_pkt->count; }
series->count_sent = 0; } else if (ls->local_addr.ss_family == AF_INET6) {
series->count_ok = 0; if (sock_count_v6 > 0 && sockets_v6) {
series->rtt_sum = 0; struct sockaddr_in6* sin6 = (struct sockaddr_in6*)&target_addr;
series->timeout_ms = req_pkt->timeout_ms; sin6->sin6_family = AF_INET6;
series->interval_ms = req_pkt->interval_ms; memcpy(&sin6->sin6_addr, sockets_v6[0].addr, 16);
int ret = etcp_send_ping_to_socket(bgp->instance, ls, target->node.public_key, sin6->sin6_port = htons(sockets_v6[0].port);
&target_addr, req_pkt->timeout_ms, route_ping_cb, series, NULL, 0);
if (ret != 0) {
// сразу считаем fail
series->sock_ctx->avg_rtt = req_pkt->timeout_ms * 10;
series->sock_ctx->count_sent = req_pkt->count;
req->completed_count++;
u_free(series);
}
} else { } else {
req->sockets[idx].avg_rtt = req_pkt->timeout_ms * 10; ls = ls->next;
req->sockets[idx].count_sent = req_pkt->count; continue;
}
} else {
ls = ls->next;
continue;
}
req->sockets[idx].local_sock = ls;
struct route_ping_series* series = u_calloc(1, sizeof(struct route_ping_series));
if (series) {
series->req = req;
series->sock_ctx = &req->sockets[idx];
series->local_sock = ls;
series->target_addr = target_addr;
memcpy(series->pubkey, target->node.public_key, SC_PUBKEY_SIZE);
series->count_total = req_pkt->count;
series->count_sent = 0;
series->count_ok = 0;
series->rtt_sum = 0;
series->timeout_ms = req_pkt->timeout_ms;
series->interval_ms = req_pkt->interval_ms;
int ret = etcp_send_ping_to_socket(bgp->instance, ls, target->node.public_key,
&target_addr, req_pkt->timeout_ms, route_ping_cb, series, NULL, 0);
if (ret != 0) {
series->sock_ctx->avg_rtt = req_pkt->timeout_ms * 10;
series->sock_ctx->count_sent = req_pkt->count;
req->completed_count++; req->completed_count++;
u_free(series);
} }
idx++; } else {
req->sockets[idx].avg_rtt = req_pkt->timeout_ms * 10;
req->sockets[idx].count_sent = req_pkt->count;
req->completed_count++;
} }
idx++;
ls = ls->next; ls = ls->next;
} }
if (req->completed_count >= req->socket_count) { if (req->completed_count >= req->socket_count) {

Loading…
Cancel
Save