@ -112,6 +112,7 @@ static const char* group_subcmd_name(uint8_t subcmd) {
case TOPO_SUBCMD_NAT_INFO : return " NAT_INFO " ;
case TOPO_SUBCMD_NAT_CHECK_REQ : return " NAT_CHECK_REQ " ;
case TOPO_SUBCMD_TABLE_COMPLETE : return " TABLE_COMPLETE " ;
case TOPO_SUBCMD_ERR_GROUP_MISMATCH : return " ERR_GROUP_MISMATCH " ;
default : return " ? " ;
}
}
@ -166,6 +167,13 @@ static void topo_group_receive_cbk(struct ETCP_CONN* from_conn, struct ll_entry*
else if ( subcmd = = TOPO_SUBCMD_NAT_INFO ) topo_group_handle_nat_info ( group , from_conn , data , entry - > len ) ;
else if ( subcmd = = TOPO_SUBCMD_NAT_CHECK_REQ ) topo_group_handle_nat_check_req ( group , from_conn , data , entry - > len ) ;
else if ( subcmd = = TOPO_SUBCMD_TABLE_COMPLETE ) { etcp_set_routing_exchange_state ( from_conn , 3 ) ; DEBUG_INFO ( DEBUG_CATEGORY_BGP , " BGP initial sync complete with %s " , from_conn - > log_name ) ; }
else if ( subcmd = = TOPO_SUBCMD_ERR_GROUP_MISMATCH ) {
if ( entry - > len > = sizeof ( struct TOPOMSG_ERR_GROUP_MISMATCH ) ) {
struct TOPOMSG_ERR_GROUP_MISMATCH * err = ( struct TOPOMSG_ERR_GROUP_MISMATCH * ) data ;
DEBUG_ERROR ( DEBUG_CATEGORY_BGP , " Group type mismatch from %s: expected_type=%u received_flags=0x%02x " ,
from_conn - > log_name , err - > expected_type , err - > received_flags ) ;
}
}
queue_dgram_free ( entry ) ; queue_entry_free ( entry ) ;
}
@ -197,7 +205,7 @@ static void topo_group_etcp_conn_cbk(struct ETCP_CONN* conn, void* arg) {
}
}
static struct TOPO_GROUP * topo_group_create ( struct UTUN_INSTANCE * instance , uint64_t group_id ) {
static struct TOPO_GROUP * topo_group_create ( struct UTUN_INSTANCE * instance , uint64_t group_id , uint8_t group_type ) {
if ( ! instance ) { DEBUG_ERROR ( DEBUG_CATEGORY_BGP , " instance is NULL " ) ; return NULL ; }
DEBUG_INFO ( DEBUG_CATEGORY_BGP , " group_id=%016llx node_id=%016llx " , ( unsigned long long ) group_id , ( unsigned long long ) instance - > node_id ) ;
@ -206,6 +214,7 @@ static struct TOPO_GROUP* topo_group_create(struct UTUN_INSTANCE* instance, uint
struct TOPO_GROUP * group = ( struct TOPO_GROUP * ) qe ;
memset ( ( uint8_t * ) group + sizeof ( struct ll_entry ) , 0 , sizeof ( * group ) - sizeof ( struct ll_entry ) ) ;
group - > group_id = group_id ;
group - > group_type = group_type ;
group - > instance = instance ;
group - > next_ping_req_id = 1 ;
@ -262,7 +271,7 @@ struct TOPO_GROUPS* topo_groups_init(struct UTUN_INSTANCE* instance) {
instance - > topo_groups = g ;
struct TOPO_GROUP * default_group = topo_group_create ( instance , TOPO_GROUP_UTUN ) ;
struct TOPO_GROUP * default_group = topo_group_create ( instance , TOPO_GROUP_UTUN , TOPO_GROUP_TYPE_UTUN ) ;
if ( ! default_group ) {
memory_pool_destroy ( g - > v4_sock_meta_pool ) ; memory_pool_destroy ( g - > v4_addr_pool ) ;
memory_pool_destroy ( g - > v6_sock_meta_pool ) ; memory_pool_destroy ( g - > v6_addr_pool ) ;
@ -313,6 +322,16 @@ struct TOPO_GROUP* topo_groups_find(struct TOPO_GROUPS* g, uint64_t group_id) {
return e ? ( struct TOPO_GROUP * ) e : NULL ;
}
struct TOPO_GROUP * topo_groups_create_group ( struct TOPO_GROUPS * g , uint64_t group_id , uint8_t group_type ) {
if ( ! g | | ! g - > instance ) { DEBUG_ERROR ( DEBUG_CATEGORY_BGP , " invalid args " ) ; return NULL ; }
if ( topo_groups_find ( g , group_id ) ) { DEBUG_ERROR ( DEBUG_CATEGORY_BGP , " group_id=%016llx already exists " , ( unsigned long long ) group_id ) ; return NULL ; }
struct TOPO_GROUP * group = topo_group_create ( g - > instance , group_id , group_type ) ;
if ( ! group ) return NULL ;
queue_data_put_with_index ( g - > group_list , & group - > ll ) ;
DEBUG_INFO ( DEBUG_CATEGORY_BGP , " Group created: group_id=%016llx type=%u " , ( unsigned long long ) group_id , group_type ) ;
return group ;
}
void topo_group_set_nat_check_local ( struct TOPO_GROUP * group , int allow ) { if ( ! group ) return ; group - > allow_nat_check_local = allow ? 1 : 0 ; }
void topo_group_new_conn ( struct TOPO_GROUP * group , struct ETCP_CONN * conn ) {
@ -351,7 +370,7 @@ void topo_group_remove_conn(struct TOPO_GROUP* group, struct ETCP_CONN* conn) {
struct ll_entry * next = node_entry - > next ;
struct TOPO_NODEQ * nq = ( struct TOPO_NODEQ * ) node_entry ;
if ( topo_group_remove_path ( nq , conn ) = = 1 ) {
if ( rt ) route_delete ( rt , nq ) ;
if ( group - > group_type ! = TOPO_GROUP_TYPE_CHAT & & rt ) route_delete ( rt , nq ) ;
if ( conn - > instance & & conn - > instance - > control_srv ) control_server_notify_node_removed ( conn - > instance - > control_srv , nq - > hash_node_id ) ;
nq - > dirty = 1 ;
route_connectivity_cancel_node ( conn - > instance , nq ) ;
@ -478,11 +497,33 @@ void topo_group_start_link_nat_check(struct TOPO_GROUP* group, struct ETCP_LINK*
// ===== NODEINFO process =====
static void topo_group_send_err_group_mismatch ( struct TOPO_GROUP * group , struct ETCP_CONN * conn , uint8_t expected_type , uint8_t received_flags ) {
if ( ! group | | ! conn ) return ;
struct TOPOMSG_ERR_GROUP_MISMATCH * pkt = u_calloc ( 1 , sizeof ( struct TOPOMSG_ERR_GROUP_MISMATCH ) ) ;
if ( ! pkt ) return ;
pkt - > cmd = ETCP_ID_TOPO_ENTRY ; pkt - > subcmd = TOPO_SUBCMD_ERR_GROUP_MISMATCH ;
pkt - > expected_type = expected_type ; pkt - > received_flags = received_flags ;
struct ll_entry * e = queue_entry_new ( 0 ) ;
if ( ! e ) { u_free ( pkt ) ; return ; }
e - > dgram = ( uint8_t * ) pkt ; e - > len = sizeof ( struct TOPOMSG_ERR_GROUP_MISMATCH ) ;
if ( etcp_send ( conn , e ) ! = 0 ) { DEBUG_ERROR ( DEBUG_CATEGORY_BGP , " etcp_send ERR_GROUP_MISMATCH failed " ) ; u_free ( pkt ) ; queue_entry_free ( e ) ; }
}
int topo_group_process_nodeinfo ( struct TOPO_GROUP * group , struct ETCP_CONN * from , const uint8_t * data , size_t len ) {
if ( ! group | | ! from | | len < sizeof ( struct TOPOMSG_NODEINFO_PKT ) ) return - 1 ;
struct TOPOMSG_NODEINFO_PKT * pkt = ( struct TOPOMSG_NODEINFO_PKT * ) data ;
struct TOPOMSG_NODE * ni = & pkt - > node ;
// Проверка соответствия типа группы
uint8_t expected_flags = ( group - > group_type = = TOPO_GROUP_TYPE_CHAT ) ? 0 : TOPO_FLAG_SEND_SUBNETS ;
if ( ( ni - > flags & TOPO_FLAG_SEND_SUBNETS ) ! = expected_flags ) {
DEBUG_ERROR ( DEBUG_CATEGORY_BGP , " Group type mismatch with %s: expected_flags=0x%02x received_flags=0x%02x (local_type=%u) " ,
from - > log_name , expected_flags , ni - > flags , group - > group_type ) ;
topo_group_send_err_group_mismatch ( group , from , group - > group_type , ni - > flags ) ;
return - 1 ;
}
int dyn = topo_node_dyn_size ( ni ) ;
if ( ( size_t ) dyn + sizeof ( struct TOPOMSG_NODEINFO_PKT ) ! = len ) { DEBUG_WARN ( DEBUG_CATEGORY_BGP , " Incorrect packet size (%s) " , from - > log_name ) ; return - 1 ; }
@ -570,7 +611,7 @@ int topo_group_process_nodeinfo(struct TOPO_GROUP* group, struct ETCP_CONN* from
topo_group_remove_path_by_hop ( nodeinfo1 , from - > peer_node_id ) ;
topo_group_add_path ( nodeinfo1 , from , hop_list , nodeinfo1 - > hop_count ) ;
if ( group - > instance - > rt ) route_insert ( group - > instance - > rt , nodeinfo1 ) ;
if ( group - > group_type ! = TOPO_GROUP_TYPE_CHAT & & group - > instance - > rt ) route_insert ( group - > instance - > rt , nodeinfo1 ) ;
if ( node_id ! = group - > instance - > node_id ) topo_node_lmdb_put ( group , nodeinfo1 ) ;
if ( group - > instance - > control_srv ) control_server_notify_node_change ( group - > instance - > control_srv , nodeinfo1 ) ;
@ -609,7 +650,7 @@ int topo_group_process_withdraw(struct TOPO_GROUP* group, struct ETCP_CONN* send
if ( ! nq ) { DEBUG_INFO ( DEBUG_CATEGORY_BGP , " node not found " ) ; return 0 ; }
int ret = topo_group_remove_path_by_hop ( nq , wd_source ) ;
if ( ret = = 1 ) {
if ( group - > instance & & group - > instance - > rt ) route_delete ( group - > instance - > rt , nq ) ;
if ( group - > group_type ! = TOPO_GROUP_TYPE_CHAT & & group - > instance & & group - > instance - > rt ) route_delete ( group - > instance - > rt , nq ) ;
if ( group - > instance - > control_srv ) control_server_notify_node_removed ( group - > instance - > control_srv , node_id ) ;
nq - > dirty = 1 ;
route_connectivity_cancel_node ( group - > instance , nq ) ;