mirror of
https://github.com/ntop/n2n.git
synced 2024-09-19 16:41:11 +02:00
Implement purge-and-re-registration process for supernodes (#445)
This commit is contained in:
parent
3f8d32fa77
commit
8dfffd9fbe
|
@ -467,7 +467,7 @@ int time_stamp_verify_and_update (uint64_t stamp, uint64_t * previous_stamp, int
|
|||
size_t purge_peer_list( struct peer_info ** peer_list,
|
||||
time_t purge_before );
|
||||
size_t clear_peer_list( struct peer_info ** peer_list );
|
||||
size_t purge_expired_registrations( struct peer_info ** peer_list, time_t* p_last_purge );
|
||||
size_t purge_expired_registrations( struct peer_info ** peer_list, time_t* p_last_purge, int timeout );
|
||||
|
||||
/* Edge conf */
|
||||
void edge_init_conf_defaults(n2n_edge_conf_t *conf);
|
||||
|
|
|
@ -40,13 +40,14 @@
|
|||
#define SOCKET_TIMEOUT_INTERVAL_SECS 10
|
||||
#define REGISTER_SUPER_INTERVAL_DFL 20 /* sec, usually UDP NAT entries in a firewall expire after 30 seconds */
|
||||
#define ALLOWED_TIME 20 /* sec, indicates supernodes that are proven to be alive */
|
||||
#define TEST_TIME (SORT_COMMUNITIES_INTERVAL - ALLOWED_TIME)/2 /* sec, indicates supernodes with unsure status, must be tested to check if they are alive */
|
||||
#define TEST_TIME (PURGE_FEDERATION_NODE_INTERVAL - ALLOWED_TIME)/2 /* sec, indicates supernodes with unsure status, must be tested to check if they are alive */
|
||||
|
||||
#define IFACE_UPDATE_INTERVAL (30) /* sec. How long it usually takes to get an IP lease. */
|
||||
#define TRANSOP_TICK_INTERVAL (10) /* sec */
|
||||
|
||||
#define PURGE_REGISTRATION_FREQUENCY 30
|
||||
#define REGISTRATION_TIMEOUT 60
|
||||
#define PURGE_FEDERATION_NODE_INTERVAL 90
|
||||
|
||||
#define SORT_COMMUNITIES_INTERVAL 90 /* sec. until supernode sorts communities' hash list again */
|
||||
|
||||
|
|
|
@ -2139,8 +2139,8 @@ int run_edge_loop(n2n_edge_t * eee, int *keep_running) {
|
|||
/* Finished processing select data. */
|
||||
update_supernode_reg(eee, nowTime);
|
||||
|
||||
numPurged = purge_expired_registrations(&eee->known_peers, &last_purge_known);
|
||||
numPurged += purge_expired_registrations(&eee->pending_peers, &last_purge_pending);
|
||||
numPurged = purge_expired_registrations(&eee->known_peers, &last_purge_known, PURGE_REGISTRATION_FREQUENCY);
|
||||
numPurged += purge_expired_registrations(&eee->pending_peers, &last_purge_pending, PURGE_REGISTRATION_FREQUENCY);
|
||||
|
||||
if(numPurged > 0) {
|
||||
traceEvent(TRACE_INFO, "%u peers removed. now: pending=%u, operational=%u",
|
||||
|
|
|
@ -280,11 +280,11 @@ void print_n2n_version() {
|
|||
|
||||
/* *********************************************** */
|
||||
|
||||
size_t purge_expired_registrations(struct peer_info ** peer_list, time_t* p_last_purge) {
|
||||
size_t purge_expired_registrations(struct peer_info ** peer_list, time_t* p_last_purge, int timeout) {
|
||||
time_t now = time(NULL);
|
||||
size_t num_reg = 0;
|
||||
|
||||
if((now - (*p_last_purge)) < PURGE_REGISTRATION_FREQUENCY) return 0;
|
||||
if((now - (*p_last_purge)) < timeout) return 0;
|
||||
|
||||
traceEvent(TRACE_DEBUG, "Purging old registrations");
|
||||
|
||||
|
|
147
src/sn_utils.c
147
src/sn_utils.c
|
@ -496,6 +496,62 @@ static int find_edge_time_stamp_and_verify (struct peer_info * edges,
|
|||
return ( time_stamp_verify_and_update (stamp, previous_stamp, allow_jitter) );
|
||||
}
|
||||
|
||||
|
||||
static int re_register_and_purge_supernodes(n2n_sn_t *sss, struct sn_community *comm, time_t now){
|
||||
time_t time;
|
||||
struct peer_info *peer, *tmp;
|
||||
|
||||
if(comm != NULL){
|
||||
HASH_ITER(hh,comm->edges,peer,tmp){
|
||||
time = now - peer->last_seen;
|
||||
if(time <= ALLOWED_TIME) continue;
|
||||
if((time > ALLOWED_TIME) && (time < PURGE_FEDERATION_NODE_INTERVAL)){ /* re-regitser (send REGISTER_SUPER) */
|
||||
uint8_t pktbuf[N2N_PKT_BUF_SIZE] = {0};
|
||||
size_t idx;
|
||||
/* ssize_t sent; */
|
||||
n2n_common_t cmn;
|
||||
n2n_cookie_t cookie;
|
||||
n2n_REGISTER_SUPER_t reg;
|
||||
n2n_sock_str_t sockbuf;
|
||||
|
||||
memset(&cmn, 0, sizeof(cmn));
|
||||
memset(®, 0, sizeof(reg));
|
||||
|
||||
cmn.ttl = N2N_DEFAULT_TTL;
|
||||
cmn.pc = n2n_register_super;
|
||||
cmn.flags = 0;
|
||||
memcpy(cmn.community, comm->community, N2N_COMMUNITY_SIZE);
|
||||
|
||||
for (idx = 0; idx < N2N_COOKIE_SIZE; ++idx) /* aggiungi sn_idx */
|
||||
cookie[idx] = n2n_rand() % 0xff;
|
||||
|
||||
memcpy(reg.cookie, cookie, N2N_COOKIE_SIZE);
|
||||
reg.dev_addr.net_addr = ntohl(peer->dev_addr.net_addr);
|
||||
reg.dev_addr.net_bitlen = mask2bitlen(ntohl(peer->dev_addr.net_bitlen));
|
||||
reg.auth.scheme = 0; /* No auth yet */
|
||||
|
||||
idx = 0;
|
||||
encode_mac(reg.edgeMac, &idx, peer->mac_addr);
|
||||
|
||||
idx = 0;
|
||||
encode_REGISTER_SUPER(pktbuf, &idx, &cmn, ®);
|
||||
|
||||
traceEvent(TRACE_DEBUG, "send REGISTER_SUPER to %s",
|
||||
sock_to_cstr(sockbuf, &(peer->sock)));
|
||||
|
||||
packet_header_encrypt(pktbuf, idx, comm->header_encryption_ctx,
|
||||
comm->header_iv_ctx,
|
||||
time_stamp(), pearson_hash_16(pktbuf, idx));
|
||||
|
||||
/* sent = */ sendto_sock(sss, &(peer->sock), pktbuf, N2N_PKT_BUF_SIZE);
|
||||
}
|
||||
if(time >= PURGE_FEDERATION_NODE_INTERVAL) purge_expired_registrations(&(comm->edges),&time,PURGE_FEDERATION_NODE_INTERVAL);/* purge not-seen-long-time supernodes*/
|
||||
}
|
||||
}
|
||||
|
||||
return 0; /* OK */
|
||||
}
|
||||
|
||||
static int purge_expired_communities(n2n_sn_t *sss,
|
||||
time_t* p_last_purge,
|
||||
time_t now)
|
||||
|
@ -659,6 +715,44 @@ static int sendto_mgmt(n2n_sn_t *sss,
|
|||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/** Iterate through REGISTER_SUPER_ACK payload and add new supernodes with a legal timestamp
|
||||
* (half of the difference between the adjustable 20 seconds and 90 seconds limit) to the federation list
|
||||
*/
|
||||
static int add_sn_to_federation_from_register_super_ack(n2n_sn_t *sss, n2n_REGISTER_SUPER_ACK_t ack){
|
||||
struct sn_community *fed;
|
||||
struct peer_info *peer;
|
||||
n2n_sock_t *tmp_sock;
|
||||
n2n_mac_t *tmp_mac;
|
||||
int i;
|
||||
|
||||
HASH_FIND_COMMUNITY(sss->communities, sss->federation, fed);
|
||||
|
||||
if(fed != NULL){
|
||||
tmp_sock = &(ack.sn_bak);
|
||||
tmp_mac = &(ack.mac_addr);
|
||||
for(i=0; i<ack.num_sn; i++){
|
||||
HASH_FIND_PEER(fed->edges, &tmp_mac, peer);
|
||||
if(peer == NULL){
|
||||
peer = (struct peer_info *)calloc(1,sizeof(struct peer_info));
|
||||
memcpy(&(peer->sock),tmp_sock,sizeof(n2n_sock_t));
|
||||
memcpy(&(peer->mac_addr), &tmp_mac, sizeof(n2n_mac_t));
|
||||
peer->dev_addr.net_addr = ntohs(ack.dev_addr.net_addr);
|
||||
peer->dev_addr.net_bitlen = mask2bitlen(ntohl(ack.dev_addr.net_bitlen));
|
||||
peer->last_seen = TEST_TIME;
|
||||
HASH_ADD_PEER(fed->edges, peer);
|
||||
}
|
||||
tmp_sock += sizeof(n2n_mac_t);
|
||||
tmp_mac += sizeof(n2n_sock_t);
|
||||
}
|
||||
}
|
||||
|
||||
return 0; /* OK */
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/** Examine a datagram and determine what to do with it.
|
||||
*
|
||||
*/
|
||||
|
@ -1086,6 +1180,59 @@ static int process_udp(n2n_sn_t * sss,
|
|||
}
|
||||
break;
|
||||
}
|
||||
case MSG_TYPE_REGISTER_SUPER_ACK: {
|
||||
n2n_REGISTER_SUPER_ACK_t ack;
|
||||
size_t encx=0;
|
||||
struct sn_community *fed;
|
||||
struct peer_info *scan;
|
||||
n2n_sock_str_t sockbuf1;
|
||||
n2n_sock_str_t sockbuf2;
|
||||
macstr_t mac_buf1;
|
||||
n2n_sock_t sender;
|
||||
n2n_sock_t *orig_sender;
|
||||
|
||||
sender.family = AF_INET;
|
||||
sender.port = ntohs(sender_sock->sin_port);
|
||||
memcpy(&(sender.addr.v4), &(sender_sock->sin_addr.s_addr), IPV4_SIZE);
|
||||
orig_sender = &sender;
|
||||
|
||||
memset(&ack, 0, sizeof(n2n_REGISTER_SUPER_ACK_t));
|
||||
|
||||
if(from_supernode != comm->is_federation){
|
||||
traceEvent(TRACE_DEBUG, "process_udp dropped REGISTER_SUPER_ACK: from_supernode value doesn't correspond to the internal federation marking.");
|
||||
return -1;
|
||||
}
|
||||
|
||||
decode_REGISTER_SUPER_ACK(&ack,&cmn,udp_buf,&rem,&idx);
|
||||
orig_sender = &(ack.sock);
|
||||
|
||||
if (comm) {
|
||||
if(comm->header_encryption == HEADER_ENCRYPTION_ENABLED) {
|
||||
if(!find_edge_time_stamp_and_verify (comm->edges, from_supernode, ack.edgeMac, stamp, TIME_STAMP_NO_JITTER)) {
|
||||
traceEvent(TRACE_DEBUG, "process_udp dropped REGISTER_SUPER_ACK due to time stamp error.");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
traceEvent(TRACE_INFO, "Rx REGISTER_SUPER_ACK myMAC=%s [%s] (external %s)",
|
||||
macaddr_str(mac_buf1, ack.mac_addr),
|
||||
sock_to_cstr(sockbuf1, &sender),
|
||||
sock_to_cstr(sockbuf2, orig_sender));
|
||||
|
||||
HASH_FIND_COMMUNITY(sss->communities, sss->federation, fed);
|
||||
|
||||
if(fed != NULL) {
|
||||
HASH_FIND_PEER(fed->edges, ack.edgeMac, scan);
|
||||
if(scan != NULL){
|
||||
scan->last_seen = now;
|
||||
}
|
||||
}
|
||||
|
||||
if(ack.num_sn > 0) add_sn_to_federation_from_register_super_ack(sss,ack);
|
||||
|
||||
break;
|
||||
}
|
||||
case MSG_TYPE_QUERY_PEER: {
|
||||
n2n_QUERY_PEER_t query;
|
||||
uint8_t encbuf[N2N_SN_PKTBUF_SIZE];
|
||||
|
|
Loading…
Reference in New Issue
Block a user