@ -1,6 +1,6 @@
/**
* @ file route _bgp. c
* @ brief BGP - like о б м е н м а р ш р у т а м и
* @ file topo _bgp. c
* @ brief BGP - like о б м е н т о п о л о г и е й у з л о в
*/
# include <stdlib.h>
# include <string.h>
@ -15,10 +15,10 @@
# include "etcp_connections.h"
# include "etcp_debug.h"
# include "config_parser.h"
# include "route _node.h"
# include "route _node_lmdb.h"
# include "topo _node.h"
# include "topo _node_lmdb.h"
# include "route_lib.h"
# include "route _bgp.h"
# include "topo _bgp.h"
# include "route_ping.h"
# include "route_connectivity.h"
# include "control_server.h"
@ -28,64 +28,64 @@
// Вспомогательные функции
// ============================================================================
static void route _bgp_send_table_request( struct ROUTE _BGP* bgp , struct ETCP_CONN * conn ) {
static void topo _bgp_send_table_request( struct TOPO _BGP* bgp , struct ETCP_CONN * conn ) {
if ( ! bgp | | ! conn ) return ;
DEBUG_INFO ( DEBUG_CATEGORY_BGP , " Sending table request to %s " , conn - > log_name ) ;
struct BGP_ROUTE_REQUEST * req = u_calloc ( 1 , sizeof ( struct BGP_ROUTE_REQUEST ) ) ;
struct TOPOMSG_TABLE_REQ * req = u_calloc ( 1 , sizeof ( struct TOPOMSG_TABLE_REQ ) ) ;
if ( ! req ) return ;
req - > cmd = ETCP_ID_ROUTE _ENTRY ;
req - > subcmd = ROUTE _SUBCMD_REQUEST_TABLE;
req - > cmd = ETCP_ID_TOPO _ENTRY ;
req - > subcmd = TOPO _SUBCMD_REQUEST_TABLE;
struct ll_entry * e = queue_entry_new ( 0 ) ;
if ( ! e ) { u_free ( req ) ; return ; }
e - > dgram = ( uint8_t * ) req ; e - > len = sizeof ( struct BGP_ROUTE_REQUEST ) ;
e - > dgram = ( uint8_t * ) req ; e - > len = sizeof ( struct TOPOMSG_TABLE_REQ ) ;
if ( etcp_send ( conn , e ) ! = 0 ) { u_free ( req ) ; queue_entry_free ( e ) ; }
}
static void route _bgp_send_table_complete( struct ROUTE _BGP* bgp , struct ETCP_CONN * conn ) {
static void topo _bgp_send_table_complete( struct TOPO _BGP* bgp , struct ETCP_CONN * conn ) {
if ( ! bgp | | ! conn ) return ;
struct BGP_ROUTE_REQUEST * req = u_calloc ( 1 , sizeof ( struct BGP_ROUTE_REQUEST ) ) ;
struct TOPOMSG_TABLE_REQ * req = u_calloc ( 1 , sizeof ( struct TOPOMSG_TABLE_REQ ) ) ;
if ( ! req ) return ;
req - > cmd = ETCP_ID_ROUTE _ENTRY ;
req - > subcmd = ROUTE _SUBCMD_TABLE_COMPLETE;
req - > cmd = ETCP_ID_TOPO _ENTRY ;
req - > subcmd = TOPO _SUBCMD_TABLE_COMPLETE;
struct ll_entry * e = queue_entry_new ( 0 ) ;
if ( ! e ) { u_free ( req ) ; return ; }
e - > dgram = ( uint8_t * ) req ; e - > len = sizeof ( struct BGP_ROUTE_REQUEST ) ;
e - > dgram = ( uint8_t * ) req ; e - > len = sizeof ( struct TOPOMSG_TABLE_REQ ) ;
if ( etcp_send ( conn , e ) ! = 0 ) { u_free ( req ) ; queue_entry_free ( e ) ; }
}
static void route_bgp_add_to_senders ( struct ROUTE _BGP* bgp , struct ETCP_CONN * conn ) ;
static bool route _bgp_should_send_to( const struct NODEINFO_ Q * nq , uint64_t target_id ) ;
static void route_bgp_send_full_table ( struct ROUTE _BGP* bgp , struct ETCP_CONN * conn ) ;
static void route _bgp_handle_request_table( struct ROUTE _BGP* bgp , struct ETCP_CONN * conn ) ;
static void topo_bgp_add_to_senders ( struct TOPO _BGP* bgp , struct ETCP_CONN * conn ) ;
static bool topo _bgp_should_send_to( const struct TOPO_ NODEQ* nq , uint64_t target_id ) ;
static void topo_bgp_send_full_table ( struct TOPO _BGP* bgp , struct ETCP_CONN * conn ) ;
static void topo _bgp_handle_request_table( struct TOPO _BGP* bgp , struct ETCP_CONN * conn ) ;
static void nodeinfo_dump_log ( const uint8_t * data , size_t len ) {
if ( ! data | | len < sizeof ( struct BGP_NODEINFO_PACKE T) ) return ;
struct BGP_NODEINFO_PACKE T* pkt = ( struct BGP_NODEINFO_PACKE T* ) data ;
struct NODEINFO_MSG * ni = & pkt - > node ;
if ( ! data | | len < sizeof ( struct TOPOMSG_NODEINFO_PK T) ) return ;
struct TOPOMSG_NODEINFO_PK T* pkt = ( struct TOPOMSG_NODEINFO_PK T* ) data ;
struct TOPOMSG_NODE * ni = & pkt - > node ;
DEBUG_DEBUG ( DEBUG_CATEGORY_BGP , " NODEINFO nid=%016llx ver=%u v4s=%u v4a=%u hops=%u " ,
( unsigned long long ) ni - > node_id , ni - > ver ,
ni - > local_v4_sockets , ni - > local_v4_addrs , ni - > hop_count ) ;
}
static char * nodeinfo_format ( const uint8_t * data , size_t len ) {
if ( ! data | | len < sizeof ( struct BGP_NODEINFO_PACKE T) ) return NULL ;
struct BGP_NODEINFO_PACKE T* pkt = ( struct BGP_NODEINFO_PACKE T* ) data ;
struct NODEINFO_MSG * ni = & pkt - > node ;
if ( ! data | | len < sizeof ( struct TOPOMSG_NODEINFO_PK T) ) return NULL ;
struct TOPOMSG_NODEINFO_PK T* pkt = ( struct TOPOMSG_NODEINFO_PK T* ) data ;
struct TOPOMSG_NODE * ni = & pkt - > node ;
uint64_t node_id = ni - > node_id ;
const uint8_t * dyn = data + sizeof ( struct BGP_NODEINFO_PACKE T) ;
const uint8_t * dyn = data + sizeof ( struct TOPOMSG_NODEINFO_PK T) ;
size_t off = 0 ;
char name_buf [ 64 ] = { 0 } ;
size_t nl = ni - > node_name_len ;
if ( nl > 0 & & nl < 63 & & off + nl < len - sizeof ( struct BGP_NODEINFO_PACKE T) ) {
if ( nl > 0 & & nl < 63 & & off + nl < len - sizeof ( struct TOPOMSG_NODEINFO_PK T) ) {
memcpy ( name_buf , dyn + off , nl ) ; off + = nl ;
}
off + = ni - > local_v4_sockets * sizeof ( struct NODEINFO_IPV4_SOCKET_META ) ;
off + = ni - > local_v4_addrs * sizeof ( struct NODEINFO_IPV4_ADDR ) ;
off + = ni - > local_v6_sockets * sizeof ( struct NODEINFO_IPV6_SOCKET_META ) ;
off + = ni - > local_v6_addrs * sizeof ( struct NODEINFO_IPV6_ADDR ) ;
off + = ni - > local_v4_sockets * sizeof ( struct TOPOMSG_SOCKMETA4 ) ;
off + = ni - > local_v4_addrs * sizeof ( struct TOPOMSG_ADDR4 ) ;
off + = ni - > local_v6_sockets * sizeof ( struct TOPOMSG_SOCKMETA6 ) ;
off + = ni - > local_v6_addrs * sizeof ( struct TOPOMSG_ADDR6 ) ;
char subs_buf [ 512 ] = { 0 } ;
if ( ni - > local_v4_subnets > 0 ) {
const struct NODEINFO_IPV4_SUBNET * subs = ( const struct NODEINFO_IPV4_SUBNET * ) ( dyn + off ) ;
const struct TOPOMSG_SUBNET4 * subs = ( const struct TOPOMSG_SUBNET4 * ) ( dyn + off ) ;
size_t sl = 0 ;
for ( uint8_t i = 0 ; i < ni - > local_v4_subnets & & sl < 400 ; i + + ) {
uint32_t addr = ( subs [ i ] . addr [ 0 ] < < 24 ) | ( subs [ i ] . addr [ 1 ] < < 16 ) | ( subs [ i ] . addr [ 2 ] < < 8 ) | subs [ i ] . addr [ 3 ] ;
@ -101,14 +101,14 @@ static char* nodeinfo_format(const uint8_t* data, size_t len) {
static const char * bgp_subcmd_name ( uint8_t subcmd ) {
switch ( subcmd ) {
case ROUTE _SUBCMD_NODEINFO: return " NODEINFO " ;
case ROUTE _SUBCMD_REQUEST_TABLE: return " REQ_TABLE " ;
case ROUTE _SUBCMD_WITHDRAW: return " WITHDRAW " ;
case ROUTE _SUBCMD_PING_REQ: return " PING_REQ " ;
case ROUTE _SUBCMD_PING_RESP: return " PING_RESP " ;
case ROUTE _SUBCMD_NAT_INFO: return " NAT_INFO " ;
case ROUTE _SUBCMD_NAT_CHECK_REQ: return " NAT_CHECK_REQ " ;
case ROUTE _SUBCMD_TABLE_COMPLETE: return " TABLE_COMPLETE " ;
case TOPO _SUBCMD_NODEINFO: return " NODEINFO " ;
case TOPO _SUBCMD_REQUEST_TABLE: return " REQ_TABLE " ;
case TOPO _SUBCMD_WITHDRAW: return " WITHDRAW " ;
case TOPO _SUBCMD_PING_REQ: return " PING_REQ " ;
case TOPO _SUBCMD_PING_RESP: return " PING_RESP " ;
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 " ;
default : return " ? " ;
}
}
@ -118,15 +118,15 @@ static const char* bgp_subcmd_name(uint8_t subcmd) {
// Broadcast / Withdraw
// ============================================================================
static void route _bgp_broadcast_withdraw( struct ROUTE _BGP* bgp , uint64_t node_id , uint64_t wd_source , struct ETCP_CONN * exclude ) {
static void topo _bgp_broadcast_withdraw( struct TOPO _BGP* bgp , uint64_t node_id , uint64_t wd_source , struct ETCP_CONN * exclude ) {
if ( ! bgp ) { DEBUG_ERROR ( DEBUG_CATEGORY_BGP , " bgp is NULL " ) ; return ; }
struct BGP_WITHDRAW_PACKE T* pkt = u_calloc ( 1 , sizeof ( struct BGP_WITHDRAW_PACKE T) ) ;
struct TOPOMSG_WITHDRAW_PK T* pkt = u_calloc ( 1 , sizeof ( struct TOPOMSG_WITHDRAW_PK T) ) ;
if ( ! pkt ) return ;
pkt - > cmd = ETCP_ID_ROUTE _ENTRY ; pkt - > subcmd = ROUTE _SUBCMD_WITHDRAW;
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 = bgp - > senders_list ? bgp - > senders_list - > head : NULL ;
while ( e ) {
struct ROUTE _BGP_CONN_ITEM* item = ( struct ROUTE _BGP_CONN_ITEM* ) e - > data ;
struct TOPO _BGP_CONN_ITEM* item = ( struct TOPO _BGP_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,27 +141,27 @@ static void route_bgp_broadcast_withdraw(struct ROUTE_BGP* bgp, uint64_t node_id
// Приём пакетов
// ============================================================================
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 topo_bgp_handle_nat_info ( struct TOPO _BGP* bgp , struct ETCP_CONN * from_conn , const uint8_t * data , size_t len ) ;
static void topo _bgp_handle_nat_check_req( struct TOPO _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 topo _bgp_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 , " route _bgp_receive_cbk: invalid instance/bgp" ) ; queue_dgram_free ( entry ) ; queue_entry_free ( entry ) ; return ; }
struct ROUTE _BGP* bgp = instance - > bgp ;
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 ;
uint8_t * data = entry - > dgram ; uint8_t cmd = data [ 0 ] ; uint8_t subcmd = data [ 1 ] ;
if ( cmd ! = ETCP_ID_ROUTE _ENTRY ) { queue_dgram_free ( entry ) ; queue_entry_free ( entry ) ; return ; }
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 " , bgp_subcmd_name ( subcmd ) , from_conn - > log_name , entry - > len ) ;
if ( subcmd = = ROUTE _SUBCMD_NODEINFO) { nodeinfo_dump_log ( data , entry - > len ) ; route _bgp_process_nodeinfo( bgp , from_conn , data , entry - > len ) ; }
else if ( subcmd = = ROUTE_SUBCMD_WITHDRAW ) route _bgp_process_withdraw( bgp , from_conn , data , entry - > len ) ;
else if ( subcmd = = ROUTE_SUBCMD_REQUEST_TABLE ) route _bgp_handle_request_table( bgp , from_conn ) ;
else if ( subcmd = = ROUTE _SUBCMD_PING_REQ) route_ping_handle_req ( bgp , from_conn , data , entry - > len ) ;
else if ( subcmd = = ROUTE _SUBCMD_PING_RESP) route_ping_handle_resp ( bgp , from_conn , data , entry - > len ) ;
else if ( subcmd = = ROUTE_SUBCMD_NAT_INFO ) route _bgp_handle_nat_info( bgp , from_conn , data , entry - > len ) ;
else if ( subcmd = = ROUTE_SUBCMD_NAT_CHECK_REQ ) route _bgp_handle_nat_check_req( bgp , from_conn , data , entry - > len ) ;
else if ( subcmd = = ROUTE _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 ) ; }
if ( subcmd = = TOPO _SUBCMD_NODEINFO) { nodeinfo_dump_log ( data , entry - > len ) ; topo _bgp_process_nodeinfo( bgp , from_conn , data , entry - > len ) ; }
else if ( subcmd = = TOPO_SUBCMD_WITHDRAW ) topo _bgp_process_withdraw( bgp , from_conn , data , entry - > len ) ;
else if ( subcmd = = TOPO_SUBCMD_REQUEST_TABLE ) topo _bgp_handle_request_table( bgp , from_conn ) ;
else if ( subcmd = = TOPO _SUBCMD_PING_REQ) route_ping_handle_req ( bgp , from_conn , data , entry - > len ) ;
else if ( subcmd = = TOPO _SUBCMD_PING_RESP) route_ping_handle_resp ( bgp , from_conn , data , entry - > len ) ;
else if ( subcmd = = TOPO_SUBCMD_NAT_INFO ) topo _bgp_handle_nat_info( bgp , from_conn , data , entry - > len ) ;
else if ( subcmd = = TOPO_SUBCMD_NAT_CHECK_REQ ) topo _bgp_handle_nat_check_req( bgp , 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,22 +171,22 @@ static void route_bgp_receive_cbk(struct ETCP_CONN* from_conn, struct ll_entry*
// Init / Destroy / New / Remove conn
// ============================================================================
static void route _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 ) ; route _bgp_new_conn( 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 route _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 ) ; route _bgp_remove_conn( 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 route _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 , route _bgp_on_conn_up, conn - > instance - > bgp ) ; etcp_conn_add_down_cbk ( conn , route _bgp_on_conn_down, conn - > instance - > bgp ) ; }
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 ) ; }
}
struct ROUTE_BGP * route _bgp_init( struct UTUN_INSTANCE * instance ) {
if ( ! instance ) { DEBUG_ERROR ( DEBUG_CATEGORY_BGP , " route _bgp_init: instance is NULL" ) ; return NULL ; }
DEBUG_INFO ( DEBUG_CATEGORY_BGP , " route _bgp_init: node_id=%016llx" , ( unsigned long long ) instance - > node_id ) ;
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 ) ;
struct ROUTE _BGP* bgp = u_calloc ( 1 , sizeof ( struct ROUTE _BGP) ) ;
if ( ! bgp ) { DEBUG_ERROR ( DEBUG_CATEGORY_BGP , " route _bgp_init: alloc failed" ) ; return NULL ; }
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 ;
@ -194,46 +194,46 @@ struct ROUTE_BGP* route_bgp_init(struct UTUN_INSTANCE* instance) {
sc_derive_ed25519_pubkey ( instance - > my_keys . private_key , bgp - > ed25519_public_key ) ;
DEBUG_INFO ( DEBUG_CATEGORY_BGP , " Ed25519 pubkey derived from X25519 private key " ) ;
if ( instance - > config & & instance - > config - > global . db_path [ 0 ] ) route _node_lmdb_init( bgp , instance - > config - > global . db_path ) ;
if ( instance - > config & & instance - > config - > global . db_path [ 0 ] ) topo _node_lmdb_init( bgp , instance - > config - > global . db_path ) ;
bgp - > nodes = queue_new ( instance - > ua , BGP_NODES_HASH_SIZE , offsetof ( struct NODEINFO_ Q , hash_node_id ) - sizeof ( struct ll_entry ) , 8 , " bgp_nodes " ) ;
if ( ! bgp - > nodes ) { u_free ( bgp ) ; DEBUG_ERROR ( DEBUG_CATEGORY_BGP , " route _bgp_init: nodes queue creation failed" ) ; return NULL ; }
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 ; }
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 , " route _bgp_init: senders_list queue creation failed" ) ; return NULL ; }
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 ; }
bgp - > v4_sock_meta_pool = memory_pool_init ( sizeof ( struct NI_IPV4_SOCKET_META ) , " ni _v4sock" ) ;
bgp - > v4_addr_pool = memory_pool_init ( sizeof ( struct NI_IPV4_ADDR ) , " ni _v4addr" ) ;
bgp - > v6_sock_meta_pool = memory_pool_init ( sizeof ( struct NI_IPV6_SOCKET_META ) , " ni _v6sock" ) ;
bgp - > v6_addr_pool = memory_pool_init ( sizeof ( struct NI_IPV6_ADDR ) , " ni _v6addr" ) ;
bgp - > v4_subnet_pool = memory_pool_init ( sizeof ( struct NI_IPV4_SUBNET ) , " ni _v4sub" ) ;
bgp - > v6_subnet_pool = memory_pool_init ( sizeof ( struct NI_IPV6_SUBNET ) , " ni _v6sub" ) ;
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" ) ;
bgp - > local_node = NULL ;
route _bgp_update_my_nodeinfo( instance , bgp ) ;
topo _bgp_update_my_nodeinfo( instance , bgp ) ;
etcp_bind ( instance , ETCP_ID_ROUTE_ENTRY , route _bgp_receive_cbk ) ;
etcp_add_new_conn_cbk ( instance , route _bgp_etcp_conn_cbk, NULL ) ;
etcp_bind ( instance , ETCP_ID_TOPO_ENTRY , topo _bgp_receive_cbk ) ;
etcp_add_new_conn_cbk ( instance , topo _bgp_etcp_conn_cbk, NULL ) ;
DEBUG_INFO ( DEBUG_CATEGORY_BGP , " BGP module initialized (NODEINFO based routing) " ) ;
DEBUG_INFO ( DEBUG_CATEGORY_BGP , " TOPO BGP module initialized" ) ;
return bgp ;
}
void route _bgp_destroy( struct UTUN_INSTANCE * instance ) {
if ( ! instance ) { DEBUG_ERROR ( DEBUG_CATEGORY_BGP , " route _bgp_destroy: instance is NULL" ) ; return ; }
if ( ! instance - > bgp ) { DEBUG_ERROR ( DEBUG_CATEGORY_BGP , " route _bgp_destroy: bgp is NULL" ) ; return ; }
DEBUG_INFO ( DEBUG_CATEGORY_BGP , " route _bgp_destroy: node_id=%016llx" , ( unsigned long long ) instance - > node_id ) ;
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 ) ;
etcp_unbind ( instance , ETCP_ID_ROUTE _ENTRY ) ;
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 ) { nodeinfo _free_lists ( instance - > bgp , instance - > bgp - > local_node ) ; u_free ( instance - > bgp - > local_node ) ; }
if ( instance - > bgp - > local_node ) { topo_ node_free_lists( instance - > bgp , instance - > bgp - > local_node ) ; u_free ( instance - > bgp - > local_node ) ; }
route _node_lmdb_destroy( instance - > bgp ) ;
topo _node_lmdb_destroy( instance - > bgp ) ;
if ( instance - > bgp - > nodes ) queue_free ( instance - > bgp - > nodes ) ;
@ -247,36 +247,36 @@ void route_bgp_destroy(struct UTUN_INSTANCE* instance) {
u_free ( instance - > bgp ) ; instance - > bgp = NULL ;
}
void route _bgp_set_nat_check_local( struct ROUTE _BGP* bgp , int allow ) { if ( ! bgp ) return ; bgp - > allow_nat_check_local = allow ? 1 : 0 ; }
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 route _bgp_new_conn( struct ETCP_CONN * conn ) {
if ( ! conn ) { DEBUG_ERROR ( DEBUG_CATEGORY_BGP , " route _bgp_new_conn: conn is NULL" ) ; return ; }
if ( ! conn - > instance ) { DEBUG_ERROR ( DEBUG_CATEGORY_BGP , " route _bgp_new_conn: conn->instance is NULL" ) ; return ; }
if ( ! conn - > instance - > bgp ) { DEBUG_ERROR ( DEBUG_CATEGORY_BGP , " route _bgp_new_conn: conn->instance->bgp is NULL" ) ; return ; }
if ( ! conn - > instance - > rt ) { DEBUG_ERROR ( DEBUG_CATEGORY_BGP , " route _bgp_new_conn: conn->instance->rt is NULL" ) ; return ; }
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 ; }
struct ROUTE _BGP* bgp = conn - > instance - > bgp ;
struct NODEINFO_ Q * peer_nq = nodeinfo _find_by_id ( bgp , conn - > peer_node_id ) ;
route _bgp_add_to_senders( bgp , conn ) ;
if ( peer_nq & & peer_nq - > alien ) { DEBUG_INFO ( DEBUG_CATEGORY_BGP , " route _bgp_new_conn: peer 0x%016llx is alien, skipping route exchange" , ( unsigned long long ) conn - > peer_node_id ) ; 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 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 ) route _bgp_start_link_nat_check( bgp , 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 _bgp_start_link_nat_check( bgp , l ) ; l = l - > next ; } c = c - > next ; }
route _bgp_send_table_request( bgp , conn ) ;
topo _bgp_send_table_request( bgp , conn ) ;
}
void route _bgp_remove_conn( struct ETCP_CONN * conn ) {
if ( ! conn ) { DEBUG_ERROR ( DEBUG_CATEGORY_BGP , " route _bgp_remove_conn: conn is NULL" ) ; return ; }
if ( ! conn - > instance | | ! conn - > instance - > bgp ) { DEBUG_ERROR ( DEBUG_CATEGORY_BGP , " route _bgp_remove_conn: invalid instance/bgp" ) ; return ; }
struct ROUTE _BGP* bgp = conn - > instance - > bgp ;
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 ;
bool found_in_list = false ;
struct ll_entry * e = bgp - > senders_list - > head ;
while ( e ) { struct ROUTE _BGP_CONN_ITEM* item = ( struct ROUTE _BGP_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 , " route _bgp_remove_conn: conn already removed or not in list, skipping" ) ; return ; }
while ( e ) { struct TOPO _BGP_CONN_ITEM* item = ( struct TOPO _BGP_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 _bgp_remove_conn: conn already removed or not in list, skipping" ) ; return ; }
DEBUG_INFO ( DEBUG_CATEGORY_BGP , " route _bgp_remove_conn: peer=%016llx" , ( unsigned long long ) conn - > peer_node_id ) ;
DEBUG_INFO ( DEBUG_CATEGORY_BGP , " topo _bgp_remove_conn: peer=%016llx" , ( unsigned long long ) conn - > peer_node_id ) ;
route_ping_cancel_for_conn ( bgp , 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 ; }
@ -286,46 +286,46 @@ void route_bgp_remove_conn(struct ETCP_CONN* conn) {
struct ll_entry * node_entry = bgp - > nodes ? bgp - > nodes - > head : NULL ;
while ( node_entry ) {
struct ll_entry * next = node_entry - > next ;
struct NODEINFO_ Q * nq = ( struct NODEINFO_ Q * ) node_entry ;
if ( route _bgp_remove_path( nq , conn ) = = 1 ) {
struct TOPO_ NODEQ* nq = ( struct TOPO_ NODEQ* ) node_entry ;
if ( topo _bgp_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 ;
nodeinfo _free_lists ( bgp , nq ) ;
topo_ node_free_lists( bgp , nq ) ;
struct ll_entry * entry = node_entry ;
if ( entry ) { queue_remove_data ( bgp - > nodes , entry ) ; queue_entry_free ( entry ) ; }
nodes_removed + + ;
etcp_router_conn_close_all_for_node ( bgp - > instance , key ) ;
uint64_t wd_src = ( key = = conn - > peer_node_id ) ? conn - > instance - > node_id : conn - > peer_node_id ;
route _bgp_broadcast_withdraw( bgp , key , wd_src , NULL ) ;
topo _bgp_broadcast_withdraw( bgp , key , wd_src , NULL ) ;
DEBUG_DEBUG ( DEBUG_CATEGORY_BGP , " Removed node %016llx after link down " , ( unsigned long long ) key ) ;
}
node_entry = next ;
}
e = bgp - > senders_list - > head ;
while ( e ) { struct ROUTE _BGP_CONN_ITEM* item = ( struct ROUTE _BGP_CONN_ITEM* ) e - > data ; if ( item - > conn = = conn ) { queue_remove_data ( bgp - > senders_list , e ) ; queue_entry_free ( e ) ; break ; } e = e - > next ; }
while ( e ) { struct TOPO _BGP_CONN_ITEM* item = ( struct TOPO _BGP_CONN_ITEM* ) e - > data ; if ( item - > conn = = conn ) { queue_remove_data ( bgp - > 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 ) ;
}
// ============================================================================
// NEW N ODEINFO BASED IMPLEMENTATION
// NODEINFO BASED IMPLEMENTATION
// ============================================================================
struct ETCP_CONN * route _bgp_find_conn_for_node( struct ROUTE _BGP* bgp , uint64_t node_id ) {
struct ETCP_CONN * topo _bgp_find_conn_for_node( struct TOPO _BGP* bgp , uint64_t node_id ) {
if ( ! bgp ) return NULL ;
struct NODEINFO_ Q * nq = nodeinfo _find_by_id ( bgp , node_id ) ;
struct TOPO_ NODEQ* nq = topo_ node_find_by_id( bgp , node_id ) ;
if ( ! nq | | ! nq - > paths | | ! nq - > paths - > head ) return NULL ;
struct ll_entry * e = nq - > paths - > head ;
struct NODEINFO_ PATH * best_live = NULL ; uint8_t best_live_hops = 255 ;
struct NODEINFO_ PATH * best_any = NULL ; uint8_t best_any_hops = 255 ;
struct TOPO_ NODEPATH* best_live = NULL ; uint8_t best_live_hops = 255 ;
struct TOPO_ NODEPATH* best_any = NULL ; uint8_t best_any_hops = 255 ;
while ( e ) {
struct NODEINFO_ PATH * path = ( struct NODEINFO_ PATH * ) e ;
struct TOPO_ NODEPATH* path = ( struct TOPO_ NODEPATH* ) e ;
if ( path - > conn ) { if ( path - > conn - > links_up & & path - > hop_count < best_live_hops ) { best_live = path ; best_live_hops = path - > hop_count ; } if ( path - > hop_count < best_any_hops ) { best_any = path ; best_any_hops = path - > hop_count ; } }
e = e - > next ;
}
@ -333,25 +333,25 @@ struct ETCP_CONN* route_bgp_find_conn_for_node(struct ROUTE_BGP* bgp, uint64_t n
return best_live ? best_live - > conn : ( best_any ? best_any - > conn : NULL ) ;
}
int route _bgp_add_path( struct NODEINFO_ Q * nq , struct ETCP_CONN * conn , uint64_t * hop_list , uint8_t hop_count ) {
int topo _bgp_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 NODEINFO_ PATH ) - sizeof ( struct ll_entry ) + hop_count * 8 ;
size_t path_size = sizeof ( struct TOPO_ NODEPATH) - sizeof ( struct ll_entry ) + hop_count * 8 ;
struct ll_entry * pe = queue_entry_new ( path_size ) ; if ( ! pe ) return - 1 ;
struct NODEINFO_ PATH * path = ( struct NODEINFO_ PATH * ) pe ;
struct TOPO_ NODEPATH* path = ( struct TOPO_ NODEPATH* ) pe ;
path - > conn = conn ; path - > hop_count = hop_count ;
memcpy ( ( uint64_t * ) ( ( uint8_t * ) path + sizeof ( struct NODEINFO_ PATH ) ) , hop_list , hop_count * 8 ) ;
memcpy ( ( uint64_t * ) ( ( uint8_t * ) path + sizeof ( struct TOPO_ NODEPATH) ) , hop_list , hop_count * 8 ) ;
queue_data_put ( nq - > paths , pe ) ;
return 0 ;
}
int route _bgp_remove_path_by_hop( struct NODEINFO_ Q * nq , uint64_t wd_source ) {
int topo _bgp_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 ;
while ( e ) {
struct NODEINFO_ PATH * path = ( struct NODEINFO_ PATH * ) e ;
uint64_t * hop = ( uint64_t * ) ( ( uint8_t * ) path + sizeof ( struct NODEINFO_ PATH ) ) ;
struct TOPO_ NODEPATH* path = ( struct TOPO_ NODEPATH* ) e ;
uint64_t * hop = ( uint64_t * ) ( ( uint8_t * ) path + sizeof ( struct TOPO_ NODEPATH) ) ;
bool has_wd = false ; for ( uint8_t i = 0 ; i < path - > hop_count ; i + + ) if ( hop [ i ] = = wd_source ) { has_wd = true ; break ; }
if ( has_wd ) { struct ll_entry * next = e - > next ; queue_remove_data ( nq - > paths , e ) ; queue_entry_free ( e ) ; removed + + ; e = next ; continue ; }
e = e - > next ;
@ -360,10 +360,10 @@ int route_bgp_remove_path_by_hop(struct NODEINFO_Q* nq, uint64_t wd_source) {
return removed ;
}
int route _bgp_remove_path( struct NODEINFO_ Q * nq , struct ETCP_CONN * conn ) {
int topo _bgp_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 NODEINFO_ PATH * path = ( struct NODEINFO_ PATH * ) e ; if ( path - > conn = = conn ) { queue_remove_data ( nq - > paths , e ) ; queue_entry_free ( e ) ; break ; } e = e - > next ; }
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 ; }
int remaining = nq - > paths ? queue_entry_count ( nq - > paths ) : 0 ;
if ( remaining = = 0 ) { if ( nq - > paths ) { queue_free ( nq - > paths ) ; nq - > paths = NULL ; } return 1 ; }
return 0 ;
@ -378,29 +378,24 @@ 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 ) route _bgp_send_nat_info( link - > etcp , link - > remote_socket_id , na - > nat_ip , na - > nat_port , link - > nat_type ) ;
if ( link - > etcp ) topo _bgp_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 * route_bgp_find_third_node ( struct ROUTE _BGP* bgp , struct ETCP_CONN * exclude ) {
static struct ETCP_CONN * topo_bgp_find_third_node ( struct TOPO _BGP* bgp , struct ETCP_CONN * exclude ) {
if ( ! bgp | | ! bgp - > senders_list ) return NULL ;
struct ll_entry * e = bgp - > senders_list - > head ;
while ( e ) { struct ROUTE _BGP_CONN_ITEM* item = ( struct ROUTE _BGP_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 ; }
while ( e ) { struct TOPO _BGP_CONN_ITEM* item = ( struct TOPO _BGP_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 ;
}
static void route_bgp_extract_nat_addr ( struct ETCP_CONN * conn , uint32_t * nat_ip , uint16_t * nat_port ) {
* nat_ip = 0 ; * nat_port = 0 ; if ( ! conn ) return ;
struct ETCP_LINK * l = conn - > links ; while ( l ) { if ( l - > nat_ip ! = 0 ) { * nat_ip = l - > nat_ip ; * nat_port = l - > nat_port ; return ; } l = l - > next ; }
}
void route_bgp_start_link_nat_check ( struct ROUTE_BGP * bgp , struct ETCP_LINK * link ) {
void topo_bgp_start_link_nat_check ( struct TOPO_BGP * bgp , struct ETCP_LINK * link ) {
if ( ! bgp | | ! 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 = route _bgp_find_third_node( bgp , link - > etcp ) ;
struct ETCP_CONN * third_conn = topo_bgp_find_third_node ( bgp , 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 ;
@ -420,30 +415,30 @@ void route_bgp_start_link_nat_check(struct ROUTE_BGP* bgp, struct ETCP_LINK* lin
// ===== NODEINFO process =====
int route_bgp_process_nodeinfo ( struct ROUTE _BGP* bgp , struct ETCP_CONN * from , const uint8_t * data , size_t len ) {
if ( ! bgp | | ! from | | len < sizeof ( struct BGP_NODEINFO_PACKE T) ) return - 1 ;
int topo_bgp_process_nodeinfo ( struct TOPO _BGP* bgp , struct ETCP_CONN * from , const uint8_t * data , size_t len ) {
if ( ! bgp | | ! from | | len < sizeof ( struct TOPOMSG_NODEINFO_PK T) ) return - 1 ;
struct BGP_NODEINFO_PACKE T* pkt = ( struct BGP_NODEINFO_PACKE T* ) data ;
struct NODEINFO_MSG * ni = & pkt - > node ;
int dyn = nodeinfo _dyn_size ( ni ) ;
if ( ( size_t ) dyn + sizeof ( struct BGP_NODEINFO_PACKE T) ! = len ) { DEBUG_WARN ( DEBUG_CATEGORY_BGP , " Incorrect packet size (%s) " , from - > log_name ) ; return - 1 ; }
struct TOPOMSG_NODEINFO_PK T* pkt = ( struct TOPOMSG_NODEINFO_PK T* ) data ;
struct TOPOMSG_NODE * ni = & pkt - > node ;
int dyn = topo_ node_dyn_size( ni ) ;
if ( ( size_t ) dyn + sizeof ( struct TOPOMSG_NODEINFO_PK T) ! = len ) { DEBUG_WARN ( DEBUG_CATEGORY_BGP , " Incorrect packet size (%s) " , from - > log_name ) ; return - 1 ; }
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 = = bgp - > instance - > node_id ) return 0 ;
struct NODEINFO_ Q * nodeinfo1 = nodeinfo _find_by_id ( bgp , node_id ) ;
struct TOPO_ NODEQ* nodeinfo1 = topo_ node_find_by_id( bgp , node_id ) ;
uint8_t new_ver = ni - > ver ;
if ( nodeinfo1 & & ( int8_t ) ( nodeinfo1 - > last_ver - new_ver ) > = 0 ) {
int new_hops = ni - > hop_count + 1 ;
if ( new_hops < = MAX_HOPS ) {
uint64_t hop_list [ MAX_HOPS ] ;
const uint8_t * hop_src = ( const uint8_t * ) ni + sizeof ( struct NODEINFO_MSG ) + dyn - ni - > hop_count * 8 ;
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 ;
route _bgp_remove_path( nodeinfo1 , from ) ;
route _bgp_add_path( nodeinfo1 , from , hop_list , new_hops ) ;
topo _bgp_remove_path( nodeinfo1 , from ) ;
topo _bgp_add_path( nodeinfo1 , from , hop_list , new_hops ) ;
}
return 0 ;
}
@ -455,39 +450,39 @@ int route_bgp_process_nodeinfo(struct ROUTE_BGP* bgp, struct ETCP_CONN* from, co
struct ll_queue * paths = NULL ;
int is_new_node = 0 ;
if ( nodeinfo1 ) {
nodeinfo _free_lists ( bgp , nodeinfo1 ) ;
topo_ node_free_lists( bgp , 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 NODEINFO * new_ni = NULL ;
struct NODEINFO_ROUTES * new_route s = NULL ;
struct NODEINFO_TRANZIT_NODE * new_tranzit = NULL ; uint8_t new_tranzit_count = 0 ;
struct TOPO_ NODE* new_ni = NULL ;
struct TOPO_NODESUBNETS * new_subnet s = 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 ( nodeinfo _deserialize ( bgp , ser_data , ser_len , & new_ni , & new_route s , & new_tranzit , & new_tranzit_count , & new_hop_list , & new_hop_count ) ! = 0 ) {
if ( topo_ node_deserialize( bgp , ser_data , ser_len , & new_ni , & new_subnet s , & 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 ( bgp - > nodes , & nodeinfo1 - > ll ) ; queue_free ( paths ) ; queue_entry_free ( & nodeinfo1 - > ll ) ; }
return - 1 ;
}
if ( nodeinfo1 ) {
nodeinfo1 - > node = new_ni ; nodeinfo _ref ( new_ni ) ;
nodeinfo1 - > node = new_ni ; topo_ node_ref( new_ni ) ;
nodeinfo1 - > hash_node_id = new_ni - > node_id ;
nodeinfo1 - > routes = new_route s;
nodeinfo1 - > subnets = new_subnet s;
u_free ( nodeinfo1 - > tranzit_data ) ; nodeinfo1 - > tranzit_data = new_tranzit ;
nodeinfo1 - > tranzit_count = new_tranzit_count ;
u_free ( nodeinfo1 - > hop_list ) ; nodeinfo1 - > hop_list = new_hop_list ;
nodeinfo1 - > hop_count = new_hop_count ;
} else {
struct ll_entry * qe = queue_entry_new ( sizeof ( struct NODEINFO_ Q ) ) ;
if ( ! qe ) { nodeinfo _unref ( new_ni ) ; u_free ( new_tranzit ) ; u_free ( new_hop_list ) ; u_free ( new_route s ) ; return - 1 ; }
nodeinfo1 = ( struct NODEINFO_ Q * ) qe ;
struct ll_entry * qe = queue_entry_new ( sizeof ( struct TOPO_ NODEQ) ) ;
if ( ! qe ) { topo_ node_unref( new_ni ) ; u_free ( new_tranzit ) ; u_free ( new_hop_list ) ; u_free ( new_subnet s ) ; return - 1 ; }
nodeinfo1 = ( struct TOPO_ NODEQ* ) qe ;
memset ( ( uint8_t * ) nodeinfo1 + sizeof ( struct ll_entry ) , 0 , sizeof ( * nodeinfo1 ) - sizeof ( struct ll_entry ) ) ;
nodeinfo1 - > node = new_ni ; nodeinfo _ref ( new_ni ) ;
nodeinfo1 - > node = new_ni ; topo_ node_ref( new_ni ) ;
nodeinfo1 - > hash_node_id = new_ni - > node_id ;
nodeinfo1 - > routes = new_route s;
nodeinfo1 - > subnets = new_subnet s;
nodeinfo1 - > tranzit_data = new_tranzit ; nodeinfo1 - > tranzit_count = new_tranzit_count ;
nodeinfo1 - > hop_list = new_hop_list ; nodeinfo1 - > hop_count = new_hop_count ;
nodeinfo1 - > connectivity . probe_status = PROBE_STATUS_NONE ;
@ -511,22 +506,22 @@ int route_bgp_process_nodeinfo(struct ROUTE_BGP* bgp, struct ETCP_CONN* from, co
nodeinfo1 - > hop_list = u_malloc ( nodeinfo1 - > hop_count * 8 ) ;
memcpy ( nodeinfo1 - > hop_list , hop_list , nodeinfo1 - > hop_count * 8 ) ;
route _bgp_remove_path_by_hop( nodeinfo1 , from - > peer_node_id ) ;
route _bgp_add_path( nodeinfo1 , from , hop_list , nodeinfo1 - > hop_count ) ;
topo _bgp_remove_path_by_hop( nodeinfo1 , from - > peer_node_id ) ;
topo _bgp_add_path( nodeinfo1 , from , hop_list , nodeinfo1 - > hop_count ) ;
if ( bgp - > instance - > rt ) route_insert ( bgp - > instance - > rt , nodeinfo1 ) ;
if ( node_id ! = bgp - > instance - > node_id ) route _node_lmdb_put( bgp , nodeinfo1 ) ;
if ( node_id ! = bgp - > instance - > node_id ) topo _node_lmdb_put( bgp , nodeinfo1 ) ;
if ( bgp - > instance - > control_srv ) control_server_notify_node_change ( bgp - > instance - > control_srv , nodeinfo1 ) ;
int hop_count = nodeinfo1 - > hop_count ;
struct ll_entry * se = bgp - > senders_list ? bgp - > senders_list - > head : NULL ;
while ( se ) {
struct ROUTE _BGP_CONN_ITEM* item = ( struct ROUTE _BGP_CONN_ITEM* ) se - > data ;
struct TOPO _BGP_CONN_ITEM* item = ( struct TOPO _BGP_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 ) route _bgp_send_nodeinfo( nodeinfo1 , item - > conn ) ;
if ( found = = 0 ) topo _bgp_send_nodeinfo( nodeinfo1 , item - > conn ) ;
}
}
se = se - > next ;
@ -536,46 +531,46 @@ int route_bgp_process_nodeinfo(struct ROUTE_BGP* bgp, struct ETCP_CONN* from, co
if ( ! is_new_node ) socks_changed = 1 ;
if ( node_id ! = bgp - > instance - > node_id & & ( is_new_node | | socks_changed ) ) {
int v4a = ni _list_count( ( struct _ni _head * ) nodeinfo1 - > node - > v4_addrs ) ;
int v6a = ni _list_count( ( struct _ni _head * ) nodeinfo1 - > node - > v6_addrs ) ;
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 ( bgp - > instance , nodeinfo1 ) ;
}
return 0 ;
}
int route_bgp_process_withdraw ( struct ROUTE _BGP* bgp , struct ETCP_CONN * sender , const uint8_t * data , size_t len ) {
if ( ! bgp | | len < sizeof ( struct BGP_WITHDRAW_PACKE T) ) return - 1 ;
struct BGP_WITHDRAW_PACKE T* wp = ( struct BGP_WITHDRAW_PACKE T* ) data ;
int topo_bgp_process_withdraw ( struct TOPO _BGP* bgp , struct ETCP_CONN * sender , const uint8_t * data , size_t len ) {
if ( ! bgp | | len < sizeof ( struct TOPOMSG_WITHDRAW_PK T) ) return - 1 ;
struct TOPOMSG_WITHDRAW_PK T* wp = ( struct TOPOMSG_WITHDRAW_PK T* ) data ;
uint64_t node_id = wp - > node_id , wd_source = wp - > wd_source ;
struct NODEINFO_ Q * nq = nodeinfo _find_by_id ( bgp , node_id ) ;
struct TOPO_ NODEQ* nq = topo_ node_find_by_id( bgp , node_id ) ;
if ( ! nq ) { DEBUG_INFO ( DEBUG_CATEGORY_BGP , " node not found " ) ; return 0 ; }
int ret = route _bgp_remove_path_by_hop( nq , wd_source ) ;
int ret = topo _bgp_remove_path_by_hop( nq , wd_source ) ;
if ( ret = = 1 ) {
if ( bgp - > instance & & bgp - > instance - > rt ) route_delete ( bgp - > instance - > rt , nq ) ;
if ( bgp - > instance - > control_srv ) control_server_notify_node_removed ( bgp - > instance - > control_srv , node_id ) ;
nq - > dirty = 1 ;
route_connectivity_cancel_node ( bgp - > instance , nq ) ;
if ( nq - > paths ) { queue_free ( nq - > paths ) ; nq - > paths = NULL ; }
nodeinfo _free_lists ( bgp , nq ) ;
topo_ node_free_lists( bgp , nq ) ;
struct ll_entry * entry = queue_find_data_by_index ( bgp - > nodes , & node_id ) ;
if ( entry ) { queue_remove_data ( bgp - > nodes , entry ) ; queue_entry_free ( entry ) ; }
route _bgp_broadcast_withdraw( bgp , node_id , wd_source , sender ) ;
topo _bgp_broadcast_withdraw( bgp , node_id , wd_source , sender ) ;
}
return 0 ;
}
void route _bgp_send_nodeinfo( struct NODEINFO_ Q * node , struct ETCP_CONN * conn ) {
void topo _bgp_send_nodeinfo( struct TOPO_ NODEQ* node , struct ETCP_CONN * conn ) {
if ( ! node | | ! conn ) return ;
size_t max_sz = sizeof ( struct BGP_NODEINFO_PACKE T) + 4096 ;
size_t max_sz = sizeof ( struct TOPOMSG_NODEINFO_PK T) + 4096 ;
uint8_t * p = u_malloc ( max_sz ) ;
if ( ! p ) return ;
p [ 0 ] = ETCP_ID_ROUTE _ENTRY ; p [ 1 ] = ROUTE _SUBCMD_NODEINFO;
p [ 0 ] = ETCP_ID_TOPO _ENTRY ; p [ 1 ] = TOPO _SUBCMD_NODEINFO;
int ser_len = nodeinfo _serialize ( conn - > instance - > bgp , node , p + 2 , max_sz - 2 ) ;
int ser_len = topo_ node_serialize( conn - > instance - > bgp , node , p + 2 , max_sz - 2 ) ;
if ( ser_len < 0 ) { u_free ( p ) ; return ; }
struct ll_entry * e = queue_entry_new ( 0 ) ;
@ -585,24 +580,24 @@ void route_bgp_send_nodeinfo(struct NODEINFO_Q* 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 route_bgp_add_to_senders ( struct ROUTE _BGP* bgp , struct ETCP_CONN * conn ) {
static void topo_bgp_add_to_senders ( struct TOPO _BGP* bgp , struct ETCP_CONN * conn ) {
if ( ! bgp | | ! conn | | ! bgp - > senders_list ) return ;
bool already = false ;
struct ll_entry * e = bgp - > senders_list - > head ;
while ( e ) { if ( ( ( struct ROUTE _BGP_CONN_ITEM* ) e - > data ) - > conn = = conn ) { already = true ; break ; } e = e - > next ; }
while ( e ) { if ( ( ( struct TOPO _BGP_CONN_ITEM* ) e - > data ) - > conn = = conn ) { already = true ; break ; } e = e - > next ; }
if ( ! already ) {
struct ll_entry * item_entry = queue_entry_new ( sizeof ( struct ROUTE _BGP_CONN_ITEM) ) ;
if ( item_entry ) { ( ( struct ROUTE _BGP_CONN_ITEM* ) item_entry - > data ) - > conn = conn ; queue_data_put ( bgp - > senders_list , item_entry ) ; }
struct ll_entry * item_entry = queue_entry_new ( sizeof ( struct TOPO _BGP_CONN_ITEM) ) ;
if ( item_entry ) { ( ( struct TOPO _BGP_CONN_ITEM* ) item_entry - > data ) - > conn = conn ; queue_data_put ( bgp - > senders_list , item_entry ) ; }
}
}
static bool route _bgp_should_send_to( const struct NODEINFO_ Q * nq , uint64_t target_id ) {
static bool topo _bgp_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 ;
while ( e ) {
struct NODEINFO_ PATH * path = ( struct NODEINFO_ PATH * ) e ;
uint64_t * hop = ( uint64_t * ) ( ( uint8_t * ) path + sizeof ( struct NODEINFO_ PATH ) ) ;
struct TOPO_ NODEPATH* path = ( struct TOPO_ NODEPATH* ) e ;
uint64_t * hop = ( uint64_t * ) ( ( uint8_t * ) path + sizeof ( struct TOPO_ NODEPATH) ) ;
bool has_id = false ; for ( uint8_t i = 0 ; i < path - > hop_count ; i + + ) if ( hop [ i ] = = target_id ) { has_id = true ; break ; }
if ( ! has_id ) return true ;
e = e - > next ;
@ -610,31 +605,31 @@ static bool route_bgp_should_send_to(const struct NODEINFO_Q* nq, uint64_t targe
return false ;
}
static void route_bgp_send_full_table ( struct ROUTE _BGP* bgp , struct ETCP_CONN * conn ) {
static void topo_bgp_send_full_table ( struct TOPO _BGP* bgp , struct ETCP_CONN * conn ) {
if ( ! bgp | | ! conn ) return ;
uint64_t target = conn - > peer_node_id ;
struct ll_entry * e = bgp - > nodes ? bgp - > nodes - > head : NULL ;
while ( e ) {
struct NODEINFO_ Q * nq = ( struct NODEINFO_ Q * ) 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 ( route _bgp_should_send_to( nq , target ) ) route _bgp_send_nodeinfo( nq , conn ) ;
if ( topo _bgp_should_send_to( nq , target ) ) topo _bgp_send_nodeinfo( nq , conn ) ;
e = e - > next ;
}
}
static void route _bgp_handle_request_table( struct ROUTE _BGP* bgp , struct ETCP_CONN * conn ) {
static void topo _bgp_handle_request_table( struct TOPO _BGP* bgp , struct ETCP_CONN * conn ) {
if ( ! bgp | | ! conn ) return ;
route _bgp_send_nodeinfo( bgp - > local_node , conn ) ;
route _bgp_send_full_table( bgp , conn ) ;
route _bgp_add_to_senders( bgp , conn ) ;
route _bgp_send_table_complete( bgp , conn ) ;
topo _bgp_send_nodeinfo( bgp - > local_node , conn ) ;
topo _bgp_send_full_table( bgp , conn ) ;
topo _bgp_add_to_senders( bgp , conn ) ;
topo _bgp_send_table_complete( 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 | | ! bgp - > local_node - > node ) return ;
static void topo_bgp_handle_nat_info ( struct TOPO _BGP* bgp , struct ETCP_CONN * from_conn , const uint8_t * data , size_t len ) {
if ( ! bgp | | ! from_conn | | ! data | | len < sizeof ( struct TOPOMSG _NAT_INFO) | | ! bgp - > local_node | | ! bgp - > local_node - > node ) return ;
const struct BGP _NAT_INFO* info = ( const struct BGP _NAT_INFO* ) data ;
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 ] ;
uint16_t nat_port = ntohs ( info - > nat_port ) ; uint8_t socket_id = info - > socket_id ;
@ -645,7 +640,7 @@ static void route_bgp_handle_nat_info(struct ROUTE_BGP* bgp, struct ETCP_CONN* f
else verified_type = NAT_VERIFIED_UNKNOWN ;
int data_changed = 0 ;
{ struct NI_IPV4_SOCKET_META * sm = bgp - > 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 = bgp - > 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 = bgp - > instance - > etcp_sockets ;
while ( es ) { if ( es - > sock_id = = socket_id ) {
@ -654,58 +649,58 @@ static void route_bgp_handle_nat_info(struct ROUTE_BGP* bgp, struct ETCP_CONN* f
es = es - > next ; }
if ( data_changed ) {
int prev_v4a = ni _list_count( ( struct _ni _head * ) bgp - > local_node - > node - > v4_addrs ) ;
route _bgp_update_my_nodeinfo( bgp - > instance , bgp ) ;
if ( ni _list_count( ( struct _ni _head * ) bgp - > local_node - > node - > v4_addrs ) ! = prev_v4a ) {
int prev_v4a = topo _list_count( ( struct _topo _head * ) bgp - > local_node - > node - > v4_addrs ) ;
topo _bgp_update_my_nodeinfo( bgp - > instance , bgp ) ;
if ( topo _list_count( ( struct _topo _head * ) bgp - > local_node - > node - > v4_addrs ) ! = prev_v4a ) {
bgp - > local_node - > dirty = 1 ;
bgp - > local_node - > node - > ver = ( bgp - > local_node - > node - > ver % 255 ) + 1 ;
bgp - > local_node - > last_ver = bgp - > local_node - > node - > ver ;
}
if ( bgp - > local_node - > dirty & & 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 ; }
while ( se ) { struct TOPO _BGP_CONN_ITEM* item = ( struct TOPO _BGP_CONN_ITEM* ) se - > data ; if ( item & & item - > conn ) topo _bgp_send_nodeinfo( bgp - > 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 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 ;
static void topo _bgp_handle_nat_check_req( struct TOPO _BGP* bgp , struct ETCP_CONN * from_conn , const uint8_t * data , size_t len ) {
if ( ! bgp | | ! 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 ;
route _bgp_start_link_nat_check( bgp , target_link ) ;
topo _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 topo _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) ) ; if ( ! pkt ) return ;
pkt - > cmd = ETCP_ID_ROUTE _ENTRY ; pkt - > subcmd = ROUTE _SUBCMD_NAT_INFO;
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;
pkt - > socket_id = socket_id ;
pkt - > nat_ip [ 0 ] = ( nat_ip > > 24 ) & 0xFF ; pkt - > nat_ip [ 1 ] = ( nat_ip > > 16 ) & 0xFF ;
pkt - > nat_ip [ 2 ] = ( nat_ip > > 8 ) & 0xFF ; pkt - > nat_ip [ 3 ] = nat_ip & 0xFF ;
pkt - > nat_port = htons ( nat_port ) ; pkt - > nat_type = nat_type ;
struct ll_entry * e = queue_entry_new ( 0 ) ; if ( ! e ) { u_free ( pkt ) ; return ; }
e - > dgram = ( uint8_t * ) pkt ; e - > len = sizeof ( struct BGP _NAT_INFO) ;
e - > dgram = ( uint8_t * ) pkt ; e - > len = sizeof ( struct TOPOMSG _NAT_INFO) ;
if ( etcp_send ( conn , e ) ! = 0 ) { DEBUG_ERROR ( DEBUG_CATEGORY_BGP , " etcp_send NAT_INFO failed " ) ; u_free ( pkt ) ; queue_entry_free ( e ) ; }
}
void route _bgp_send_nat_check_req( struct ETCP_CONN * conn , uint8_t socket_id ) {
void topo _bgp_send_nat_check_req( struct ETCP_CONN * conn , uint8_t socket_id ) {
if ( ! conn ) return ;
struct BGP _NAT_CHECK_REQ* pkt = u_calloc ( 1 , sizeof ( struct BGP _NAT_CHECK_REQ) ) ; if ( ! pkt ) return ;
pkt - > cmd = ETCP_ID_ROUTE _ENTRY ; pkt - > subcmd = ROUTE _SUBCMD_NAT_CHECK_REQ; pkt - > socket_id = socket_id ;
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 ;
struct ETCP_LINK * l = conn - > links ; while ( l ) { if ( l - > remote_socket_id = = socket_id ) { struct sockaddr_in * sin = ( struct sockaddr_in * ) & l - > conn - > interface_addr ; if ( sin - > sin_family = = AF_INET ) { pkt - > interface_ip = sin - > sin_addr . s_addr ; pkt - > interface_port = sin - > sin_port ; } break ; } l = l - > next ; }
struct ll_entry * e = queue_entry_new ( 0 ) ; if ( ! e ) { u_free ( pkt ) ; return ; }
e - > dgram = ( uint8_t * ) pkt ; e - > len = sizeof ( struct BGP _NAT_CHECK_REQ) ;
e - > dgram = ( uint8_t * ) pkt ; e - > len = sizeof ( struct TOPOMSG _NAT_CHECK_REQ) ;
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 route _bgp_request_nat_check_all( struct ROUTE _BGP* bgp ) {
void topo _bgp_request_nat_check_all( struct TOPO _BGP* bgp ) {
if ( ! bgp | | ! bgp - > 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 ) route _bgp_start_link_nat_check( bgp , link ) ; count + + ; link = link - > next ; } conn = conn - > next ; }
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 ; }
}