@ -1,6 +1,6 @@
/**
* @ file topo_b gp . c
* @ brief BGP - like о б м е н т о п о л о г и е й у з л о в
* @ file topo_grou p . c
* @ brief BGP - like о б м е н т о п о л о г и е й у з л о в ( г р у п п ы )
*/
# include <stdlib.h>
# include <string.h>
@ -18,18 +18,21 @@
# include "topo_node.h"
# include "topo_node_lmdb.h"
# include "route_lib.h"
# include "topo_b gp.h"
# include "topo_grou p.h"
# include "route_ping.h"
# include "route_connectivity.h"
# include "control_server.h"
# define TOPO_GROUP_UTUN 0x8000000000000000ULL
// ============================================================================
// Вспомогательные функции
// ============================================================================
static void topo_b gp_send_table_request ( struct TOPO_B GP * b gp, struct ETCP_CONN * conn ) {
if ( ! b gp | | ! conn ) return ;
static void topo_grou p_send_table_request ( struct TOPO_GROU P * grou p , struct ETCP_CONN * conn ) {
if ( ! grou p | | ! conn ) return ;
DEBUG_INFO ( DEBUG_CATEGORY_BGP , " Sending table request to %s " , conn - > log_name ) ;
struct TOPOMSG_TABLE_REQ * req = u_calloc ( 1 , sizeof ( struct TOPOMSG_TABLE_REQ ) ) ;
if ( ! req ) return ;
@ -41,8 +44,8 @@ static void topo_bgp_send_table_request(struct TOPO_BGP* bgp, struct ETCP_CONN*
if ( etcp_send ( conn , e ) ! = 0 ) { u_free ( req ) ; queue_entry_free ( e ) ; }
}
static void topo_b gp_send_table_complete ( struct TOPO_B GP * b gp, struct ETCP_CONN * conn ) {
if ( ! b gp | | ! conn ) return ;
static void topo_grou p_send_table_complete ( struct TOPO_GROU P * grou p , struct ETCP_CONN * conn ) {
if ( ! grou p | | ! conn ) return ;
struct TOPOMSG_TABLE_REQ * req = u_calloc ( 1 , sizeof ( struct TOPOMSG_TABLE_REQ ) ) ;
if ( ! req ) return ;
req - > cmd = ETCP_ID_TOPO_ENTRY ;
@ -53,10 +56,10 @@ static void topo_bgp_send_table_complete(struct TOPO_BGP* bgp, struct ETCP_CONN*
if ( etcp_send ( conn , e ) ! = 0 ) { u_free ( req ) ; queue_entry_free ( e ) ; }
}
static void topo_b gp_add_to_senders ( struct TOPO_B GP * b gp, struct ETCP_CONN * conn ) ;
static bool topo_b gp_should_send_to ( const struct TOPO_NODEQ * nq , uint64_t target_id ) ;
static void topo_b gp_send_full_table ( struct TOPO_B GP * b gp, struct ETCP_CONN * conn ) ;
static void topo_b gp_handle_request_table ( struct TOPO_B GP * b gp, struct ETCP_CONN * conn ) ;
static void topo_grou p_add_to_senders ( struct TOPO_GROU P * grou p , struct ETCP_CONN * conn ) ;
static bool topo_grou p_should_send_to ( const struct TOPO_NODEQ * nq , uint64_t target_id ) ;
static void topo_grou p_send_full_table ( struct TOPO_GROU P * grou p , struct ETCP_CONN * conn ) ;
static void topo_grou p_handle_request_table ( struct TOPO_GROU P * grou p , struct ETCP_CONN * conn ) ;
static void nodeinfo_dump_log ( const uint8_t * data , size_t len ) {
if ( ! data | | len < sizeof ( struct TOPOMSG_NODEINFO_PKT ) ) return ;
@ -99,7 +102,7 @@ static char* nodeinfo_format(const uint8_t* data, size_t len) {
return buf ;
}
static const char * b gp_subcmd_name( uint8_t subcmd ) {
static const char * grou p_subcmd_name ( uint8_t subcmd ) {
switch ( subcmd ) {
case TOPO_SUBCMD_NODEINFO : return " NODEINFO " ;
case TOPO_SUBCMD_REQUEST_TABLE : return " REQ_TABLE " ;
@ -118,15 +121,15 @@ static const char* bgp_subcmd_name(uint8_t subcmd) {
// Broadcast / Withdraw
// ============================================================================
static void topo_b gp_broadcast_withdraw ( struct TOPO_B GP * b gp, uint64_t node_id , uint64_t wd_source , struct ETCP_CONN * exclude ) {
if ( ! b gp) { DEBUG_ERROR ( DEBUG_CATEGORY_BGP , " b gp is NULL" ) ; return ; }
static void topo_grou p_broadcast_withdraw ( struct TOPO_GROU P * grou p , uint64_t node_id , uint64_t wd_source , struct ETCP_CONN * exclude ) {
if ( ! grou p ) { DEBUG_ERROR ( DEBUG_CATEGORY_BGP , " grou p is NULL " ) ; return ; }
struct TOPOMSG_WITHDRAW_PKT * pkt = u_calloc ( 1 , sizeof ( struct TOPOMSG_WITHDRAW_PKT ) ) ;
if ( ! pkt ) return ;
pkt - > cmd = ETCP_ID_TOPO_ENTRY ; pkt - > subcmd = TOPO_SUBCMD_WITHDRAW ;
pkt - > node_id = node_id ; pkt - > wd_source = wd_source ;
struct ll_entry * e = b gp- > senders_list ? b gp- > senders_list - > head : NULL ;
struct ll_entry * e = grou p - > senders_list ? grou p - > senders_list - > head : NULL ;
while ( e ) {
struct TOPO_B GP_CONN_ITEM * item = ( struct TOPO_B GP_CONN_ITEM * ) e - > data ;
struct TOPO_GROU P_CONN_ITEM * item = ( struct TOPO_GROU P_CONN_ITEM * ) e - > data ;
if ( item & & item - > conn & & item - > conn ! = exclude ) {
struct ll_entry * copy = queue_entry_new ( 0 ) ;
if ( copy ) { copy - > dgram = u_malloc ( sizeof ( * pkt ) ) ; if ( copy - > dgram ) memcpy ( copy - > dgram , pkt , sizeof ( * pkt ) ) ; copy - > len = sizeof ( * pkt ) ; etcp_send ( item - > conn , copy ) ; }
@ -141,26 +144,27 @@ static void topo_bgp_broadcast_withdraw(struct TOPO_BGP* bgp, uint64_t node_id,
// Приём пакетов
// ============================================================================
static void topo_b gp_handle_nat_info ( struct TOPO_B GP * b gp, struct ETCP_CONN * from_conn , const uint8_t * data , size_t len ) ;
static void topo_b gp_handle_nat_check_req ( struct TOPO_B GP * b gp, struct ETCP_CONN * from_conn , const uint8_t * data , size_t len ) ;
static void topo_grou p_handle_nat_info ( struct TOPO_GROU P * grou p , struct ETCP_CONN * from_conn , const uint8_t * data , size_t len ) ;
static void topo_grou p_handle_nat_check_req ( struct TOPO_GROU P * grou p , struct ETCP_CONN * from_conn , const uint8_t * data , size_t len ) ;
static void topo_b gp_receive_cbk ( struct ETCP_CONN * from_conn , struct ll_entry * entry ) {
static void topo_grou p_receive_cbk ( struct ETCP_CONN * from_conn , struct ll_entry * entry ) {
if ( ! from_conn | | ! entry | | entry - > len < 2 ) { if ( entry ) { queue_dgram_free ( entry ) ; queue_entry_free ( entry ) ; } return ; }
struct UTUN_INSTANCE * instance = from_conn - > instance ;
if ( ! instance | | ! instance - > bgp ) { DEBUG_ERROR ( DEBUG_CATEGORY_BGP , " topo_bgp_receive_cbk: invalid instance/bgp " ) ; queue_dgram_free ( entry ) ; queue_entry_free ( entry ) ; return ; }
struct TOPO_BGP * bgp = instance - > bgp ;
if ( ! instance | | ! instance - > topo_groups ) { DEBUG_ERROR ( DEBUG_CATEGORY_BGP , " topo_group_receive_cbk: invalid instance/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 , " topo_group_receive_cbk: no default group " ) ; queue_dgram_free ( entry ) ; queue_entry_free ( entry ) ; return ; }
uint8_t * data = entry - > dgram ; uint8_t cmd = data [ 0 ] ; uint8_t subcmd = data [ 1 ] ;
if ( cmd ! = ETCP_ID_TOPO_ENTRY ) { queue_dgram_free ( entry ) ; queue_entry_free ( entry ) ; return ; }
DEBUG_INFO ( DEBUG_CATEGORY_BGP , " BGP recv %s from %s len=%zu " , b gp_subcmd_name( subcmd ) , from_conn - > log_name , entry - > len ) ;
DEBUG_INFO ( DEBUG_CATEGORY_BGP , " BGP recv %s from %s len=%zu " , grou p_subcmd_name ( subcmd ) , from_conn - > log_name , entry - > len ) ;
if ( subcmd = = TOPO_SUBCMD_NODEINFO ) { nodeinfo_dump_log ( data , entry - > len ) ; topo_b gp_process_nodeinfo ( b gp, from_conn , data , entry - > len ) ; }
else if ( subcmd = = TOPO_SUBCMD_WITHDRAW ) topo_b gp_process_withdraw ( b gp, from_conn , data , entry - > len ) ;
else if ( subcmd = = TOPO_SUBCMD_REQUEST_TABLE ) topo_b gp_handle_request_table ( b gp, from_conn ) ;
else if ( subcmd = = TOPO_SUBCMD_PING_REQ ) route_ping_handle_req ( b gp, from_conn , data , entry - > len ) ;
else if ( subcmd = = TOPO_SUBCMD_PING_RESP ) route_ping_handle_resp ( b gp, from_conn , data , entry - > len ) ;
else if ( subcmd = = TOPO_SUBCMD_NAT_INFO ) topo_b gp_handle_nat_info ( b gp, from_conn , data , entry - > len ) ;
else if ( subcmd = = TOPO_SUBCMD_NAT_CHECK_REQ ) topo_b gp_handle_nat_check_req ( b gp, from_conn , data , entry - > len ) ;
if ( subcmd = = TOPO_SUBCMD_NODEINFO ) { nodeinfo_dump_log ( data , entry - > len ) ; topo_grou p_process_nodeinfo ( grou p , from_conn , data , entry - > len ) ; }
else if ( subcmd = = TOPO_SUBCMD_WITHDRAW ) topo_grou p_process_withdraw ( grou p , from_conn , data , entry - > len ) ;
else if ( subcmd = = TOPO_SUBCMD_REQUEST_TABLE ) topo_grou p_handle_request_table ( grou p , from_conn ) ;
else if ( subcmd = = TOPO_SUBCMD_PING_REQ ) route_ping_handle_req ( grou p , from_conn , data , entry - > len ) ;
else if ( subcmd = = TOPO_SUBCMD_PING_RESP ) route_ping_handle_resp ( grou p , from_conn , data , entry - > len ) ;
else if ( subcmd = = TOPO_SUBCMD_NAT_INFO ) topo_grou p_handle_nat_info ( grou p , from_conn , data , entry - > len ) ;
else if ( subcmd = = TOPO_SUBCMD_NAT_CHECK_REQ ) topo_grou p_handle_nat_check_req ( grou p , 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 ) ; }
queue_dgram_free ( entry ) ; queue_entry_free ( entry ) ;
@ -171,143 +175,204 @@ static void topo_bgp_receive_cbk(struct ETCP_CONN* from_conn, struct ll_entry* e
// Init / Destroy / New / Remove conn
// ============================================================================
static void topo_bgp_on_conn_up ( struct ETCP_CONN * conn , void * arg ) {
( void ) arg ; if ( conn & & conn - > instance & & conn - > instance - > bgp ) { DEBUG_INFO ( DEBUG_CATEGORY_BGP , " BGP peer UP: %s peer=%016llx " , conn - > log_name , ( unsigned long long ) conn - > peer_node_id ) ; topo_bgp_new_conn ( conn ) ; }
static void topo_group_on_conn_up ( struct ETCP_CONN * conn , void * arg ) {
( void ) arg ;
if ( conn & & conn - > instance & & conn - > instance - > topo_groups ) {
struct TOPO_GROUP * group = topo_groups_get_default ( conn - > instance - > topo_groups ) ;
if ( group ) { DEBUG_INFO ( DEBUG_CATEGORY_BGP , " BGP peer UP: %s peer=%016llx " , conn - > log_name , ( unsigned long long ) conn - > peer_node_id ) ; topo_group_new_conn ( group , conn ) ; }
}
}
static void topo_bgp_on_conn_down ( struct ETCP_CONN * conn , void * arg ) {
( void ) arg ; if ( conn & & conn - > instance & & conn - > instance - > bgp ) { DEBUG_INFO ( DEBUG_CATEGORY_BGP , " BGP peer DOWN: %s peer=%016llx " , conn - > log_name , ( unsigned long long ) conn - > peer_node_id ) ; topo_bgp_remove_conn ( conn ) ; }
static void topo_group_on_conn_down ( struct ETCP_CONN * conn , void * arg ) {
( void ) arg ;
if ( conn & & conn - > instance & & conn - > instance - > topo_groups ) {
struct TOPO_GROUP * group = topo_groups_get_default ( conn - > instance - > topo_groups ) ;
if ( group ) { DEBUG_INFO ( DEBUG_CATEGORY_BGP , " BGP peer DOWN: %s peer=%016llx " , conn - > log_name , ( unsigned long long ) conn - > peer_node_id ) ; topo_group_remove_conn ( group , conn ) ; }
}
}
static void topo_bgp_etcp_conn_cbk ( struct ETCP_CONN * conn , void * arg ) {
( void ) arg ; if ( conn & & conn - > instance & & conn - > instance - > bgp ) { DEBUG_INFO ( DEBUG_CATEGORY_BGP , " BGP set callbacks: %s " , conn - > log_name ) ; etcp_conn_add_up_cbk ( conn , topo_bgp_on_conn_up , conn - > instance - > bgp ) ; etcp_conn_add_down_cbk ( conn , topo_bgp_on_conn_down , conn - > instance - > bgp ) ; }
static void topo_group_etcp_conn_cbk ( struct ETCP_CONN * conn , void * arg ) {
( void ) arg ;
if ( conn & & conn - > instance & & conn - > instance - > topo_groups ) {
struct TOPO_GROUP * group = topo_groups_get_default ( conn - > instance - > topo_groups ) ;
if ( group ) { DEBUG_INFO ( DEBUG_CATEGORY_BGP , " BGP set callbacks: %s " , conn - > log_name ) ; etcp_conn_add_up_cbk ( conn , topo_group_on_conn_up , group ) ; etcp_conn_add_down_cbk ( conn , topo_group_on_conn_down , group ) ; }
}
}
struct TOPO_BGP * topo_bgp_init ( struct UTUN_INSTANCE * instance ) {
if ( ! instance ) { DEBUG_ERROR ( DEBUG_CATEGORY_BGP , " topo_bgp_init: instance is NULL " ) ; return NULL ; }
DEBUG_INFO ( DEBUG_CATEGORY_BGP , " topo_bgp_init: node_id=%016llx " , ( unsigned long long ) instance - > node_id ) ;
static st ruct TOPO_GROU P * topo_group_create ( struct UTUN_INSTANCE * instance , uint64_t group_id ) {
if ( ! instance ) { DEBUG_ERROR ( DEBUG_CATEGORY_BGP , " topo_group_create : instance is NULL " ) ; return NULL ; }
DEBUG_INFO ( DEBUG_CATEGORY_BGP , " topo_group_create: group_id=%016llx node_id=%016llx " , ( unsigned long long ) group_id , ( unsigned long long ) instance - > node_id ) ;
struct TOPO_BGP * bgp = u_calloc ( 1 , sizeof ( struct TOPO_BGP ) ) ;
if ( ! bgp ) { DEBUG_ERROR ( DEBUG_CATEGORY_BGP , " topo_bgp_init: alloc failed " ) ; return NULL ; }
bgp - > instance = instance ;
bgp - > ping_pending = NULL ; bgp - > next_ping_req_id = 1 ;
bgp - > nodeinfo_env = NULL ; bgp - > nodeinfo_dbi = 0 ;
struct TOPO_GROUP * group = u_calloc ( 1 , sizeof ( struct TOPO_GROUP ) ) ;
if ( ! group ) { DEBUG_ERROR ( DEBUG_CATEGORY_BGP , " topo_group_create: alloc failed " ) ; return NULL ; }
group - > group_id = group_id ;
group - > instance = instance ;
group - > ping_pending = NULL ; group - > next_ping_req_id = 1 ;
group - > nodeinfo_env = NULL ; group - > nodeinfo_dbi = 0 ;
sc_derive_ed25519_pubkey ( instance - > my_keys . private_key , b gp- > ed25519_public_key ) ;
sc_derive_ed25519_pubkey ( instance - > my_keys . private_key , grou p - > ed25519_public_key ) ;
DEBUG_INFO ( DEBUG_CATEGORY_BGP , " Ed25519 pubkey derived from X25519 private key " ) ;
if ( instance - > config & & instance - > config - > global . db_path [ 0 ] ) topo_node_lmdb_init ( bgp , instance - > config - > global . db_path ) ;
if ( instance - > config & & instance - > config - > global . db_path [ 0 ] ) topo_node_lmdb_init ( group , instance - > config - > global . db_path ) ;
group - > nodes = queue_new ( instance - > ua , BGP_NODES_HASH_SIZE , offsetof ( struct TOPO_NODEQ , hash_node_id ) - sizeof ( struct ll_entry ) , 8 , " group_nodes " ) ;
if ( ! group - > nodes ) { u_free ( group ) ; DEBUG_ERROR ( DEBUG_CATEGORY_BGP , " topo_group_create: nodes queue creation failed " ) ; return NULL ; }
group - > senders_list = queue_new ( instance - > ua , 0 , 0 , 0 , " group_senders " ) ;
if ( ! group - > senders_list ) { queue_free ( group - > nodes ) ; u_free ( group ) ; DEBUG_ERROR ( DEBUG_CATEGORY_BGP , " topo_group_create: senders_list queue creation failed " ) ; return NULL ; }
group - > local_node = NULL ;
topo_group_update_my_nodeinfo ( instance , group ) ;
DEBUG_INFO ( DEBUG_CATEGORY_BGP , " TOPO group created: group_id=%016llx " , ( unsigned long long ) group_id ) ;
return group ;
}
static void topo_group_destroy ( struct TOPO_GROUP * group ) {
if ( ! group ) return ;
DEBUG_INFO ( DEBUG_CATEGORY_BGP , " topo_group_destroy: group_id=%016llx " , ( unsigned long long ) group - > group_id ) ;
struct ll_entry * e ;
while ( ( e = queue_data_get ( group - > senders_list ) ) ! = NULL ) queue_entry_free ( e ) ;
queue_free ( group - > senders_list ) ;
if ( group - > local_node ) { topo_node_free_lists ( group , group - > local_node ) ; u_free ( group - > local_node ) ; }
bgp - > nodes = queue_new ( instance - > ua , BGP_NODES_HASH_SIZE , offsetof ( struct TOPO_NODEQ , hash_node_id ) - sizeof ( struct ll_entry ) , 8 , " bgp_nodes " ) ;
if ( ! bgp - > nodes ) { u_free ( bgp ) ; DEBUG_ERROR ( DEBUG_CATEGORY_BGP , " topo_bgp_init: nodes queue creation failed " ) ; return NULL ; }
topo_node_lmdb_destroy ( group ) ;
bgp - > senders_list = queue_new ( instance - > ua , 0 , 0 , 0 , " BGP_senders " ) ;
if ( ! bgp - > senders_list ) { queue_free ( bgp - > nodes ) ; u_free ( bgp ) ; DEBUG_ERROR ( DEBUG_CATEGORY_BGP , " topo_bgp_init: senders_list queue creation failed " ) ; return NULL ; }
if ( group - > nodes ) queue_free ( group - > nodes ) ;
bgp - > v4_sock_meta_pool = memory_pool_init ( sizeof ( struct TOPO_SOCKMETA4 ) , " to_v4sock " ) ;
bgp - > v4_addr_pool = memory_pool_init ( sizeof ( struct TOPO_ADDR4 ) , " to_v4addr " ) ;
bgp - > v6_sock_meta_pool = memory_pool_init ( sizeof ( struct TOPO_SOCKMETA6 ) , " to_v6sock " ) ;
bgp - > v6_addr_pool = memory_pool_init ( sizeof ( struct TOPO_ADDR6 ) , " to_v6addr " ) ;
bgp - > v4_subnet_pool = memory_pool_init ( sizeof ( struct TOPO_SUBNET4 ) , " to_v4sub " ) ;
bgp - > v6_subnet_pool = memory_pool_init ( sizeof ( struct TOPO_SUBNET6 ) , " to_v6sub " ) ;
u_free ( group ) ;
}
struct TOPO_GROUPS * topo_groups_init ( struct UTUN_INSTANCE * instance ) {
if ( ! instance ) { DEBUG_ERROR ( DEBUG_CATEGORY_BGP , " topo_groups_init: instance is NULL " ) ; return NULL ; }
DEBUG_INFO ( DEBUG_CATEGORY_BGP , " topo_groups_init: node_id=%016llx " , ( unsigned long long ) instance - > node_id ) ;
struct TOPO_GROUPS * g = u_calloc ( 1 , sizeof ( struct TOPO_GROUPS ) ) ;
if ( ! g ) { DEBUG_ERROR ( DEBUG_CATEGORY_BGP , " topo_groups_init: alloc failed " ) ; return NULL ; }
g - > instance = instance ;
g - > group_list = queue_new ( instance - > ua , 0 , 0 , 0 , " topo_groups " ) ;
if ( ! g - > group_list ) { u_free ( g ) ; DEBUG_ERROR ( DEBUG_CATEGORY_BGP , " topo_groups_init: group_list queue creation failed " ) ; return NULL ; }
bgp - > local_node = NULL ;
topo_bgp_update_my_nodeinfo ( instance , bgp ) ;
g - > v4_sock_meta_pool = memory_pool_init ( sizeof ( struct TOPO_SOCKMETA4 ) , " to_v4sock " ) ;
g - > v4_addr_pool = memory_pool_init ( sizeof ( struct TOPO_ADDR4 ) , " to_v4addr " ) ;
g - > v6_sock_meta_pool = memory_pool_init ( sizeof ( struct TOPO_SOCKMETA6 ) , " to_v6sock " ) ;
g - > v6_addr_pool = memory_pool_init ( sizeof ( struct TOPO_ADDR6 ) , " to_v6addr " ) ;
g - > v4_subnet_pool = memory_pool_init ( sizeof ( struct TOPO_SUBNET4 ) , " to_v4sub " ) ;
g - > v6_subnet_pool = memory_pool_init ( sizeof ( struct TOPO_SUBNET6 ) , " to_v6sub " ) ;
instance - > topo_groups = g ;
struct TOPO_GROUP * default_group = topo_group_create ( instance , TOPO_GROUP_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 ) ;
memory_pool_destroy ( g - > v4_subnet_pool ) ; memory_pool_destroy ( g - > v6_subnet_pool ) ;
queue_free ( g - > group_list ) ; u_free ( g ) ;
DEBUG_ERROR ( DEBUG_CATEGORY_BGP , " topo_groups_init: failed to create default group " ) ;
return NULL ;
}
{ struct ll_entry * e = queue_entry_new ( sizeof ( struct TOPO_GROUP ) ) ; if ( e ) { * ( struct TOPO_GROUP * * ) e - > data = default_group ; queue_data_put ( g - > group_list , e ) ; } }
etcp_bind ( instance , ETCP_ID_TOPO_ENTRY , topo_bgp_receive_cbk ) ;
etcp_add_new_conn_cbk ( instance , topo_bgp_etcp_conn_cbk , NULL ) ;
etcp_bind ( instance , ETCP_ID_TOPO_ENTRY , topo_grou p_receive_cbk ) ;
etcp_add_new_conn_cbk ( instance , topo_grou p_etcp_conn_cbk , NULL ) ;
DEBUG_INFO ( DEBUG_CATEGORY_BGP , " TOPO BGP module initialized " ) ;
return bgp ;
DEBUG_INFO ( DEBUG_CATEGORY_BGP , " TOPO groups initialized (with default group) " ) ;
return g ;
}
void topo_bgp_destroy ( struct UTUN_INSTANCE * instance ) {
if ( ! instance ) { DEBUG_ERROR ( DEBUG_CATEGORY_BGP , " topo_bgp_destroy: instance is NULL " ) ; return ; }
if ( ! instance - > bgp ) { DEBUG_ERROR ( DEBUG_CATEGORY_BGP , " topo_bgp_destroy: bgp is NULL " ) ; return ; }
DEBUG_INFO ( DEBUG_CATEGORY_BGP , " topo_bgp_destroy: node_id=%016llx " , ( unsigned long long ) instance - > node_id ) ;
void topo_grou ps _destroy ( struct UTUN_INSTANCE * instance ) {
if ( ! instance ) { DEBUG_ERROR ( DEBUG_CATEGORY_BGP , " topo_grou ps _destroy: instance is NULL " ) ; return ; }
if ( ! instance - > topo_groups ) { DEBUG_ERROR ( DEBUG_CATEGORY_BGP , " topo_groups_destroy: topo_groups is NULL " ) ; return ; }
DEBUG_INFO ( DEBUG_CATEGORY_BGP , " topo_grou ps _destroy: node_id=%016llx " , ( unsigned long long ) instance - > node_id ) ;
etcp_unbind ( instance , ETCP_ID_TOPO_ENTRY ) ;
route_connectivity_cancel_all ( instance ) ;
struct ll_entry * e ;
while ( ( e = queue_data_get ( instance - > bgp - > senders_list ) ) ! = NULL ) queue_entry_free ( e ) ;
queue_free ( instance - > bgp - > senders_list ) ;
if ( instance - > bgp - > local_node ) { topo_node_free_lists ( instance - > bgp , instance - > bgp - > local_node ) ; u_free ( instance - > bgp - > local_node ) ; }
struct TOPO_GROUPS * g = instance - > topo_groups ;
struct ll_entry * ge ;
while ( ( ge = queue_data_get ( g - > group_list ) ) ! = NULL ) { topo_group_destroy ( * ( struct TOPO_GROUP * * ) ge - > data ) ; queue_entry_free ( ge ) ; }
queue_free ( g - > group_list ) ;
topo_node_lmdb_destroy ( instance - > bgp ) ;
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 ) ;
memory_pool_destroy ( g - > v4_subnet_pool ) ;
memory_pool_destroy ( g - > v6_subnet_pool ) ;
if ( instance - > bgp - > nodes ) queue_free ( instance - > bgp - > nodes ) ;
u_free ( g ) ; instance - > topo_groups = NULL ;
}
memory_pool_destroy ( instance - > bgp - > v4_sock_meta_pool ) ;
memory_pool_destroy ( instance - > bgp - > v4_addr_pool ) ;
memory_pool_destroy ( instance - > bgp - > v6_sock_meta_pool ) ;
memory_pool_destroy ( instance - > bgp - > v6_addr_pool ) ;
memory_pool_destroy ( instance - > bgp - > v4_subnet_pool ) ;
memory_pool_destroy ( instance - > bgp - > v6_subnet_pool ) ;
struct TOPO_GROUP * topo_groups_get_default ( struct TOPO_GROUPS * g ) {
return topo_groups_find ( g , TOPO_GROUP_UTUN ) ;
}
u_free ( instance - > bgp ) ; instance - > bgp = NULL ;
struct TOPO_GROUP * topo_groups_find ( struct TOPO_GROUPS * g , uint64_t group_id ) {
if ( ! g | | ! g - > group_list ) return NULL ;
struct ll_entry * e = g - > group_list - > head ;
while ( e ) { struct TOPO_GROUP * grp = * ( struct TOPO_GROUP * * ) e - > data ; if ( grp & & grp - > group_id = = group_id ) return grp ; e = e - > next ; }
return NULL ;
}
void topo_bgp_set_nat_check_local ( struct TOPO_BGP * bgp , int allow ) { if ( ! bgp ) return ; bgp - > allow_nat_check_local = allow ? 1 : 0 ; }
void topo_grou p_set_nat_check_local ( struct TOPO_GROU P * grou p , int allow ) { if ( ! grou p ) return ; grou p - > allow_nat_check_local = allow ? 1 : 0 ; }
void topo_bgp_new_conn ( struct ETCP_CONN * conn ) {
if ( ! conn ) { DEBUG_ERROR ( DEBUG_CATEGORY_BGP , " topo_bgp_new_conn: conn is NULL " ) ; return ; }
if ( ! conn - > instance ) { DEBUG_ERROR ( DEBUG_CATEGORY_BGP , " topo_bgp_new_conn: conn->instance is NULL " ) ; return ; }
if ( ! conn - > instance - > bgp ) { DEBUG_ERROR ( DEBUG_CATEGORY_BGP , " topo_bgp_new_conn: conn->instance->bgp is NULL " ) ; return ; }
if ( ! conn - > instance - > rt ) { DEBUG_ERROR ( DEBUG_CATEGORY_BGP , " topo_bgp_new_conn: conn->instance->rt is NULL " ) ; return ; }
void topo_group_new_conn ( struct TOPO_GROUP * group , struct ETCP_CONN * conn ) {
if ( ! group | | ! conn ) { DEBUG_ERROR ( DEBUG_CATEGORY_BGP , " topo_group_new_conn: invalid args " ) ; return ; }
if ( ! conn - > instance ) { DEBUG_ERROR ( DEBUG_CATEGORY_BGP , " topo_group_new_conn: conn->instance is NULL " ) ; return ; }
if ( ! conn - > instance - > rt ) { DEBUG_ERROR ( DEBUG_CATEGORY_BGP , " topo_group_new_conn: conn->instance->rt is NULL " ) ; return ; }
struct TOPO_BGP * bgp = conn - > instance - > bgp ;
struct TOPO_NODEQ * peer_nq = topo_node_find_by_id ( bgp , conn - > peer_node_id ) ;
topo_bgp_add_to_senders ( bgp , conn ) ;
if ( peer_nq & & peer_nq - > alien ) { DEBUG_INFO ( DEBUG_CATEGORY_BGP , " topo_bgp_new_conn: peer 0x%016llx is alien, skipping route exchange " , ( unsigned long long ) conn - > peer_node_id ) ; return ; }
struct TOPO_NODEQ * peer_nq = topo_node_find_by_id ( group , conn - > peer_node_id ) ;
topo_group_add_to_senders ( group , conn ) ;
if ( peer_nq & & peer_nq - > alien ) { DEBUG_INFO ( DEBUG_CATEGORY_BGP , " topo_group_new_conn: peer 0x%016llx is alien, skipping route exchange " , ( unsigned long long ) conn - > peer_node_id ) ; return ; }
struct ETCP_CONN * c = conn - > instance - > connections ;
while ( c ) { struct ETCP_LINK * l = c - > links ; while ( l ) { if ( l - > initialized & & l - > conn & & l - > nat_check_status < NAT_CHECK_IN_PROGRESS ) topo_b gp_start_link_nat_check ( b gp, l ) ; l = l - > next ; } c = c - > next ; }
while ( c ) { struct ETCP_LINK * l = c - > links ; while ( l ) { if ( l - > initialized & & l - > conn & & l - > nat_check_status < NAT_CHECK_IN_PROGRESS ) topo_grou p_start_link_nat_check ( grou p , l ) ; l = l - > next ; } c = c - > next ; }
topo_b gp_send_table_request ( b gp, conn ) ;
topo_grou p_send_table_request ( grou p , conn ) ;
}
void topo_bgp_remove_conn ( struct ETCP_CONN * conn ) {
if ( ! conn ) { DEBUG_ERROR ( DEBUG_CATEGORY_BGP , " topo_bgp_remove_conn: conn is NULL " ) ; return ; }
if ( ! conn - > instance | | ! conn - > instance - > bgp ) { DEBUG_ERROR ( DEBUG_CATEGORY_BGP , " topo_bgp_remove_conn: invalid instance/bgp " ) ; return ; }
struct TOPO_BGP * bgp = conn - > instance - > bgp ;
void topo_group_remove_conn ( struct TOPO_GROUP * group , struct ETCP_CONN * conn ) {
if ( ! group | | ! conn ) { DEBUG_ERROR ( DEBUG_CATEGORY_BGP , " topo_group_remove_conn: invalid args " ) ; return ; }
if ( ! conn - > instance ) { DEBUG_ERROR ( DEBUG_CATEGORY_BGP , " topo_group_remove_conn: invalid instance " ) ; return ; }
bool found_in_list = false ;
struct ll_entry * e = b gp- > senders_list - > head ;
while ( e ) { struct TOPO_B GP_CONN_ITEM * item = ( struct TOPO_B GP_CONN_ITEM * ) e - > data ; if ( item - > conn = = conn ) { found_in_list = true ; break ; } e = e - > next ; }
if ( ! found_in_list ) { DEBUG_WARN ( DEBUG_CATEGORY_BGP , " topo_b gp_remove_conn: conn already removed or not in list, skipping " ) ; return ; }
struct ll_entry * e = grou p - > senders_list - > head ;
while ( e ) { struct TOPO_GROU P_CONN_ITEM * item = ( struct TOPO_GROU P_CONN_ITEM * ) e - > data ; if ( item - > conn = = conn ) { found_in_list = true ; break ; } e = e - > next ; }
if ( ! found_in_list ) { DEBUG_WARN ( DEBUG_CATEGORY_BGP , " topo_grou p_remove_conn: conn already removed or not in list, skipping " ) ; return ; }
DEBUG_INFO ( DEBUG_CATEGORY_BGP , " topo_b gp_remove_conn: peer=%016llx " , ( unsigned long long ) conn - > peer_node_id ) ;
DEBUG_INFO ( DEBUG_CATEGORY_BGP , " topo_grou p_remove_conn: peer=%016llx " , ( unsigned long long ) conn - > peer_node_id ) ;
route_ping_cancel_for_conn ( b gp, conn ) ;
route_ping_cancel_for_conn ( grou p , conn ) ;
struct ETCP_LINK * lnk = conn - > links ; while ( lnk ) { if ( lnk - > nat_check_status = = NAT_CHECK_IN_PROGRESS ) lnk - > nat_check_status = NAT_CHECK_NONE ; lnk = lnk - > next ; }
struct ROUTE_TABLE * rt = conn - > instance - > rt ;
int nodes_removed = 0 ;
struct ll_entry * node_entry = b gp- > nodes ? b gp- > nodes - > head : NULL ;
struct ll_entry * node_entry = grou p - > nodes ? grou p - > nodes - > head : NULL ;
while ( node_entry ) {
struct ll_entry * next = node_entry - > next ;
struct TOPO_NODEQ * nq = ( struct TOPO_NODEQ * ) node_entry ;
if ( topo_b gp_remove_path ( nq , conn ) = = 1 ) {
if ( topo_grou p_remove_path ( nq , conn ) = = 1 ) {
if ( 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 ) ;
if ( nq - > paths ) { queue_free ( nq - > paths ) ; nq - > paths = NULL ; }
uint64_t key = nq - > hash_node_id ;
topo_node_free_lists ( b gp, nq ) ;
topo_node_free_lists ( grou p , nq ) ;
struct ll_entry * entry = node_entry ;
if ( entry ) { queue_remove_data ( b gp- > nodes , entry ) ; queue_entry_free ( entry ) ; }
if ( entry ) { queue_remove_data ( grou p - > nodes , entry ) ; queue_entry_free ( entry ) ; }
nodes_removed + + ;
etcp_router_conn_close_all_for_node ( b gp- > instance , key ) ;
etcp_router_conn_close_all_for_node ( grou p - > instance , key ) ;
uint64_t wd_src = ( key = = conn - > peer_node_id ) ? conn - > instance - > node_id : conn - > peer_node_id ;
topo_b gp_broadcast_withdraw ( b gp, key , wd_src , NULL ) ;
topo_grou p_broadcast_withdraw ( grou p , key , wd_src , NULL ) ;
DEBUG_DEBUG ( DEBUG_CATEGORY_BGP , " Removed node %016llx after link down " , ( unsigned long long ) key ) ;
}
node_entry = next ;
}
e = b gp- > senders_list - > head ;
while ( e ) { struct TOPO_B GP_CONN_ITEM * item = ( struct TOPO_B GP_CONN_ITEM * ) e - > data ; if ( item - > conn = = conn ) { queue_remove_data ( b gp- > senders_list , e ) ; queue_entry_free ( e ) ; break ; } e = e - > next ; }
e = grou p - > senders_list - > head ;
while ( e ) { struct TOPO_GROU P_CONN_ITEM * item = ( struct TOPO_GROU P_CONN_ITEM * ) e - > data ; if ( item - > conn = = conn ) { queue_remove_data ( grou p - > senders_list , e ) ; queue_entry_free ( e ) ; break ; } e = e - > next ; }
DEBUG_INFO ( DEBUG_CATEGORY_BGP , " BGP peer removed: %s nodes=%d " , conn - > log_name , nodes_removed ) ;
}
@ -317,9 +382,9 @@ void topo_bgp_remove_conn(struct ETCP_CONN* conn) {
// NODEINFO BASED IMPLEMENTATION
// ============================================================================
struct ETCP_CONN * topo_b gp_find_conn_for_node ( struct TOPO_B GP * b gp, uint64_t node_id ) {
if ( ! b gp) return NULL ;
struct TOPO_NODEQ * nq = topo_node_find_by_id ( b gp, node_id ) ;
struct ETCP_CONN * topo_grou p_find_conn_for_node ( struct TOPO_GROU P * grou p , uint64_t node_id ) {
if ( ! grou p ) return NULL ;
struct TOPO_NODEQ * nq = topo_node_find_by_id ( grou p , node_id ) ;
if ( ! nq | | ! nq - > paths | | ! nq - > paths - > head ) return NULL ;
struct ll_entry * e = nq - > paths - > head ;
struct TOPO_NODEPATH * best_live = NULL ; uint8_t best_live_hops = 255 ;
@ -333,7 +398,7 @@ struct ETCP_CONN* topo_bgp_find_conn_for_node(struct TOPO_BGP* bgp, uint64_t nod
return best_live ? best_live - > conn : ( best_any ? best_any - > conn : NULL ) ;
}
int topo_b gp_add_path ( struct TOPO_NODEQ * nq , struct ETCP_CONN * conn , uint64_t * hop_list , uint8_t hop_count ) {
int topo_grou p_add_path ( struct TOPO_NODEQ * nq , struct ETCP_CONN * conn , uint64_t * hop_list , uint8_t hop_count ) {
if ( ! nq | | ! conn | | hop_count > MAX_HOPS | | ! hop_list ) { DEBUG_ERROR ( DEBUG_CATEGORY_BGP , " add_path: invalid args " ) ; return - 1 ; }
if ( ! nq - > paths ) { nq - > paths = queue_new ( conn - > instance - > ua , 0 , 0 , 0 , " node_paths " ) ; if ( ! nq - > paths ) return - 1 ; }
size_t path_size = sizeof ( struct TOPO_NODEPATH ) - sizeof ( struct ll_entry ) + hop_count * 8 ;
@ -345,7 +410,7 @@ int topo_bgp_add_path(struct TOPO_NODEQ* nq, struct ETCP_CONN* conn, uint64_t* h
return 0 ;
}
int topo_b gp_remove_path_by_hop ( struct TOPO_NODEQ * nq , uint64_t wd_source ) {
static int topo_grou p_remove_path_by_hop ( struct TOPO_NODEQ * nq , uint64_t wd_source ) {
if ( ! nq | | ! nq - > paths ) return 0 ;
int removed = 0 ;
struct ll_entry * e = nq - > paths - > head ;
@ -360,7 +425,7 @@ int topo_bgp_remove_path_by_hop(struct TOPO_NODEQ* nq, uint64_t wd_source) {
return removed ;
}
int topo_b gp_remove_path ( struct TOPO_NODEQ * nq , struct ETCP_CONN * conn ) {
int topo_grou p_remove_path ( struct TOPO_NODEQ * nq , struct ETCP_CONN * conn ) {
if ( ! nq | | ! conn | | ! nq - > paths ) return - 1 ;
struct ll_entry * e = nq - > paths - > head ;
while ( e ) { struct TOPO_NODEPATH * path = ( struct TOPO_NODEPATH * ) e ; if ( path - > conn = = conn ) { queue_remove_data ( nq - > paths , e ) ; queue_entry_free ( e ) ; break ; } e = e - > next ; }
@ -378,45 +443,45 @@ static void nat_link_check_cb(int success, uint16_t avg_rtt, uint8_t count_sent,
if ( link - > nat_check_status ! = NAT_CHECK_IN_PROGRESS ) { DEBUG_DEBUG ( DEBUG_CATEGORY_BGP , " nat check cb: link status=%d, skip (conn down?) " , link - > nat_check_status ) ; u_free ( na ) ; return ; }
link - > nat_type = success ? NAT_TYPE_EIM : NAT_TYPE_STRICT ;
link - > nat_check_status = success ? NAT_CHECK_EIM : NAT_CHECK_STRICT ;
if ( link - > etcp ) topo_b gp_send_nat_info ( link - > etcp , link - > remote_socket_id , na - > nat_ip , na - > nat_port , link - > nat_type ) ;
if ( link - > etcp ) topo_grou p_send_nat_info ( link - > etcp , link - > remote_socket_id , na - > nat_ip , na - > nat_port , link - > nat_type ) ;
DEBUG_INFO ( DEBUG_CATEGORY_BGP , " NAT check result: type=%s for conn=%s nat=%s:%u " , success ? " EIM " : " STRICT " , link - > etcp - > log_name , ip_to_str ( & na - > nat_ip , AF_INET ) . str , na - > nat_port ) ;
u_free ( na ) ;
}
static struct ETCP_CONN * topo_b gp_find_third_node ( struct TOPO_B GP * b gp, struct ETCP_CONN * exclude ) {
if ( ! b gp | | ! b gp- > senders_list ) return NULL ;
struct ll_entry * e = b gp- > senders_list - > head ;
while ( e ) { struct TOPO_B GP_CONN_ITEM * item = ( struct TOPO_B GP_CONN_ITEM * ) e - > data ; if ( item & & item - > conn & & item - > conn ! = exclude & & item - > conn - > links & & item - > conn - > links - > remote_only_local = = 0 & & item - > conn - > links - > remote_type ! = CFG_SERVER_TYPE_PRIVATE & & item - > conn - > links - > remote_type ! = CFG_SERVER_TYPE_LOCAL ) return item - > conn ; e = e - > next ; }
static struct ETCP_CONN * topo_grou p_find_third_node ( struct TOPO_GROU P * grou p , struct ETCP_CONN * exclude ) {
if ( ! grou p | | ! grou p - > senders_list ) return NULL ;
struct ll_entry * e = grou p - > senders_list - > head ;
while ( e ) { struct TOPO_GROU P_CONN_ITEM * item = ( struct TOPO_GROU P_CONN_ITEM * ) e - > data ; if ( item & & item - > conn & & item - > conn ! = exclude & & item - > conn - > links & & item - > conn - > links - > remote_only_local = = 0 & & item - > conn - > links - > remote_type ! = CFG_SERVER_TYPE_PRIVATE & & item - > conn - > links - > remote_type ! = CFG_SERVER_TYPE_LOCAL ) return item - > conn ; e = e - > next ; }
return NULL ;
}
void topo_b gp_start_link_nat_check ( struct TOPO_B GP * b gp, struct ETCP_LINK * link ) {
if ( ! b gp | | ! link | | ! link - > conn | | ! link - > etcp ) return ;
void topo_grou p_start_link_nat_check ( struct TOPO_GROU P * grou p , struct ETCP_LINK * link ) {
if ( ! grou p | | ! link | | ! link - > conn | | ! link - > etcp ) return ;
if ( link - > nat_type = = NAT_TYPE_DIRECT ) return ;
if ( link - > nat_check_status = = NAT_CHECK_IN_PROGRESS ) return ;
if ( link - > conn - > type = = CFG_SERVER_TYPE_PRIVATE | | link - > conn - > type = = CFG_SERVER_TYPE_LOCAL ) { DEBUG_DEBUG ( DEBUG_CATEGORY_BGP , " skip nat check for private/local socket link " ) ; return ; }
struct ETCP_CONN * third_conn = topo_b gp_find_third_node ( b gp, link - > etcp ) ;
struct ETCP_CONN * third_conn = topo_grou p_find_third_node ( grou p , link - > etcp ) ;
if ( ! third_conn ) { DEBUG_DEBUG ( DEBUG_CATEGORY_BGP , " no third node found for link " ) ; return ; }
uint32_t target_ip ; uint16_t target_port ;
if ( link - > nat_ip ! = 0 & & link - > nat_port ! = 0 ) { target_ip = link - > nat_ip ; target_port = link - > nat_port ; }
else { struct sockaddr_in * sin = ( struct sockaddr_in * ) & link - > remote_addr ; target_ip = sin - > sin_addr . s_addr ; target_port = ntohs ( sin - > sin_port ) ; }
if ( ! b gp- > allow_nat_check_local & & is_local_subnet ( target_ip ) ) { DEBUG_DEBUG ( DEBUG_CATEGORY_BGP , " local connection: %s, skip nat check " , ip_to_str ( & target_ip , AF_INET ) . str ) ; return ; }
if ( ! grou p - > allow_nat_check_local & & is_local_subnet ( target_ip ) ) { DEBUG_DEBUG ( DEBUG_CATEGORY_BGP , " local connection: %s, skip nat check " , ip_to_str ( & target_ip , AF_INET ) . str ) ; return ; }
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 ;
const uint8_t * pubkey = link - > etcp - > crypto_ctx . peer_key_set ? link - > etcp - > crypto_ctx . peer_public_key : NULL ;
if ( ! pubkey ) { u_free ( arg ) ; DEBUG_DEBUG ( DEBUG_CATEGORY_BGP , " no peer pubkey for link=%p " , ( void * ) link ) ; return ; }
int ret = route_ping_send_req_addr ( b gp, third_conn , target_ip , target_port , 3 , 500 , 1000 , 5000 , nat_link_check_cb , arg , pubkey ) ;
int ret = route_ping_send_req_addr ( grou p , third_conn , target_ip , target_port , 3 , 500 , 1000 , 5000 , nat_link_check_cb , arg , pubkey ) ;
if ( ret = = 0 ) { link - > nat_check_status = NAT_CHECK_IN_PROGRESS ; DEBUG_INFO ( DEBUG_CATEGORY_BGP , " ping remote request via=%s (%s:%d) " , third_conn - > log_name , ip_to_str ( & target_ip , AF_INET ) . str , target_port ) ; }
else { u_free ( arg ) ; DEBUG_WARN ( DEBUG_CATEGORY_BGP , " failed to start for link=%s (%s:%d) " , third_conn - > log_name , ip_to_str ( & target_ip , AF_INET ) . str , target_port ) ; }
}
// ===== NODEINFO process =====
int topo_b gp_process_nodeinfo ( struct TOPO_B GP * b gp, struct ETCP_CONN * from , const uint8_t * data , size_t len ) {
if ( ! b gp | | ! from | | len < sizeof ( struct TOPOMSG_NODEINFO_PKT ) ) return - 1 ;
int topo_grou p_process_nodeinfo ( struct TOPO_GROU P * grou p , struct ETCP_CONN * from , const uint8_t * data , size_t len ) {
if ( ! grou p | | ! 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 ;
@ -425,9 +490,9 @@ int topo_bgp_process_nodeinfo(struct TOPO_BGP* bgp, struct ETCP_CONN* from, cons
uint64_t node_id = ni - > node_id ;
if ( ni - > hop_count > = MAX_HOPS ) { DEBUG_WARN ( DEBUG_CATEGORY_BGP , " NODEINFO from %s dropped: too many hops (%d) " , from - > log_name , ni - > hop_count ) ; return - 1 ; }
if ( node_id = = b gp- > instance - > node_id ) return 0 ;
if ( node_id = = grou p - > instance - > node_id ) return 0 ;
struct TOPO_NODEQ * nodeinfo1 = topo_node_find_by_id ( b gp, node_id ) ;
struct TOPO_NODEQ * nodeinfo1 = topo_node_find_by_id ( grou p , node_id ) ;
uint8_t new_ver = ni - > ver ;
if ( nodeinfo1 & & ( int8_t ) ( nodeinfo1 - > last_ver - new_ver ) > = 0 ) {
@ -437,8 +502,8 @@ int topo_bgp_process_nodeinfo(struct TOPO_BGP* bgp, struct ETCP_CONN* from, cons
const uint8_t * hop_src = ( const uint8_t * ) ni + sizeof ( struct TOPOMSG_NODE ) + dyn - ni - > hop_count * 8 ;
memcpy ( hop_list , hop_src , ni - > hop_count * 8 ) ;
hop_list [ ni - > hop_count ] = from - > peer_node_id ;
topo_b gp_remove_path ( nodeinfo1 , from ) ;
topo_b gp_add_path ( nodeinfo1 , from , hop_list , new_hops ) ;
topo_grou p_remove_path ( nodeinfo1 , from ) ;
topo_grou p_add_path ( nodeinfo1 , from , hop_list , new_hops ) ;
}
return 0 ;
}
@ -450,20 +515,19 @@ int topo_bgp_process_nodeinfo(struct TOPO_BGP* bgp, struct ETCP_CONN* from, cons
struct ll_queue * paths = NULL ;
int is_new_node = 0 ;
if ( nodeinfo1 ) {
topo_node_free_lists ( b gp, nodeinfo1 ) ;
topo_node_free_lists ( grou p , nodeinfo1 ) ;
paths = nodeinfo1 - > paths ; nodeinfo1 - > paths = NULL ;
} else { is_new_node = 1 ; }
// deserialize from protocol
const uint8_t * ser_data = data + 2 ;
size_t ser_len = len - 2 ;
struct TOPO_NODE * new_ni = NULL ;
struct TOPO_NODESUBNETS * new_subnets = NULL ;
struct TOPOMSG_TRANZIT * new_tranzit = NULL ; uint8_t new_tranzit_count = 0 ;
uint64_t * new_hop_list = NULL ; uint8_t new_hop_count = 0 ;
if ( topo_node_deserialize ( b gp, ser_data , ser_len , & new_ni , & new_subnets , & new_tranzit , & new_tranzit_count , & new_hop_list , & new_hop_count ) ! = 0 ) {
if ( topo_node_deserialize ( grou p , ser_data , ser_len , & new_ni , & new_subnets , & new_tranzit , & new_tranzit_count , & new_hop_list , & new_hop_count ) ! = 0 ) {
DEBUG_ERROR ( DEBUG_CATEGORY_BGP , " NODEINFO deserialize failed from %s " , from - > log_name ) ;
if ( nodeinfo1 ) { queue_remove_data ( b gp- > nodes , & nodeinfo1 - > ll ) ; queue_free ( paths ) ; queue_entry_free ( & nodeinfo1 - > ll ) ; }
if ( nodeinfo1 ) { queue_remove_data ( grou p - > nodes , & nodeinfo1 - > ll ) ; queue_free ( paths ) ; queue_entry_free ( & nodeinfo1 - > ll ) ; }
return - 1 ;
}
@ -491,12 +555,11 @@ int topo_bgp_process_nodeinfo(struct TOPO_BGP* bgp, struct ETCP_CONN* from, cons
nodeinfo1 - > connectivity . real_status = PROBE_RESULT_UNKNOWN ;
nodeinfo1 - > connectivity . ping_req_time = 0 ;
nodeinfo1 - > alien = 0 ;
queue_data_put_with_index ( b gp- > nodes , & nodeinfo1 - > ll ) ;
queue_data_put_with_index ( grou p - > nodes , & nodeinfo1 - > ll ) ;
}
nodeinfo1 - > paths = paths ; nodeinfo1 - > last_ver = new_ver ;
// add this hop
uint64_t hop_list [ MAX_HOPS ] ;
if ( nodeinfo1 - > hop_count > 0 ) memcpy ( hop_list , nodeinfo1 - > hop_list , nodeinfo1 - > hop_count * 8 ) ;
hop_list [ nodeinfo1 - > hop_count ] = from - > peer_node_id ;
@ -506,22 +569,22 @@ int topo_bgp_process_nodeinfo(struct TOPO_BGP* bgp, struct ETCP_CONN* from, cons
nodeinfo1 - > hop_list = u_malloc ( nodeinfo1 - > hop_count * 8 ) ;
memcpy ( nodeinfo1 - > hop_list , hop_list , nodeinfo1 - > hop_count * 8 ) ;
topo_b gp_remove_path_by_hop ( nodeinfo1 , from - > peer_node_id ) ;
topo_b gp_add_path ( nodeinfo1 , from , hop_list , nodeinfo1 - > hop_count ) ;
topo_grou p_remove_path_by_hop ( nodeinfo1 , from - > peer_node_id ) ;
topo_grou p_add_path ( nodeinfo1 , from , hop_list , nodeinfo1 - > hop_count ) ;
if ( b gp- > instance - > rt ) route_insert ( b gp- > instance - > rt , nodeinfo1 ) ;
if ( node_id ! = b gp- > instance - > node_id ) topo_node_lmdb_put ( b gp, nodeinfo1 ) ;
if ( b gp- > instance - > control_srv ) control_server_notify_node_change ( b gp- > instance - > control_srv , nodeinfo1 ) ;
if ( grou p - > instance - > rt ) route_insert ( grou p - > instance - > rt , nodeinfo1 ) ;
if ( node_id ! = grou p - > instance - > node_id ) topo_node_lmdb_put ( grou p , nodeinfo1 ) ;
if ( grou p - > instance - > control_srv ) control_server_notify_node_change ( grou p - > instance - > control_srv , nodeinfo1 ) ;
int hop_count = nodeinfo1 - > hop_count ;
struct ll_entry * se = b gp- > senders_list ? b gp- > senders_list - > head : NULL ;
struct ll_entry * se = grou p - > senders_list ? grou p - > senders_list - > head : NULL ;
while ( se ) {
struct TOPO_B GP_CONN_ITEM * item = ( struct TOPO_B GP_CONN_ITEM * ) se - > data ;
struct TOPO_GROU P_CONN_ITEM * item = ( struct TOPO_GROU P_CONN_ITEM * ) se - > data ;
if ( item - > conn ) {
uint64_t id = item - > conn - > peer_node_id ;
if ( id ! = node_id ) {
int found = 0 ; for ( int i = 0 ; i < hop_count ; i + + ) if ( hop_list [ i ] = = id ) found = 1 ;
if ( found = = 0 ) topo_b gp_send_nodeinfo ( nodeinfo1 , item - > conn ) ;
if ( found = = 0 ) topo_grou p_send_nodeinfo ( group , nodeinfo1 , item - > conn ) ;
}
}
se = se - > next ;
@ -530,39 +593,39 @@ int topo_bgp_process_nodeinfo(struct TOPO_BGP* bgp, struct ETCP_CONN* from, cons
int socks_changed = 1 ;
if ( ! is_new_node ) socks_changed = 1 ;
if ( node_id ! = b gp- > instance - > node_id & & ( is_new_node | | socks_changed ) ) {
if ( node_id ! = grou p - > instance - > node_id & & ( is_new_node | | socks_changed ) ) {
int v4a = topo_list_count ( ( struct _topo_head * ) nodeinfo1 - > node - > v4_addrs ) ;
int v6a = topo_list_count ( ( struct _topo_head * ) nodeinfo1 - > node - > v6_addrs ) ;
if ( v4a > 0 | | v6a > 0 ) route_connectivity_probe_node ( b gp- > instance , nodeinfo1 ) ;
if ( v4a > 0 | | v6a > 0 ) route_connectivity_probe_node ( grou p - > instance , nodeinfo1 ) ;
}
return 0 ;
}
int topo_b gp_process_withdraw ( struct TOPO_B GP * b gp, struct ETCP_CONN * sender , const uint8_t * data , size_t len ) {
if ( ! b gp | | len < sizeof ( struct TOPOMSG_WITHDRAW_PKT ) ) return - 1 ;
int topo_grou p_process_withdraw ( struct TOPO_GROU P * grou p , struct ETCP_CONN * sender , const uint8_t * data , size_t len ) {
if ( ! grou p | | len < sizeof ( struct TOPOMSG_WITHDRAW_PKT ) ) return - 1 ;
struct TOPOMSG_WITHDRAW_PKT * wp = ( struct TOPOMSG_WITHDRAW_PKT * ) data ;
uint64_t node_id = wp - > node_id , wd_source = wp - > wd_source ;
struct TOPO_NODEQ * nq = topo_node_find_by_id ( b gp, node_id ) ;
struct TOPO_NODEQ * nq = topo_node_find_by_id ( grou p , node_id ) ;
if ( ! nq ) { DEBUG_INFO ( DEBUG_CATEGORY_BGP , " node not found " ) ; return 0 ; }
int ret = topo_b gp_remove_path_by_hop ( nq , wd_source ) ;
int ret = topo_grou p_remove_path_by_hop ( nq , wd_source ) ;
if ( ret = = 1 ) {
if ( b gp- > instance & & b gp- > instance - > rt ) route_delete ( b gp- > instance - > rt , nq ) ;
if ( b gp- > instance - > control_srv ) control_server_notify_node_removed ( b gp- > instance - > control_srv , node_id ) ;
if ( grou p - > instance & & grou p - > instance - > rt ) route_delete ( grou p - > instance - > rt , nq ) ;
if ( grou p - > instance - > control_srv ) control_server_notify_node_removed ( grou p - > instance - > control_srv , node_id ) ;
nq - > dirty = 1 ;
route_connectivity_cancel_node ( b gp- > instance , nq ) ;
route_connectivity_cancel_node ( grou p - > instance , nq ) ;
if ( nq - > paths ) { queue_free ( nq - > paths ) ; nq - > paths = NULL ; }
topo_node_free_lists ( b gp, nq ) ;
struct ll_entry * entry = queue_find_data_by_index ( b gp- > nodes , & node_id ) ;
if ( entry ) { queue_remove_data ( b gp- > nodes , entry ) ; queue_entry_free ( entry ) ; }
topo_b gp_broadcast_withdraw ( b gp, node_id , wd_source , sender ) ;
topo_node_free_lists ( grou p , nq ) ;
struct ll_entry * entry = queue_find_data_by_index ( grou p - > nodes , & node_id ) ;
if ( entry ) { queue_remove_data ( grou p - > nodes , entry ) ; queue_entry_free ( entry ) ; }
topo_grou p_broadcast_withdraw ( grou p , node_id , wd_source , sender ) ;
}
return 0 ;
}
void topo_b gp_send_nodeinfo ( struct TOPO_NODEQ * node , struct ETCP_CONN * conn ) {
if ( ! node | | ! conn ) return ;
void topo_grou p_send_nodeinfo ( struct TOPO_GROUP * group , struct TOPO_NODEQ * node , struct ETCP_CONN * conn ) {
if ( ! group | | ! node | | ! conn ) return ;
size_t max_sz = sizeof ( struct TOPOMSG_NODEINFO_PKT ) + 4096 ;
uint8_t * p = u_malloc ( max_sz ) ;
@ -570,7 +633,7 @@ void topo_bgp_send_nodeinfo(struct TOPO_NODEQ* node, struct ETCP_CONN* conn) {
p [ 0 ] = ETCP_ID_TOPO_ENTRY ; p [ 1 ] = TOPO_SUBCMD_NODEINFO ;
int ser_len = topo_node_serialize ( conn - > instance - > bg p, node , p + 2 , max_sz - 2 ) ;
int ser_len = topo_node_serialize ( grou p, node , p + 2 , max_sz - 2 ) ;
if ( ser_len < 0 ) { u_free ( p ) ; return ; }
struct ll_entry * e = queue_entry_new ( 0 ) ;
@ -580,18 +643,18 @@ void topo_bgp_send_nodeinfo(struct TOPO_NODEQ* node, struct ETCP_CONN* conn) {
if ( etcp_send ( conn , e ) ! = 0 ) { DEBUG_ERROR ( DEBUG_CATEGORY_BGP , " etcp_send NODEINFO failed " ) ; u_free ( p ) ; queue_entry_free ( e ) ; }
}
static void topo_b gp_add_to_senders ( struct TOPO_B GP * b gp, struct ETCP_CONN * conn ) {
if ( ! b gp | | ! conn | | ! b gp- > senders_list ) return ;
static void topo_grou p_add_to_senders ( struct TOPO_GROU P * grou p , struct ETCP_CONN * conn ) {
if ( ! grou p | | ! conn | | ! grou p - > senders_list ) return ;
bool already = false ;
struct ll_entry * e = b gp- > senders_list - > head ;
while ( e ) { if ( ( ( struct TOPO_B GP_CONN_ITEM * ) e - > data ) - > conn = = conn ) { already = true ; break ; } e = e - > next ; }
struct ll_entry * e = grou p - > senders_list - > head ;
while ( e ) { if ( ( ( struct TOPO_GROU P_CONN_ITEM * ) e - > data ) - > conn = = conn ) { already = true ; break ; } e = e - > next ; }
if ( ! already ) {
struct ll_entry * item_entry = queue_entry_new ( sizeof ( struct TOPO_B GP_CONN_ITEM ) ) ;
if ( item_entry ) { ( ( struct TOPO_B GP_CONN_ITEM * ) item_entry - > data ) - > conn = conn ; queue_data_put ( b gp- > senders_list , item_entry ) ; }
struct ll_entry * item_entry = queue_entry_new ( sizeof ( struct TOPO_GROU P_CONN_ITEM ) ) ;
if ( item_entry ) { ( ( struct TOPO_GROU P_CONN_ITEM * ) item_entry - > data ) - > conn = conn ; queue_data_put ( grou p - > senders_list , item_entry ) ; }
}
}
static bool topo_b gp_should_send_to ( const struct TOPO_NODEQ * nq , uint64_t target_id ) {
static bool topo_grou p_should_send_to ( const struct TOPO_NODEQ * nq , uint64_t target_id ) {
if ( ! nq | | ! nq - > node | | ! nq - > paths ) return false ;
if ( target_id = = nq - > node - > node_id ) return false ;
struct ll_entry * e = nq - > paths - > head ;
@ -605,29 +668,29 @@ static bool topo_bgp_should_send_to(const struct TOPO_NODEQ* nq, uint64_t target
return false ;
}
static void topo_b gp_send_full_table ( struct TOPO_B GP * b gp, struct ETCP_CONN * conn ) {
if ( ! b gp | | ! conn ) return ;
static void topo_grou p_send_full_table ( struct TOPO_GROU P * grou p , struct ETCP_CONN * conn ) {
if ( ! grou p | | ! conn ) return ;
uint64_t target = conn - > peer_node_id ;
struct ll_entry * e = b gp- > nodes ? b gp- > nodes - > head : NULL ;
struct ll_entry * e = grou p - > nodes ? grou p - > nodes - > head : NULL ;
while ( e ) {
struct TOPO_NODEQ * nq = ( struct TOPO_NODEQ * ) e ;
if ( nq - > hop_count = = 0 ) { e = e - > next ; continue ; }
if ( ! nq - > paths ) { DEBUG_WARN ( DEBUG_CATEGORY_BGP , " node has no paths " ) ; e = e - > next ; continue ; }
if ( topo_b gp_should_send_to ( nq , target ) ) topo_b gp_send_nodeinfo ( nq , conn ) ;
if ( topo_grou p_should_send_to ( nq , target ) ) topo_grou p_send_nodeinfo ( group , nq , conn ) ;
e = e - > next ;
}
}
static void topo_b gp_handle_request_table ( struct TOPO_B GP * b gp, struct ETCP_CONN * conn ) {
if ( ! b gp | | ! conn ) return ;
topo_b gp_send_nodeinfo ( bg p- > local_node , conn ) ;
topo_b gp_send_full_table ( b gp, conn ) ;
topo_b gp_add_to_senders ( b gp, conn ) ;
topo_b gp_send_table_complete ( b gp, conn ) ;
static void topo_grou p_handle_request_table ( struct TOPO_GROU P * grou p , struct ETCP_CONN * conn ) {
if ( ! grou p | | ! conn ) return ;
topo_grou p_send_nodeinfo ( group , grou p- > local_node , conn ) ;
topo_grou p_send_full_table ( grou p , conn ) ;
topo_grou p_add_to_senders ( grou p , conn ) ;
topo_grou p_send_table_complete ( grou p , conn ) ;
}
static void topo_b gp_handle_nat_info ( struct TOPO_B GP * b gp, struct ETCP_CONN * from_conn , const uint8_t * data , size_t len ) {
if ( ! b gp | | ! from_conn | | ! data | | len < sizeof ( struct TOPOMSG_NAT_INFO ) | | ! b gp- > local_node | | ! b gp- > local_node - > node ) return ;
static void topo_grou p_handle_nat_info ( struct TOPO_GROU P * grou p , struct ETCP_CONN * from_conn , const uint8_t * data , size_t len ) {
if ( ! grou p | | ! from_conn | | ! data | | len < sizeof ( struct TOPOMSG_NAT_INFO ) | | ! grou p - > local_node | | ! grou p - > local_node - > node ) return ;
const struct TOPOMSG_NAT_INFO * info = ( const struct TOPOMSG_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 ] ;
@ -640,43 +703,43 @@ static void topo_bgp_handle_nat_info(struct TOPO_BGP* bgp, struct ETCP_CONN* fro
else verified_type = NAT_VERIFIED_UNKNOWN ;
int data_changed = 0 ;
{ struct TOPO_SOCKMETA4 * sm = b gp- > local_node - > node - > v4_sock_meta ; while ( sm ) { if ( sm - > id = = socket_id ) { if ( sm - > nat_type ! = verified_type ) { sm - > nat_type = verified_type ; data_changed = 1 ; } break ; } sm = sm - > next ; } }
{ struct TOPO_SOCKMETA4 * sm = grou p - > local_node - > node - > v4_sock_meta ; while ( sm ) { if ( sm - > id = = socket_id ) { if ( sm - > nat_type ! = verified_type ) { sm - > nat_type = verified_type ; data_changed = 1 ; } break ; } sm = sm - > next ; } }
struct ETCP_SOCKET * es = b gp- > instance - > etcp_sockets ;
struct ETCP_SOCKET * es = grou p - > 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 * ) b gp- > local_node - > node - > v4_addrs ) ;
topo_b gp_update_my_nodeinfo ( b gp- > instance , b gp) ;
if ( topo_list_count ( ( struct _topo_head * ) b gp- > local_node - > node - > v4_addrs ) ! = prev_v4a ) {
b gp- > local_node - > dirty = 1 ;
b gp- > local_node - > node - > ver = ( b gp- > local_node - > node - > ver % 255 ) + 1 ;
b gp- > local_node - > last_ver = b gp- > local_node - > node - > ver ;
int prev_v4a = topo_list_count ( ( struct _topo_head * ) grou p - > local_node - > node - > v4_addrs ) ;
topo_grou p_update_my_nodeinfo ( grou p - > instance , grou p ) ;
if ( topo_list_count ( ( struct _topo_head * ) grou p - > local_node - > node - > v4_addrs ) ! = prev_v4a ) {
grou p - > local_node - > dirty = 1 ;
grou p - > local_node - > node - > ver = ( grou p - > local_node - > node - > ver % 255 ) + 1 ;
grou p - > local_node - > last_ver = grou p - > local_node - > node - > ver ;
}
if ( b gp- > local_node - > dirty & & b gp- > senders_list ) {
struct ll_entry * se = b gp- > senders_list - > head ;
while ( se ) { struct TOPO_B GP_CONN_ITEM * item = ( struct TOPO_B GP_CONN_ITEM * ) se - > data ; if ( item & & item - > conn ) topo_b gp_send_nodeinfo ( bg p- > local_node , item - > conn ) ; se = se - > next ; }
if ( grou p - > local_node - > dirty & & grou p - > senders_list ) {
struct ll_entry * se = grou p - > senders_list - > head ;
while ( se ) { struct TOPO_GROU P_CONN_ITEM * item = ( struct TOPO_GROU P_CONN_ITEM * ) se - > data ; if ( item & & item - > conn ) topo_grou p_send_nodeinfo ( group , grou p- > local_node , item - > conn ) ; se = se - > next ; }
}
}
struct ETCP_LINK * l = from_conn - > links ; while ( l ) { l - > nat_type = info - > nat_type ; l = l - > next ; }
}
static void topo_b gp_handle_nat_check_req ( struct TOPO_B GP * b gp, struct ETCP_CONN * from_conn , const uint8_t * data , size_t len ) {
if ( ! b gp | | ! from_conn | | ! data | | len < sizeof ( struct TOPOMSG_NAT_CHECK_REQ ) ) return ;
static void topo_grou p_handle_nat_check_req ( struct TOPO_GROU P * grou p , struct ETCP_CONN * from_conn , const uint8_t * data , size_t len ) {
if ( ! grou p | | ! from_conn | | ! data | | len < sizeof ( struct TOPOMSG_NAT_CHECK_REQ ) ) return ;
const struct TOPOMSG_NAT_CHECK_REQ * req = ( const struct TOPOMSG_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 ) return ;
if ( target_link - > nat_check_status = = NAT_CHECK_IN_PROGRESS ) return ;
topo_b gp_start_link_nat_check ( b gp, target_link ) ;
topo_grou p_start_link_nat_check ( grou p , target_link ) ;
}
void topo_b gp_send_nat_info ( struct ETCP_CONN * conn , uint8_t socket_id , uint32_t nat_ip , uint16_t nat_port , uint8_t nat_type ) {
void topo_grou p_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 TOPOMSG_NAT_INFO * pkt = u_calloc ( 1 , sizeof ( struct TOPOMSG_NAT_INFO ) ) ; if ( ! pkt ) return ;
pkt - > cmd = ETCP_ID_TOPO_ENTRY ; pkt - > subcmd = TOPO_SUBCMD_NAT_INFO ;
@ -689,7 +752,7 @@ void topo_bgp_send_nat_info(struct ETCP_CONN* conn, uint8_t socket_id, uint32_t
if ( etcp_send ( conn , e ) ! = 0 ) { DEBUG_ERROR ( DEBUG_CATEGORY_BGP , " etcp_send NAT_INFO failed " ) ; u_free ( pkt ) ; queue_entry_free ( e ) ; }
}
void topo_b gp_send_nat_check_req ( struct ETCP_CONN * conn , uint8_t socket_id ) {
void topo_grou p_send_nat_check_req ( struct ETCP_CONN * conn , uint8_t socket_id ) {
if ( ! conn ) return ;
struct TOPOMSG_NAT_CHECK_REQ * pkt = u_calloc ( 1 , sizeof ( struct TOPOMSG_NAT_CHECK_REQ ) ) ; if ( ! pkt ) return ;
pkt - > cmd = ETCP_ID_TOPO_ENTRY ; pkt - > subcmd = TOPO_SUBCMD_NAT_CHECK_REQ ; pkt - > socket_id = socket_id ;
@ -699,8 +762,14 @@ void topo_bgp_send_nat_check_req(struct ETCP_CONN* conn, uint8_t socket_id) {
if ( etcp_send ( conn , e ) ! = 0 ) { DEBUG_ERROR ( DEBUG_CATEGORY_BGP , " etcp_send NAT_CHECK_REQ failed " ) ; u_free ( pkt ) ; queue_entry_free ( e ) ; }
}
void topo_b gp_request_nat_check_all ( struct TOPO_B GP * b gp) {
if ( ! b gp | | ! b gp- > instance ) return ;
void topo_grou p_request_nat_check_all ( struct TOPO_GROU P * grou p ) {
if ( ! grou p | | ! grou p - > instance ) return ;
int count = 0 ;
struct ETCP_CONN * conn = bgp - > instance - > connections ; while ( conn ) { struct ETCP_LINK * link = conn - > links ; while ( link ) { if ( link - > nat_check_status < NAT_CHECK_IN_PROGRESS ) topo_bgp_start_link_nat_check ( bgp , link ) ; count + + ; link = link - > next ; } conn = conn - > next ; }
struct ETCP_CONN * conn = group - > instance - > connections ; while ( conn ) { struct ETCP_LINK * link = conn - > links ; while ( link ) { if ( link - > nat_check_status < NAT_CHECK_IN_PROGRESS ) topo_group_start_link_nat_check ( group , link ) ; count + + ; link = link - > next ; } conn = conn - > next ; }
}
void topo_group_send_withdraw ( struct TOPO_GROUP * group , uint64_t node_id ) {
if ( ! group ) return ;
DEBUG_INFO ( DEBUG_CATEGORY_BGP , " topo_group_send_withdraw: node=%016llx " , ( unsigned long long ) node_id ) ;
topo_group_broadcast_withdraw ( group , node_id , group - > instance - > node_id , NULL ) ;
}