1
This commit is contained in:
1 parent
a1dd99c8d4
commit
58eea06f60
1 file changed
+104
-93
+104
-93
@@ -114,6 +114,8 @@ static void route_bgp_broadcast_withdraw(struct ROUTE_BGP* bgp, uint64_t node_id
|
||||
// ============================================================================
|
||||
|
||||
static void route_bgp_start_link_nat_check(struct ROUTE_BGP* bgp, struct ETCP_LINK* link);
|
||||
static void route_bgp_handle_nat_info(struct ROUTE_BGP* bgp, struct ETCP_CONN* from_conn, const uint8_t* data, size_t len);
|
||||
static void route_bgp_handle_nat_check_req(struct ROUTE_BGP* bgp, struct ETCP_CONN* from_conn, const uint8_t* data, size_t len);
|
||||
|
||||
static void route_bgp_receive_cbk(struct ETCP_CONN* from_conn, struct ll_entry* entry) {
|
||||
if (!from_conn || !entry || entry->len < 2) {
|
||||
@@ -158,100 +160,9 @@ static void route_bgp_receive_cbk(struct ETCP_CONN* from_conn, struct ll_entry*
|
||||
} else if (subcmd == ROUTE_SUBCMD_PING_RESP) {
|
||||
route_ping_handle_resp(bgp, from_conn, data, entry->len);
|
||||
} else if (subcmd == ROUTE_SUBCMD_NAT_INFO) {
|
||||
if (entry->len >= sizeof(struct BGP_NAT_INFO) && bgp && bgp->local_node) {
|
||||
const struct BGP_NAT_INFO* info = (const struct BGP_NAT_INFO*)data;
|
||||
uint32_t nat_ip = (info->nat_ip[0] << 24) | (info->nat_ip[1] << 16) |
|
||||
(info->nat_ip[2] << 8) | info->nat_ip[3];
|
||||
uint16_t nat_port = ((info->nat_port >> 8) & 0xFF) | ((info->nat_port & 0xFF) << 8);
|
||||
uint8_t socket_id = info->socket_id;
|
||||
// Update socket in local_node and ETCP_SOCKET
|
||||
uint8_t* dynamic = (uint8_t*)&bgp->local_node->node + sizeof(struct NODEINFO);
|
||||
dynamic += bgp->local_node->node.node_name_len;
|
||||
struct NODEINFO_IPV4_SOCKET* sockets = (struct NODEINFO_IPV4_SOCKET*)dynamic;
|
||||
for (int i = 0; i < bgp->local_node->node.local_v4_sockets; i++) {
|
||||
if (sockets[i].id == socket_id) {
|
||||
uint8_t old_type = sockets[i].type;
|
||||
uint32_t old_ip = (sockets[i].addr[0] << 24) | (sockets[i].addr[1] << 16) |
|
||||
(sockets[i].addr[2] << 8) | sockets[i].addr[3];
|
||||
uint16_t old_port = sockets[i].port;
|
||||
memcpy(sockets[i].addr, info->nat_ip, 4);
|
||||
sockets[i].port = nat_port;
|
||||
uint8_t verified_type;
|
||||
if (info->nat_type == NAT_TYPE_OPEN) {
|
||||
verified_type = NAT_VERIFIED_OPEN;
|
||||
} else if (info->nat_type == NAT_TYPE_RESTRICTED) {
|
||||
verified_type = NAT_VERIFIED_RESTRICTED;
|
||||
} else {
|
||||
verified_type = NAT_VERIFIED_UNKNOWN;
|
||||
}
|
||||
sockets[i].type = verified_type;
|
||||
// Update ETCP_SOCKET
|
||||
struct ETCP_SOCKET* es = bgp->instance->etcp_sockets;
|
||||
while (es) {
|
||||
if (es->sock_id == socket_id) {
|
||||
es->nat_type = verified_type;
|
||||
break;
|
||||
}
|
||||
es = es->next;
|
||||
}
|
||||
// Check if NAT actually changed - only update nodeinfo if changed
|
||||
if (old_ip != nat_ip || old_port != nat_port || old_type != verified_type) {
|
||||
bgp->local_node->dirty = 1;
|
||||
bgp->local_node->node.ver = (bgp->local_node->node.ver + 1) % 255 + 1;
|
||||
// Broadcast updated nodeinfo to all peers immediately
|
||||
if (bgp->senders_list) {
|
||||
struct ll_entry* se = bgp->senders_list->head;
|
||||
while (se) {
|
||||
struct ROUTE_BGP_CONN_ITEM* item = (struct ROUTE_BGP_CONN_ITEM*)se->data;
|
||||
if (item && item->conn) {
|
||||
route_bgp_send_nodeinfo(bgp->local_node, item->conn);
|
||||
}
|
||||
se = se->next;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
// Save nat_type to all links of this connection
|
||||
struct ETCP_LINK* l = from_conn->links;
|
||||
while (l) {
|
||||
l->nat_type = info->nat_type;
|
||||
l = l->next;
|
||||
}
|
||||
DEBUG_INFO(DEBUG_CATEGORY_BGP, "NAT_INFO from %s: socket_id=%u type=%s ip=%u.%u.%u.%u %s port=%u",
|
||||
from_conn->log_name, socket_id,
|
||||
info->nat_type == NAT_TYPE_OPEN ? "OPEN" : "RESTRICTED",
|
||||
(info->nat_ip[0]), (info->nat_ip[1]),
|
||||
(info->nat_ip[2]), (info->nat_ip[3]), ip_to_str(&info->nat_ip, AF_INET).str,
|
||||
(unsigned)nat_port);
|
||||
}
|
||||
route_bgp_handle_nat_info(bgp, from_conn, data, entry->len);
|
||||
} else if (subcmd == ROUTE_SUBCMD_NAT_CHECK_REQ) {
|
||||
if (entry->len >= sizeof(struct BGP_NAT_CHECK_REQ) && bgp) {
|
||||
const struct BGP_NAT_CHECK_REQ* req = (const struct BGP_NAT_CHECK_REQ*)data;
|
||||
uint8_t socket_id = req->socket_id;
|
||||
// Find link by remote_socket_id in the connection
|
||||
struct ETCP_LINK* target_link = NULL;
|
||||
struct ETCP_LINK* l = from_conn->links;
|
||||
while (l) {
|
||||
if (l->remote_socket_id == socket_id) {
|
||||
target_link = l;
|
||||
break;
|
||||
}
|
||||
l = l->next;
|
||||
}
|
||||
if (!target_link) {
|
||||
DEBUG_WARN(DEBUG_CATEGORY_BGP, "NAT_CHECK_REQ from %s: no link with remote_socket_id=%u",
|
||||
from_conn->log_name, socket_id);
|
||||
} else if (target_link->nat_check_status == NAT_CHECK_IN_PROGRESS) {
|
||||
DEBUG_DEBUG(DEBUG_CATEGORY_BGP, "NAT_CHECK_REQ from %s: check already in progress for socket_id=%u",
|
||||
from_conn->log_name, socket_id);
|
||||
} else {
|
||||
DEBUG_INFO(DEBUG_CATEGORY_BGP, "NAT_CHECK_REQ from %s: restarting NAT check for socket_id=%u",
|
||||
from_conn->log_name, socket_id);
|
||||
route_bgp_start_link_nat_check(bgp, target_link);
|
||||
}
|
||||
}
|
||||
route_bgp_handle_nat_check_req(bgp, from_conn, data, entry->len);
|
||||
}
|
||||
|
||||
queue_dgram_free(entry);
|
||||
@@ -958,6 +869,106 @@ static void route_bgp_handle_request_table(struct ROUTE_BGP* bgp, struct ETCP_CO
|
||||
route_bgp_add_to_senders(bgp, conn);
|
||||
}
|
||||
|
||||
static void route_bgp_handle_nat_info(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_NAT_INFO) || !bgp->local_node) return;
|
||||
|
||||
const struct BGP_NAT_INFO* info = (const struct BGP_NAT_INFO*)data;
|
||||
uint32_t nat_ip = (info->nat_ip[0] << 24) | (info->nat_ip[1] << 16) |
|
||||
(info->nat_ip[2] << 8) | info->nat_ip[3];
|
||||
uint16_t nat_port = ((info->nat_port >> 8) & 0xFF) | ((info->nat_port & 0xFF) << 8);
|
||||
uint8_t socket_id = info->socket_id;
|
||||
|
||||
uint8_t* dynamic = (uint8_t*)&bgp->local_node->node + sizeof(struct NODEINFO);
|
||||
dynamic += bgp->local_node->node.node_name_len;
|
||||
struct NODEINFO_IPV4_SOCKET* sockets = (struct NODEINFO_IPV4_SOCKET*)dynamic;
|
||||
for (int i = 0; i < bgp->local_node->node.local_v4_sockets; i++) {
|
||||
if (sockets[i].id == socket_id) {
|
||||
uint8_t old_type = sockets[i].type;
|
||||
uint32_t old_ip = (sockets[i].addr[0] << 24) | (sockets[i].addr[1] << 16) |
|
||||
(sockets[i].addr[2] << 8) | sockets[i].addr[3];
|
||||
uint16_t old_port = sockets[i].port;
|
||||
memcpy(sockets[i].addr, info->nat_ip, 4);
|
||||
sockets[i].port = nat_port;
|
||||
uint8_t verified_type;
|
||||
if (info->nat_type == NAT_TYPE_OPEN) {
|
||||
verified_type = NAT_VERIFIED_OPEN;
|
||||
} else if (info->nat_type == NAT_TYPE_RESTRICTED) {
|
||||
verified_type = NAT_VERIFIED_RESTRICTED;
|
||||
} else {
|
||||
verified_type = NAT_VERIFIED_UNKNOWN;
|
||||
}
|
||||
sockets[i].type = verified_type;
|
||||
|
||||
struct ETCP_SOCKET* es = bgp->instance->etcp_sockets;
|
||||
while (es) {
|
||||
if (es->sock_id == socket_id) {
|
||||
es->nat_type = verified_type;
|
||||
break;
|
||||
}
|
||||
es = es->next;
|
||||
}
|
||||
|
||||
if (old_ip != nat_ip || old_port != nat_port || old_type != verified_type) {
|
||||
bgp->local_node->dirty = 1;
|
||||
bgp->local_node->node.ver = (bgp->local_node->node.ver + 1) % 255 + 1;
|
||||
if (bgp->senders_list) {
|
||||
struct ll_entry* se = bgp->senders_list->head;
|
||||
while (se) {
|
||||
struct ROUTE_BGP_CONN_ITEM* item = (struct ROUTE_BGP_CONN_ITEM*)se->data;
|
||||
if (item && item->conn) {
|
||||
route_bgp_send_nodeinfo(bgp->local_node, item->conn);
|
||||
}
|
||||
se = se->next;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
struct ETCP_LINK* l = from_conn->links;
|
||||
while (l) {
|
||||
l->nat_type = info->nat_type;
|
||||
l = l->next;
|
||||
}
|
||||
|
||||
DEBUG_INFO(DEBUG_CATEGORY_BGP, "NAT_INFO from %s: socket_id=%u type=%s ip=%u.%u.%u.%u %s port=%u",
|
||||
from_conn->log_name, socket_id,
|
||||
info->nat_type == NAT_TYPE_OPEN ? "OPEN" : "RESTRICTED",
|
||||
(info->nat_ip[0]), (info->nat_ip[1]),
|
||||
(info->nat_ip[2]), (info->nat_ip[3]), ip_to_str(&info->nat_ip, AF_INET).str,
|
||||
(unsigned)nat_port);
|
||||
}
|
||||
|
||||
static void route_bgp_handle_nat_check_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_NAT_CHECK_REQ)) return;
|
||||
|
||||
const struct BGP_NAT_CHECK_REQ* req = (const struct BGP_NAT_CHECK_REQ*)data;
|
||||
uint8_t socket_id = req->socket_id;
|
||||
|
||||
struct ETCP_LINK* target_link = NULL;
|
||||
struct ETCP_LINK* l = from_conn->links;
|
||||
while (l) {
|
||||
if (l->remote_socket_id == socket_id) {
|
||||
target_link = l;
|
||||
break;
|
||||
}
|
||||
l = l->next;
|
||||
}
|
||||
|
||||
if (!target_link) {
|
||||
DEBUG_WARN(DEBUG_CATEGORY_BGP, "NAT_CHECK_REQ from %s: no link with remote_socket_id=%u",
|
||||
from_conn->log_name, socket_id);
|
||||
} else if (target_link->nat_check_status == NAT_CHECK_IN_PROGRESS) {
|
||||
DEBUG_DEBUG(DEBUG_CATEGORY_BGP, "NAT_CHECK_REQ from %s: check already in progress for socket_id=%u",
|
||||
from_conn->log_name, socket_id);
|
||||
} else {
|
||||
DEBUG_INFO(DEBUG_CATEGORY_BGP, "NAT_CHECK_REQ from %s: restarting NAT check for socket_id=%u",
|
||||
from_conn->log_name, socket_id);
|
||||
route_bgp_start_link_nat_check(bgp, target_link);
|
||||
}
|
||||
}
|
||||
|
||||
void route_bgp_send_nat_info(struct ETCP_CONN* conn, uint8_t socket_id, uint32_t nat_ip, uint16_t nat_port, uint8_t nat_type) {
|
||||
if (!conn) return;
|
||||
struct BGP_NAT_INFO* pkt = u_calloc(1, sizeof(struct BGP_NAT_INFO));
|
||||
|
||||
Reference in new issue
Block a user