|
@ -52,10 +52,6 @@ static int update_edge(n2n_sn_t *sss, |
|
|
const n2n_sock_t *sender_sock, |
|
|
const n2n_sock_t *sender_sock, |
|
|
time_t now); |
|
|
time_t now); |
|
|
|
|
|
|
|
|
static int re_register_and_purge_supernodes(n2n_sn_t *sss, |
|
|
|
|
|
struct sn_community *comm, |
|
|
|
|
|
time_t now); |
|
|
|
|
|
|
|
|
|
|
|
static int purge_expired_communities(n2n_sn_t *sss, |
|
|
static int purge_expired_communities(n2n_sn_t *sss, |
|
|
time_t* p_last_purge, |
|
|
time_t* p_last_purge, |
|
|
time_t now); |
|
|
time_t now); |
|
@ -70,16 +66,14 @@ static int process_mgmt(n2n_sn_t *sss, |
|
|
size_t mgmt_size, |
|
|
size_t mgmt_size, |
|
|
time_t now); |
|
|
time_t now); |
|
|
|
|
|
|
|
|
static int add_sn_to_federation_from_register_super_ack(n2n_sn_t *sss, |
|
|
|
|
|
n2n_REGISTER_SUPER_ACK_t ack, |
|
|
|
|
|
time_t now); |
|
|
|
|
|
|
|
|
|
|
|
static int process_udp(n2n_sn_t *sss, |
|
|
static int process_udp(n2n_sn_t *sss, |
|
|
const struct sockaddr_in *sender_sock, |
|
|
const struct sockaddr_in *sender_sock, |
|
|
uint8_t *udp_buf, |
|
|
uint8_t *udp_buf, |
|
|
size_t udp_size, |
|
|
size_t udp_size, |
|
|
time_t now); |
|
|
time_t now); |
|
|
|
|
|
|
|
|
|
|
|
static const n2n_mac_t null_mac = {0, 0, 0, 0, 0, 0}; |
|
|
|
|
|
|
|
|
/* ************************************** */ |
|
|
/* ************************************** */ |
|
|
|
|
|
|
|
|
static int try_forward(n2n_sn_t * sss, |
|
|
static int try_forward(n2n_sn_t * sss, |
|
@ -244,8 +238,20 @@ int sn_init(n2n_sn_t *sss) { |
|
|
sss->max_auto_ip_net.net_addr = inet_addr(N2N_SN_MAX_AUTO_IP_NET_DEFAULT); |
|
|
sss->max_auto_ip_net.net_addr = inet_addr(N2N_SN_MAX_AUTO_IP_NET_DEFAULT); |
|
|
sss->max_auto_ip_net.net_addr = ntohl(sss->max_auto_ip_net.net_addr); |
|
|
sss->max_auto_ip_net.net_addr = ntohl(sss->max_auto_ip_net.net_addr); |
|
|
sss->max_auto_ip_net.net_bitlen = N2N_SN_AUTO_IP_NET_BIT_DEFAULT; |
|
|
sss->max_auto_ip_net.net_bitlen = N2N_SN_AUTO_IP_NET_BIT_DEFAULT; |
|
|
strncpy(sss->federation, (char*)FEDERATION_NAME, N2N_COMMUNITY_SIZE-1); |
|
|
sss->federation = (struct sn_community *)calloc(1,sizeof(struct sn_community)); |
|
|
sss->federation[N2N_COMMUNITY_SIZE-1] = '\0'; |
|
|
|
|
|
|
|
|
/* Initialize the federation */ |
|
|
|
|
|
if(sss->federation){ |
|
|
|
|
|
strncpy(sss->federation->community, (char*)FEDERATION_NAME, N2N_COMMUNITY_SIZE-1); |
|
|
|
|
|
sss->federation->community[N2N_COMMUNITY_SIZE-1] = '\0'; |
|
|
|
|
|
/* enable the flag for federation */ |
|
|
|
|
|
sss->federation->is_federation = IS_FEDERATION; |
|
|
|
|
|
sss->federation->purgeable = COMMUNITY_UNPURGEABLE; |
|
|
|
|
|
/* header encryption enabled by default */ |
|
|
|
|
|
sss->federation->header_encryption = HEADER_ENCRYPTION_ENABLED; |
|
|
|
|
|
/*setup the encryption key */ |
|
|
|
|
|
packet_header_setup_key(sss->federation->community, &(sss->federation->header_encryption_ctx), &(sss->federation->header_iv_ctx)); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
n2n_srand (n2n_seed()); |
|
|
n2n_srand (n2n_seed()); |
|
|
|
|
|
|
|
@ -513,7 +519,7 @@ static int re_register_and_purge_supernodes(n2n_sn_t *sss, struct sn_community * |
|
|
HASH_ITER(hh,comm->edges,peer,tmp){ |
|
|
HASH_ITER(hh,comm->edges,peer,tmp){ |
|
|
time = now - peer->last_seen; |
|
|
time = now - peer->last_seen; |
|
|
if(time <= ALLOWED_TIME) continue; |
|
|
if(time <= ALLOWED_TIME) continue; |
|
|
if((time > ALLOWED_TIME) && (time < PURGE_FEDERATION_NODE_INTERVAL)){ /* re-regitser (send REGISTER_SUPER) */ |
|
|
if((time < PURGE_FEDERATION_NODE_INTERVAL) || (peer->purgeable == SN_UNPURGEABLE)){ /* re-regitser (send REGISTER_SUPER) */ |
|
|
uint8_t pktbuf[N2N_PKT_BUF_SIZE] = {0}; |
|
|
uint8_t pktbuf[N2N_PKT_BUF_SIZE] = {0}; |
|
|
size_t idx; |
|
|
size_t idx; |
|
|
/* ssize_t sent; */ |
|
|
/* ssize_t sent; */ |
|
@ -724,43 +730,45 @@ static int sendto_mgmt(n2n_sn_t *sss, |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** Iterate through REGISTER_SUPER_ACK payload and add new supernodes with a legal timestamp
|
|
|
/** Search for a node in the federation list. If it has to add a new node, it creates a new peer_info and initializes it
|
|
|
* (half of the difference between the adjustable 20 seconds and 90 seconds limit) to the federation list |
|
|
* Evaluate first the MAC parameter and if it's zero-MAC, then it can skip HASH_FIND_PEER by MAC and search by socket |
|
|
*/ |
|
|
*/ |
|
|
static int add_sn_to_federation_from_register_super_ack(n2n_sn_t *sss, n2n_REGISTER_SUPER_ACK_t ack, time_t now){ |
|
|
struct peer_info* add_sn_to_federation_by_mac_or_sock(n2n_sn_t *sss,n2n_sock_t *sock, n2n_mac_t *mac){ |
|
|
struct sn_community *fed; |
|
|
struct peer_info *scan, *tmp, *peer; |
|
|
struct peer_info *peer; |
|
|
int found = 0; |
|
|
n2n_sock_t *tmp_sock; |
|
|
|
|
|
n2n_mac_t *tmp_mac; |
|
|
|
|
|
int i; |
|
|
|
|
|
|
|
|
|
|
|
HASH_FIND_COMMUNITY(sss->communities, sss->federation, fed); |
|
|
if(sss->federation != NULL){ |
|
|
|
|
|
if(memcmp(mac,null_mac,sizeof(n2n_mac_t)) != 0){ /* not zero MAC */ |
|
|
|
|
|
HASH_FIND_PEER(sss->federation->edges, mac, peer); |
|
|
|
|
|
|
|
|
|
|
|
//REVISIT: make this dependent from last_seen and update socket
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if(peer == NULL){ /* zero MAC, search by socket */ |
|
|
|
|
|
HASH_ITER(hh,sss->federation->edges,scan,tmp){ |
|
|
|
|
|
if(memcmp(&(scan->sock), sock, sizeof(n2n_sock_t))){ |
|
|
|
|
|
memcpy(&(scan->mac_addr), sock, sizeof(n2n_mac_t)); |
|
|
|
|
|
peer = scan; |
|
|
|
|
|
break; |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
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){ |
|
|
if(peer == NULL){ |
|
|
peer = (struct peer_info*)calloc(1,sizeof(struct peer_info)); |
|
|
peer = (struct peer_info*)calloc(1,sizeof(struct peer_info)); |
|
|
memcpy(&(peer->sock),tmp_sock,sizeof(n2n_sock_t)); |
|
|
if(peer){ |
|
|
memcpy(&(peer->mac_addr), &tmp_mac, sizeof(n2n_mac_t)); |
|
|
memcpy(&(peer->sock),sock,sizeof(n2n_sock_t)); |
|
|
peer->dev_addr.net_addr = ntohs(ack.dev_addr.net_addr); |
|
|
memcpy(&(peer->mac_addr),mac, sizeof(n2n_mac_t)); |
|
|
peer->dev_addr.net_bitlen = mask2bitlen(ntohl(ack.dev_addr.net_bitlen)); |
|
|
HASH_ADD_PEER(sss->federation->edges,peer); |
|
|
peer->last_seen = now - TEST_TIME; |
|
|
} |
|
|
HASH_ADD_PEER(fed->edges, peer); |
|
|
|
|
|
} |
|
|
} |
|
|
tmp_sock += sizeof(n2n_mac_t); |
|
|
|
|
|
tmp_mac += sizeof(n2n_sock_t); |
|
|
|
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
return 0; /* OK */ |
|
|
return peer; |
|
|
|
|
|
|
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** Examine a datagram and determine what to do with it.
|
|
|
/** Examine a datagram and determine what to do with it.
|
|
|
* |
|
|
* |
|
|
*/ |
|
|
*/ |
|
@ -1044,6 +1052,7 @@ static int process_udp(n2n_sn_t * sss, |
|
|
n2n_REGISTER_SUPER_ACK_t ack; |
|
|
n2n_REGISTER_SUPER_ACK_t ack; |
|
|
n2n_common_t cmn2; |
|
|
n2n_common_t cmn2; |
|
|
uint8_t ackbuf[N2N_SN_PKTBUF_SIZE]; |
|
|
uint8_t ackbuf[N2N_SN_PKTBUF_SIZE]; |
|
|
|
|
|
uint8_t tmpbuf[MAX_AVAILABLE_SPACE_FOR_ENTRIES]; |
|
|
size_t encx=0; |
|
|
size_t encx=0; |
|
|
struct sn_community *fed; |
|
|
struct sn_community *fed; |
|
|
struct sn_community_regular_expression *re, *tmp_re; |
|
|
struct sn_community_regular_expression *re, *tmp_re; |
|
@ -1122,7 +1131,6 @@ static int process_udp(n2n_sn_t * sss, |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
if(comm) { |
|
|
if(comm) { |
|
|
HASH_FIND_COMMUNITY(sss->communities, sss->federation, fed); |
|
|
|
|
|
cmn2.ttl = N2N_DEFAULT_TTL; |
|
|
cmn2.ttl = N2N_DEFAULT_TTL; |
|
|
cmn2.pc = n2n_register_super_ack; |
|
|
cmn2.pc = n2n_register_super_ack; |
|
|
cmn2.flags = N2N_FLAGS_SOCKET | N2N_FLAGS_FROM_SUPERNODE; |
|
|
cmn2.flags = N2N_FLAGS_SOCKET | N2N_FLAGS_FROM_SUPERNODE; |
|
@ -1143,24 +1151,28 @@ static int process_udp(n2n_sn_t * sss, |
|
|
ack.sock.port = ntohs(sender_sock->sin_port); |
|
|
ack.sock.port = ntohs(sender_sock->sin_port); |
|
|
memcpy(ack.sock.addr.v4, &(sender_sock->sin_addr.s_addr), IPV4_SIZE); |
|
|
memcpy(ack.sock.addr.v4, &(sender_sock->sin_addr.s_addr), IPV4_SIZE); |
|
|
|
|
|
|
|
|
if(fed != NULL){ |
|
|
/* Add sender's data to federation (or update it) */ |
|
|
HASH_FIND_PEER(fed->edges, reg.edgeMac, p); |
|
|
if(comm->is_federation == IS_FEDERATION){ |
|
|
if(p != NULL){ |
|
|
p = add_sn_to_federation_by_mac_or_sock(sss,&(ack.sock),&(reg.edgeMac)); |
|
|
p->last_seen = now; |
|
|
if(p) p->last_seen = now; |
|
|
tmp_sock = &(ack.sn_bak); |
|
|
} |
|
|
tmp_mac = &(ack.mac_addr); |
|
|
|
|
|
|
|
|
tmp_sock = (void*)tmpbuf; |
|
|
|
|
|
tmp_mac = (void*)tmpbuf + sizeof(n2n_sock_t); |
|
|
|
|
|
|
|
|
|
|
|
// REVISIT: consider adding last_seen
|
|
|
|
|
|
|
|
|
HASH_ITER(hh, fed->edges, peer, tmp_peer) { |
|
|
/* Assembling supernode list for REGISTER_SUPER_ACK payload */ |
|
|
|
|
|
HASH_ITER(hh, sss->federation->edges, peer, tmp_peer) { |
|
|
if((now - peer->last_seen) >= ALLOWED_TIME) continue; /* skip long-time-not-seen supernodes */ |
|
|
if((now - peer->last_seen) >= ALLOWED_TIME) continue; /* skip long-time-not-seen supernodes */ |
|
|
if(((++num)*ENTRY_SIZE) > MAX_AVAILABLE_SPACE_FOR_ENTRIES) break; /* no more space available in REGISTER_SUPER_ACK payload */ |
|
|
if(((++num)*ENTRY_SIZE) > MAX_AVAILABLE_SPACE_FOR_ENTRIES) break; /* no more space available in REGISTER_SUPER_ACK payload */ |
|
|
memcpy(tmp_sock, &(peer->sock), sizeof(n2n_sock_t)); |
|
|
memcpy((void*)tmpbuf, (void*)&(peer->sock), sizeof(n2n_sock_t)); |
|
|
memcpy(tmp_mac, &(peer->mac_addr), sizeof(n2n_mac_t)); |
|
|
memcpy((void*)tmpbuf, (void*)&(peer->mac_addr), sizeof(n2n_mac_t)); |
|
|
tmp_sock += sizeof(n2n_mac_t); |
|
|
tmp_sock += ENTRY_SIZE; |
|
|
tmp_mac += sizeof(n2n_sock_t); |
|
|
tmp_mac += ENTRY_SIZE; |
|
|
} |
|
|
} |
|
|
ack.num_sn = num; |
|
|
ack.num_sn = num; |
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
traceEvent(TRACE_DEBUG, "Rx REGISTER_SUPER for %s [%s]", |
|
|
traceEvent(TRACE_DEBUG, "Rx REGISTER_SUPER for %s [%s]", |
|
|
macaddr_str(mac_buf, reg.edgeMac), |
|
|
macaddr_str(mac_buf, reg.edgeMac), |
|
@ -1171,6 +1183,7 @@ static int process_udp(n2n_sn_t * sss, |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
encode_REGISTER_SUPER_ACK(ackbuf, &encx, &cmn2, &ack); |
|
|
encode_REGISTER_SUPER_ACK(ackbuf, &encx, &cmn2, &ack); |
|
|
|
|
|
encode_buf(ackbuf,&encx,tmpbuf,(num*ENTRY_SIZE)); |
|
|
|
|
|
|
|
|
if (comm->header_encryption == HEADER_ENCRYPTION_ENABLED) |
|
|
if (comm->header_encryption == HEADER_ENCRYPTION_ENABLED) |
|
|
packet_header_encrypt (ackbuf, encx, comm->header_encryption_ctx, |
|
|
packet_header_encrypt (ackbuf, encx, comm->header_encryption_ctx, |
|
@ -1194,12 +1207,15 @@ static int process_udp(n2n_sn_t * sss, |
|
|
n2n_REGISTER_SUPER_ACK_t ack; |
|
|
n2n_REGISTER_SUPER_ACK_t ack; |
|
|
size_t encx=0; |
|
|
size_t encx=0; |
|
|
struct sn_community *fed; |
|
|
struct sn_community *fed; |
|
|
struct peer_info *scan; |
|
|
struct peer_info *scan, *tmp; |
|
|
n2n_sock_str_t sockbuf1; |
|
|
n2n_sock_str_t sockbuf1; |
|
|
n2n_sock_str_t sockbuf2; |
|
|
n2n_sock_str_t sockbuf2; |
|
|
macstr_t mac_buf1; |
|
|
macstr_t mac_buf1; |
|
|
n2n_sock_t sender; |
|
|
n2n_sock_t sender; |
|
|
n2n_sock_t *orig_sender; |
|
|
n2n_sock_t *orig_sender; |
|
|
|
|
|
n2n_sock_t *tmp_sock; |
|
|
|
|
|
n2n_mac_t *tmp_mac; |
|
|
|
|
|
int i; |
|
|
|
|
|
|
|
|
sender.family = AF_INET; |
|
|
sender.family = AF_INET; |
|
|
sender.port = ntohs(sender_sock->sin_port); |
|
|
sender.port = ntohs(sender_sock->sin_port); |
|
@ -1208,6 +1224,11 @@ static int process_udp(n2n_sn_t * sss, |
|
|
|
|
|
|
|
|
memset(&ack, 0, sizeof(n2n_REGISTER_SUPER_ACK_t)); |
|
|
memset(&ack, 0, sizeof(n2n_REGISTER_SUPER_ACK_t)); |
|
|
|
|
|
|
|
|
|
|
|
if(!comm) { |
|
|
|
|
|
traceEvent(TRACE_DEBUG, "process_udp REGISTER_SUPER_ACK with unknown community %s", cmn.community); |
|
|
|
|
|
return -1; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
if(from_supernode != comm->is_federation){ |
|
|
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."); |
|
|
traceEvent(TRACE_DEBUG, "process_udp dropped REGISTER_SUPER_ACK: from_supernode value doesn't correspond to the internal federation marking."); |
|
|
return -1; |
|
|
return -1; |
|
@ -1226,20 +1247,33 @@ static int process_udp(n2n_sn_t * sss, |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
traceEvent(TRACE_INFO, "Rx REGISTER_SUPER_ACK myMAC=%s [%s] (external %s)", |
|
|
traceEvent(TRACE_INFO, "Rx REGISTER_SUPER_ACK myMAC=%s [%s] (external %s)", |
|
|
macaddr_str(mac_buf1, ack.mac_addr), |
|
|
macaddr_str(mac_buf1, ack.edgeMac), |
|
|
sock_to_cstr(sockbuf1, &sender), |
|
|
sock_to_cstr(sockbuf1, &sender), |
|
|
sock_to_cstr(sockbuf2, orig_sender)); |
|
|
sock_to_cstr(sockbuf2, orig_sender)); |
|
|
|
|
|
|
|
|
HASH_FIND_COMMUNITY(sss->communities, sss->federation, fed); |
|
|
if(comm->is_federation == IS_FEDERATION) { |
|
|
|
|
|
HASH_FIND_PEER(sss->federation->edges, ack.edgeMac, scan); |
|
|
if(fed != NULL) { |
|
|
|
|
|
HASH_FIND_PEER(fed->edges, ack.edgeMac, scan); |
|
|
|
|
|
if(scan != NULL){ |
|
|
if(scan != NULL){ |
|
|
scan->last_seen = now; |
|
|
scan->last_seen = now; |
|
|
|
|
|
} else { |
|
|
|
|
|
traceEvent(TRACE_DEBUG, "process_udp dropped REGISTER_SUPER_ACK due to an unknown supernode."); |
|
|
|
|
|
break; |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
if(ack.num_sn > 0) add_sn_to_federation_from_register_super_ack(sss,ack,now); |
|
|
tmp_sock = (void*)&(ack.num_sn) + sizeof(ack.num_sn); |
|
|
|
|
|
tmp_mac = (void*)tmp_sock + sizeof(n2n_sock_t); |
|
|
|
|
|
|
|
|
|
|
|
for(i=0; i<ack.num_sn; i++){ |
|
|
|
|
|
tmp = add_sn_to_federation_by_mac_or_sock(sss,tmp_sock,tmp_mac); |
|
|
|
|
|
|
|
|
|
|
|
if(tmp){ |
|
|
|
|
|
tmp->last_seen = now - TEST_TIME; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
tmp_sock += ENTRY_SIZE; |
|
|
|
|
|
tmp_mac += ENTRY_SIZE; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
break; |
|
|
break; |
|
|
} |
|
|
} |
|
@ -1400,6 +1434,7 @@ int run_sn_loop(n2n_sn_t *sss, int *keep_running) |
|
|
traceEvent(TRACE_DEBUG, "timeout"); |
|
|
traceEvent(TRACE_DEBUG, "timeout"); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
re_register_and_purge_supernodes(sss, sss->federation, now); |
|
|
purge_expired_communities(sss, &last_purge_edges, now); |
|
|
purge_expired_communities(sss, &last_purge_edges, now); |
|
|
sort_communities (sss, &last_sort_communities, now); |
|
|
sort_communities (sss, &last_sort_communities, now); |
|
|
} /* while */ |
|
|
} /* while */ |
|
|