Add NAT detection with burst ping, test timing, fix port conflicts
- route_ping.c: burst mode - send next ping immediately on response - route_ping.h: add target_ipv4/target_port/pubkey to BGP_PING_REQUEST - test_nat_detection.c: add test for ping without embedded pubkey - test_etcp_simple_traffic.c: use dynamic ports + fix timebase units - Makefile.am: show test execution time in ms
This commit is contained in:
1 parent
31eb4a5d26
commit
7cdb84c7a2
5 files changed
+149
-81
No files matched your search
+43
-31
@@ -99,8 +99,14 @@ static void route_ping_cb(int success, uint16_t rtt, void* arg, uint64_t nonce,
|
||||
series->rtt_sum += rtt;
|
||||
}
|
||||
if (series->count_sent < series->count_total && series->req->reply_conn) {
|
||||
struct UTUN_INSTANCE* inst = series->req->reply_conn->instance;
|
||||
series->next_timer = uasync_set_timeout(inst->ua, series->interval_ms * 10, series, route_ping_next);
|
||||
if (success) {
|
||||
// Ответ получен — следующий пинг сразу (burst mode)
|
||||
route_ping_next(series);
|
||||
} else {
|
||||
// Таймаут — ждем interval_ms перед retry
|
||||
struct UTUN_INSTANCE* inst = series->req->reply_conn->instance;
|
||||
series->next_timer = uasync_set_timeout(inst->ua, series->interval_ms * 10, series, route_ping_next);
|
||||
}
|
||||
return;
|
||||
}
|
||||
// серия завершена
|
||||
@@ -236,7 +242,7 @@ int route_ping_send_req(struct ROUTE_BGP* bgp, struct ETCP_CONN* to_conn, uint64
|
||||
return -3;
|
||||
}
|
||||
e->dgram = (uint8_t*)req_pkt;
|
||||
e->len = sizeof(struct BGP_PING_REQUEST);
|
||||
e->len = offsetof(struct BGP_PING_REQUEST, target_ipv4);
|
||||
|
||||
int ret = etcp_send(to_conn, e);
|
||||
if (ret != 0) {
|
||||
@@ -275,8 +281,7 @@ int route_ping_send_req_addr(struct ROUTE_BGP* bgp, struct ETCP_CONN* to_conn, u
|
||||
DEBUG_ERROR(DEBUG_CATEGORY_BGP, "route_ping_send_req_addr: invalid args");
|
||||
return -1;
|
||||
}
|
||||
size_t extra = 6 + (pubkey ? SC_PUBKEY_SIZE : 0);
|
||||
size_t pkt_size = sizeof(struct BGP_PING_REQUEST) + extra;
|
||||
size_t pkt_size = pubkey ? sizeof(struct BGP_PING_REQUEST) : offsetof(struct BGP_PING_REQUEST, pubkey);
|
||||
struct BGP_PING_REQUEST* req_pkt = u_calloc(1, pkt_size);
|
||||
if (!req_pkt) {
|
||||
DEBUG_ERROR(DEBUG_CATEGORY_BGP, "route_ping_send_req_addr: alloc failed");
|
||||
@@ -289,16 +294,13 @@ int route_ping_send_req_addr(struct ROUTE_BGP* bgp, struct ETCP_CONN* to_conn, u
|
||||
req_pkt->count = count;
|
||||
req_pkt->interval_ms = interval_ms;
|
||||
req_pkt->timeout_ms = timeout_ms;
|
||||
|
||||
uint8_t* tail = (uint8_t*)req_pkt + sizeof(struct BGP_PING_REQUEST);
|
||||
tail[0] = (target_ip >> 24) & 0xFF;
|
||||
tail[1] = (target_ip >> 16) & 0xFF;
|
||||
tail[2] = (target_ip >> 8) & 0xFF;
|
||||
tail[3] = target_ip & 0xFF;
|
||||
tail[4] = (target_port >> 8) & 0xFF;
|
||||
tail[5] = target_port & 0xFF;
|
||||
req_pkt->target_ipv4[0] = (target_ip >> 24) & 0xFF;
|
||||
req_pkt->target_ipv4[1] = (target_ip >> 16) & 0xFF;
|
||||
req_pkt->target_ipv4[2] = (target_ip >> 8) & 0xFF;
|
||||
req_pkt->target_ipv4[3] = target_ip & 0xFF;
|
||||
req_pkt->target_port = target_port;
|
||||
if (pubkey) {
|
||||
memcpy(tail + 6, pubkey, SC_PUBKEY_SIZE);
|
||||
memcpy(req_pkt->pubkey, pubkey, SC_PUBKEY_SIZE);
|
||||
}
|
||||
|
||||
struct ll_entry* e = queue_entry_new(0);
|
||||
@@ -352,8 +354,10 @@ void route_ping_destroy_pending(struct ROUTE_BGP* bgp) {
|
||||
}
|
||||
|
||||
void route_ping_handle_req(struct ROUTE_BGP* bgp, struct ETCP_CONN* from_conn, const uint8_t* data, size_t len) {
|
||||
if (!bgp || !from_conn || !data || len < sizeof(struct BGP_PING_REQUEST)) {
|
||||
DEBUG_ERROR(DEBUG_CATEGORY_BGP, "route_ping_handle_req: invalid args");
|
||||
const size_t base_len = offsetof(struct BGP_PING_REQUEST, target_ipv4);
|
||||
const size_t addr_len = offsetof(struct BGP_PING_REQUEST, pubkey);
|
||||
if (!bgp || !from_conn || !data || (len != base_len && len != addr_len && len != sizeof(struct BGP_PING_REQUEST))) {
|
||||
DEBUG_ERROR(DEBUG_CATEGORY_BGP, "route_ping_handle_req: invalid args len=%zu", len);
|
||||
return;
|
||||
}
|
||||
const struct BGP_PING_REQUEST* req_pkt = (const struct BGP_PING_REQUEST*)data;
|
||||
@@ -367,29 +371,34 @@ void route_ping_handle_req(struct ROUTE_BGP* bgp, struct ETCP_CONN* from_conn, c
|
||||
struct NODEINFO_Q* target = NULL;
|
||||
|
||||
const uint8_t* embedded_pubkey = NULL;
|
||||
if (len >= sizeof(struct BGP_PING_REQUEST) + 6) {
|
||||
// Custom target address provided (for NAT ping)
|
||||
const uint8_t* tail = data + sizeof(struct BGP_PING_REQUEST);
|
||||
custom_socket.addr[0] = tail[0];
|
||||
custom_socket.addr[1] = tail[1];
|
||||
custom_socket.addr[2] = tail[2];
|
||||
custom_socket.addr[3] = tail[3];
|
||||
custom_socket.port = (tail[4] << 8) | tail[5];
|
||||
if (len == sizeof(struct BGP_PING_REQUEST) || len == addr_len) {
|
||||
// Extended packet with custom target (with or without pubkey)
|
||||
custom_socket.addr[0] = req_pkt->target_ipv4[0];
|
||||
custom_socket.addr[1] = req_pkt->target_ipv4[1];
|
||||
custom_socket.addr[2] = req_pkt->target_ipv4[2];
|
||||
custom_socket.addr[3] = req_pkt->target_ipv4[3];
|
||||
custom_socket.port = req_pkt->target_port;
|
||||
custom_socket.type = 0;
|
||||
custom_socket.id = 0;
|
||||
sockets_v4 = &custom_socket;
|
||||
sock_count_v4 = 1;
|
||||
DEBUG_INFO(DEBUG_CATEGORY_BGP, "route_ping_handle_req: using custom target %d.%d.%d.%d:%u for node %016llx",
|
||||
tail[0], tail[1], tail[2], tail[3], custom_socket.port,
|
||||
(unsigned long long)req_pkt->node_id);
|
||||
// Check for embedded pubkey
|
||||
if (len >= sizeof(struct BGP_PING_REQUEST) + 6 + SC_PUBKEY_SIZE) {
|
||||
embedded_pubkey = tail + 6;
|
||||
req_pkt->target_ipv4[0], req_pkt->target_ipv4[1], req_pkt->target_ipv4[2], req_pkt->target_ipv4[3],
|
||||
req_pkt->target_port, (unsigned long long)req_pkt->node_id);
|
||||
// Check if embedded pubkey is non-zero (only when full packet length)
|
||||
if (len == sizeof(struct BGP_PING_REQUEST)) {
|
||||
int pubkey_zero = 1;
|
||||
for (int i = 0; i < SC_PUBKEY_SIZE; i++) {
|
||||
if (req_pkt->pubkey[i] != 0) { pubkey_zero = 0; break; }
|
||||
}
|
||||
if (!pubkey_zero) {
|
||||
embedded_pubkey = req_pkt->pubkey;
|
||||
}
|
||||
}
|
||||
// For custom target, we still need target node for pubkey lookup if not embedded
|
||||
target = route_bgp_get_node(bgp, req_pkt->node_id);
|
||||
} else {
|
||||
// No custom target - look up nodeinfo for advertised sockets
|
||||
} else if (len == base_len) {
|
||||
// Base packet without custom target - use nodeinfo sockets
|
||||
target = route_bgp_get_node(bgp, req_pkt->node_id);
|
||||
if (!target) {
|
||||
DEBUG_WARN(DEBUG_CATEGORY_BGP, "route_ping_handle_req: node %016llx not found",
|
||||
@@ -407,6 +416,9 @@ void route_ping_handle_req(struct ROUTE_BGP* bgp, struct ETCP_CONN* from_conn, c
|
||||
}
|
||||
sock_count_v4 = get_node_v4_sockets(target, &sockets_v4);
|
||||
sock_count_v6 = get_node_v6_sockets(target, &sockets_v6);
|
||||
} else {
|
||||
DEBUG_WARN(DEBUG_CATEGORY_BGP, "route_ping_handle_req: unexpected packet size %zu", len);
|
||||
return;
|
||||
}
|
||||
|
||||
if ((sock_count_v4 <= 0 || !sockets_v4) && (sock_count_v6 <= 0 || !sockets_v6)) {
|
||||
|
||||
+10
-7
@@ -9,13 +9,16 @@
|
||||
#define ROUTE_SUBCMD_PING_RESP 0x08
|
||||
|
||||
struct BGP_PING_REQUEST {
|
||||
uint8_t cmd; // ETCP_ID_ROUTE_ENTRY
|
||||
uint8_t subcmd; // ROUTE_SUBCMD_PING_REQ
|
||||
uint64_t request_id; // для корреляции
|
||||
uint64_t node_id; // целевой узел (должен быть известен в nodes)
|
||||
uint8_t count; // число пингов
|
||||
uint16_t interval_ms; // интервал между пингами
|
||||
uint16_t timeout_ms; // таймаут одного пинга
|
||||
uint8_t cmd; // ETCP_ID_ROUTE_ENTRY
|
||||
uint8_t subcmd; // ROUTE_SUBCMD_PING_REQ
|
||||
uint64_t request_id; // для корреляции
|
||||
uint64_t node_id; // целевой узел
|
||||
uint8_t count; // число пингов
|
||||
uint16_t interval_ms; // интервал между пингами
|
||||
uint16_t timeout_ms; // таймаут одного пинга
|
||||
uint8_t target_ipv4[4]; // custom target IP (0 = use nodeinfo sockets)
|
||||
uint16_t target_port; // custom target port
|
||||
uint8_t pubkey[SC_PUBKEY_SIZE]; // pubkey for encryption if target not in nodes
|
||||
} __attribute__((packed));
|
||||
|
||||
struct BGP_PING_RESPONSE {
|
||||
|
||||
Reference in new issue
Block a user