|
|
|
|
@ -38,10 +38,7 @@ static struct ETCP_CONN* nat_check_find_third_node(struct NAT_DETECTION* nd, str
|
|
|
|
|
struct ll_entry* e = nd->inst->connections->head; |
|
|
|
|
while (e) { |
|
|
|
|
struct conn_queue_entry* ce = (struct conn_queue_entry*)e->data; |
|
|
|
|
if (ce->conn && ce->conn != exclude && ce->conn->links |
|
|
|
|
&& ce->conn->links->remote_only_local == 0 |
|
|
|
|
&& ce->conn->links->remote_type != CFG_SERVER_TYPE_PRIVATE |
|
|
|
|
&& ce->conn->links->remote_type != CFG_SERVER_TYPE_LOCAL) |
|
|
|
|
if (ce->conn && ce->conn != exclude && ce->conn->links) |
|
|
|
|
return ce->conn; |
|
|
|
|
e = e->next; |
|
|
|
|
} |
|
|
|
|
@ -91,8 +88,8 @@ static void nat_detection_start_link_check(struct NAT_DETECTION* nd, struct ETCP
|
|
|
|
|
ip_to_str(&target_ip, AF_INET).str); return; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
struct TOPO_GROUP* group = topo_groups_get_default(nd->inst->topo_groups); |
|
|
|
|
if (!group) return; |
|
|
|
|
struct TOPO_GROUP* group = nd->inst->topo_groups |
|
|
|
|
? topo_groups_get_default(nd->inst->topo_groups) : NULL; |
|
|
|
|
struct nat_check_arg* arg = u_calloc(1, sizeof(struct nat_check_arg)); |
|
|
|
|
if (!arg) return; |
|
|
|
|
arg->link = link; arg->nat_ip = target_ip; arg->nat_port = target_port; |
|
|
|
|
@ -117,8 +114,7 @@ static void nat_detection_start_link_check(struct NAT_DETECTION* nd, struct ETCP
|
|
|
|
|
static void nat_detection_handle_nat_info(struct NAT_DETECTION* nd, struct TOPO_GROUP* group, |
|
|
|
|
struct ETCP_CONN* from_conn, |
|
|
|
|
const uint8_t* data, size_t len) { |
|
|
|
|
if (!nd || !group || !from_conn || !data || len < sizeof(struct NATDET_MSG_NAT_INFO) |
|
|
|
|
|| !group->local_node || !group->local_node->node) return; |
|
|
|
|
if (!nd || !from_conn || !data || len < sizeof(struct NATDET_MSG_NAT_INFO)) return; |
|
|
|
|
|
|
|
|
|
const struct NATDET_MSG_NAT_INFO* info = (const struct NATDET_MSG_NAT_INFO*)data; |
|
|
|
|
uint32_t nat_ip = (info->nat_ip[0] << 24) | (info->nat_ip[1] << 16) |
|
|
|
|
@ -132,8 +128,8 @@ static void nat_detection_handle_nat_info(struct NAT_DETECTION* nd, struct TOPO_
|
|
|
|
|
else if (info->nat_type == NAT_TYPE_DIRECT) verified_type = NAT_VERIFIED_DIRECT; |
|
|
|
|
else verified_type = NAT_VERIFIED_UNKNOWN; |
|
|
|
|
|
|
|
|
|
int data_changed = 0; |
|
|
|
|
{ |
|
|
|
|
if (group && group->local_node && group->local_node->node) { |
|
|
|
|
int data_changed = 0; |
|
|
|
|
struct TOPO_SOCKMETA4* sm = group->local_node->node->v4_sock_meta; |
|
|
|
|
while (sm) { |
|
|
|
|
if (sm->id == socket_id) { |
|
|
|
|
@ -142,48 +138,81 @@ static void nat_detection_handle_nat_info(struct NAT_DETECTION* nd, struct TOPO_
|
|
|
|
|
} |
|
|
|
|
sm = sm->next; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
struct ETCP_SOCKET* es = group->instance->etcp_sockets; |
|
|
|
|
while (es) { |
|
|
|
|
if (es->sock_id == socket_id) { |
|
|
|
|
if (verified_type == NAT_VERIFIED_STRICT) { |
|
|
|
|
struct sockaddr_in* nat_sin = (struct sockaddr_in*)&es->nat_addr; |
|
|
|
|
nat_sin->sin_family = AF_INET; |
|
|
|
|
nat_sin->sin_addr.s_addr = nat_ip; |
|
|
|
|
nat_sin->sin_port = htons(nat_port); |
|
|
|
|
es->nat_type = verified_type; |
|
|
|
|
} else { |
|
|
|
|
struct ETCP_SOCKET* es = group->instance->etcp_sockets; |
|
|
|
|
while (es) { |
|
|
|
|
if (es->sock_id == socket_id) { |
|
|
|
|
if (verified_type == NAT_VERIFIED_STRICT) { |
|
|
|
|
struct sockaddr_in* nat_sin = (struct sockaddr_in*)&es->nat_addr; |
|
|
|
|
nat_sin->sin_family = AF_INET; |
|
|
|
|
nat_sin->sin_addr.s_addr = nat_ip; |
|
|
|
|
nat_sin->sin_port = htons(nat_port); |
|
|
|
|
es->nat_type = verified_type; |
|
|
|
|
} else { |
|
|
|
|
struct sockaddr_in* nat_sin = (struct sockaddr_in*)&es->nat_addr; |
|
|
|
|
uint32_t old_nat_ip = nat_sin->sin_addr.s_addr; |
|
|
|
|
uint16_t old_nat_port = ntohs(nat_sin->sin_port); |
|
|
|
|
nat_sin->sin_family = AF_INET; |
|
|
|
|
nat_sin->sin_addr.s_addr = nat_ip; |
|
|
|
|
nat_sin->sin_port = htons(nat_port); |
|
|
|
|
if (old_nat_ip != nat_ip || old_nat_port != nat_port) data_changed = 1; |
|
|
|
|
es->nat_type = verified_type; |
|
|
|
|
} |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
es = es->next; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (data_changed) { |
|
|
|
|
int prev_v4a = topo_list_count((struct _topo_head*)group->local_node->node->v4_addrs); |
|
|
|
|
topo_group_update_my_nodeinfo(group->instance, group); |
|
|
|
|
if (topo_list_count((struct _topo_head*)group->local_node->node->v4_addrs) != prev_v4a) { |
|
|
|
|
group->local_node->dirty = 1; |
|
|
|
|
group->local_node->node->ver = (group->local_node->node->ver % 255) + 1; |
|
|
|
|
group->local_node->last_ver = group->local_node->node->ver; |
|
|
|
|
} |
|
|
|
|
if (topo_list_count((struct _topo_head*)group->local_node->node->v4_addrs) == prev_v4a) { |
|
|
|
|
struct TOPO_ADDR4* a = group->local_node->node->v4_addrs; |
|
|
|
|
while (a) { |
|
|
|
|
if (a->type == TOPO_ADDR_INTERFACE && a->socket_id == socket_id) { |
|
|
|
|
uint32_t a_ip; memcpy(&a_ip, a->addr, 4); |
|
|
|
|
if (a_ip == nat_ip && a->port == nat_port) { |
|
|
|
|
a->type = TOPO_ADDR_NAT; a->socket_id = socket_id | 1; |
|
|
|
|
group->local_node->dirty = 1; |
|
|
|
|
group->local_node->node->ver = (group->local_node->node->ver % 255) + 1; |
|
|
|
|
group->local_node->last_ver = group->local_node->node->ver; |
|
|
|
|
DEBUG_INFO(DEBUG_CATEGORY_BGP, "NAT_INFO matched interface addr, updated entry type to NAT sock=%d", socket_id); |
|
|
|
|
} |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
a = a->next; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
if (group->local_node->dirty && group->senders_list) { |
|
|
|
|
struct ll_entry* se = group->senders_list->head; |
|
|
|
|
while (se) { |
|
|
|
|
struct TOPO_GROUP_CONN_ITEM* item = (struct TOPO_GROUP_CONN_ITEM*)se->data; |
|
|
|
|
if (item && item->conn) |
|
|
|
|
topo_group_send_nodeinfo(group, group->local_node, item->conn); |
|
|
|
|
se = se->next; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} else { |
|
|
|
|
struct ETCP_SOCKET* es = nd->inst->etcp_sockets; |
|
|
|
|
while (es) { |
|
|
|
|
if (es->sock_id == socket_id) { |
|
|
|
|
struct sockaddr_in* nat_sin = (struct sockaddr_in*)&es->nat_addr; |
|
|
|
|
uint32_t old_nat_ip = nat_sin->sin_addr.s_addr; |
|
|
|
|
uint16_t old_nat_port = ntohs(nat_sin->sin_port); |
|
|
|
|
nat_sin->sin_family = AF_INET; |
|
|
|
|
nat_sin->sin_addr.s_addr = nat_ip; |
|
|
|
|
nat_sin->sin_port = htons(nat_port); |
|
|
|
|
if (old_nat_ip != nat_ip || old_nat_port != nat_port) data_changed = 1; |
|
|
|
|
es->nat_type = verified_type; |
|
|
|
|
DEBUG_INFO(DEBUG_CATEGORY_BGP, "NAT_INFO socket=%s id=%d type=%d addr=%s:%u (no topo_group)", |
|
|
|
|
es->name, socket_id, verified_type, |
|
|
|
|
ip_to_str(&nat_ip, AF_INET).str, nat_port); |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
es = es->next; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (data_changed) { |
|
|
|
|
int prev_v4a = topo_list_count((struct _topo_head*)group->local_node->node->v4_addrs); |
|
|
|
|
topo_group_update_my_nodeinfo(group->instance, group); |
|
|
|
|
if (topo_list_count((struct _topo_head*)group->local_node->node->v4_addrs) != prev_v4a) { |
|
|
|
|
group->local_node->dirty = 1; |
|
|
|
|
group->local_node->node->ver = (group->local_node->node->ver % 255) + 1; |
|
|
|
|
group->local_node->last_ver = group->local_node->node->ver; |
|
|
|
|
} |
|
|
|
|
if (group->local_node->dirty && group->senders_list) { |
|
|
|
|
struct ll_entry* se = group->senders_list->head; |
|
|
|
|
while (se) { |
|
|
|
|
struct TOPO_GROUP_CONN_ITEM* item = (struct TOPO_GROUP_CONN_ITEM*)se->data; |
|
|
|
|
if (item && item->conn) |
|
|
|
|
topo_group_send_nodeinfo(group, group->local_node, item->conn); |
|
|
|
|
se = se->next; |
|
|
|
|
} |
|
|
|
|
es = es->next; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@ -194,7 +223,8 @@ static void nat_detection_handle_nat_info(struct NAT_DETECTION* nd, struct TOPO_
|
|
|
|
|
static void nat_detection_handle_nat_check_req(struct NAT_DETECTION* nd, struct TOPO_GROUP* group, |
|
|
|
|
struct ETCP_CONN* from_conn, |
|
|
|
|
const uint8_t* data, size_t len) { |
|
|
|
|
if (!nd || !group || !from_conn || !data || len < sizeof(struct NATDET_MSG_NAT_CHECK_REQ)) return; |
|
|
|
|
if (!nd || !from_conn || !data || len < sizeof(struct NATDET_MSG_NAT_CHECK_REQ)) return; |
|
|
|
|
(void)group; |
|
|
|
|
const struct NATDET_MSG_NAT_CHECK_REQ* req = (const struct NATDET_MSG_NAT_CHECK_REQ*)data; |
|
|
|
|
uint8_t socket_id = req->socket_id; |
|
|
|
|
struct ETCP_LINK* target_link = NULL; |
|
|
|
|
@ -256,20 +286,17 @@ static void nat_detection_receive_cbk(struct ETCP_CONN* from_conn, struct ll_ent
|
|
|
|
|
if (entry) { queue_dgram_free(entry); queue_entry_free(entry); } return; |
|
|
|
|
} |
|
|
|
|
struct UTUN_INSTANCE* instance = from_conn->instance; |
|
|
|
|
if (!instance || !instance->nat_det || !instance->topo_groups) { |
|
|
|
|
DEBUG_ERROR(DEBUG_CATEGORY_BGP, "invalid instance/nat_det/topo_groups"); |
|
|
|
|
queue_dgram_free(entry); queue_entry_free(entry); return; |
|
|
|
|
} |
|
|
|
|
struct TOPO_GROUP* group = topo_groups_get_default(instance->topo_groups); |
|
|
|
|
if (!group) { |
|
|
|
|
DEBUG_ERROR(DEBUG_CATEGORY_BGP, "no default group"); |
|
|
|
|
if (!instance || !instance->nat_det) { |
|
|
|
|
DEBUG_ERROR(DEBUG_CATEGORY_BGP, "invalid instance/nat_det"); |
|
|
|
|
queue_dgram_free(entry); queue_entry_free(entry); return; |
|
|
|
|
} |
|
|
|
|
struct TOPO_GROUP* group = instance->topo_groups |
|
|
|
|
? topo_groups_get_default(instance->topo_groups) : NULL; |
|
|
|
|
struct NAT_DETECTION* nd = instance->nat_det; |
|
|
|
|
uint8_t* data = entry->dgram; uint8_t subcmd = data[1]; |
|
|
|
|
|
|
|
|
|
DEBUG_INFO(DEBUG_CATEGORY_BGP, "NAT recv %s from %s len=%zu", |
|
|
|
|
nat_subcmd_name(subcmd), from_conn->log_name, entry->len); |
|
|
|
|
DEBUG_INFO(DEBUG_CATEGORY_BGP, "NAT recv %s from %s len=%zu group=%s", |
|
|
|
|
nat_subcmd_name(subcmd), from_conn->log_name, entry->len, group ? "yes" : "no"); |
|
|
|
|
|
|
|
|
|
if (subcmd == NATDET_SUBCMD_PING_REQ) |
|
|
|
|
route_ping_handle_req(nd, group, from_conn, data, entry->len); |
|
|
|
|
|