|
|
|
@ -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_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) { |
|
|
|
static void route_bgp_receive_cbk(struct ETCP_CONN* from_conn, struct ll_entry* entry) { |
|
|
|
if (!from_conn || !entry || entry->len < 2) { |
|
|
|
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) { |
|
|
|
} else if (subcmd == ROUTE_SUBCMD_PING_RESP) { |
|
|
|
route_ping_handle_resp(bgp, from_conn, data, entry->len); |
|
|
|
route_ping_handle_resp(bgp, from_conn, data, entry->len); |
|
|
|
} else if (subcmd == ROUTE_SUBCMD_NAT_INFO) { |
|
|
|
} else if (subcmd == ROUTE_SUBCMD_NAT_INFO) { |
|
|
|
if (entry->len >= sizeof(struct BGP_NAT_INFO) && bgp && bgp->local_node) { |
|
|
|
route_bgp_handle_nat_info(bgp, from_conn, data, entry->len); |
|
|
|
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); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} else if (subcmd == ROUTE_SUBCMD_NAT_CHECK_REQ) { |
|
|
|
} else if (subcmd == ROUTE_SUBCMD_NAT_CHECK_REQ) { |
|
|
|
if (entry->len >= sizeof(struct BGP_NAT_CHECK_REQ) && bgp) { |
|
|
|
route_bgp_handle_nat_check_req(bgp, from_conn, data, entry->len); |
|
|
|
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); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
queue_dgram_free(entry); |
|
|
|
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); |
|
|
|
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) { |
|
|
|
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; |
|
|
|
if (!conn) return; |
|
|
|
struct BGP_NAT_INFO* pkt = u_calloc(1, sizeof(struct BGP_NAT_INFO)); |
|
|
|
struct BGP_NAT_INFO* pkt = u_calloc(1, sizeof(struct BGP_NAT_INFO)); |
|
|
|
|