Initialize the federation of supernodes (#460)

* Add supernode2sock() and add_sn_to_federation_by_mac_or_sock()

* Update sn_utils.c

* Update sn.c and sn_utils.c

* Update REG_SUPER_ACK payload

* Update add_sn_to_federation_by_mac_or_sock()
This commit is contained in:
Francesco Carli 2020-10-11 11:44:40 +02:00 committed by GitHub
parent e3f64bfd1e
commit c9eedd68f0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 180 additions and 117 deletions

View File

@ -190,24 +190,26 @@ typedef char macstr_t[N2N_MACSTR_SIZE];
typedef char dec_ip_str_t[N2N_NETMASK_STR_SIZE]; typedef char dec_ip_str_t[N2N_NETMASK_STR_SIZE];
typedef char dec_ip_bit_str_t[N2N_NETMASK_STR_SIZE + 4]; typedef char dec_ip_bit_str_t[N2N_NETMASK_STR_SIZE + 4];
typedef struct speck_context_t he_context_t;
typedef char n2n_sn_name_t[N2N_EDGE_SN_HOST_SIZE];
struct peer_info { struct peer_info {
n2n_mac_t mac_addr; n2n_mac_t mac_addr;
n2n_ip_subnet_t dev_addr; n2n_ip_subnet_t dev_addr;
n2n_sock_t sock; n2n_sock_t sock;
int timeout; int timeout;
uint8_t purgeable;
time_t last_seen; time_t last_seen;
time_t last_p2p; time_t last_p2p;
time_t last_sent_query; time_t last_sent_query;
uint64_t last_valid_time_stamp; uint64_t last_valid_time_stamp;
char *ip_addr;
UT_hash_handle hh; /* makes this structure hashable */ UT_hash_handle hh; /* makes this structure hashable */
}; };
typedef struct speck_context_t he_context_t;
typedef char n2n_sn_name_t[N2N_EDGE_SN_HOST_SIZE];
typedef struct n2n_route { typedef struct n2n_route {
in_addr_t net_addr; in_addr_t net_addr;
uint8_t net_bitlen; uint8_t net_bitlen;
@ -396,7 +398,7 @@ typedef struct n2n_sn
int lock_communities; /* If true, only loaded and matching communities can be used. */ int lock_communities; /* If true, only loaded and matching communities can be used. */
struct sn_community *communities; struct sn_community *communities;
struct sn_community_regular_expression *rules; struct sn_community_regular_expression *rules;
char federation[N2N_COMMUNITY_SIZE]; struct sn_community *federation;
} n2n_sn_t; } n2n_sn_t;
/* ************************************** */ /* ************************************** */
@ -443,6 +445,7 @@ uint32_t bitlen2mask(uint8_t bitlen);
uint8_t mask2bitlen(uint32_t mask); uint8_t mask2bitlen(uint32_t mask);
char* macaddr_str(macstr_t buf, const n2n_mac_t mac); char* macaddr_str(macstr_t buf, const n2n_mac_t mac);
int str2mac( uint8_t * outmac /* 6 bytes */, const char * s ); int str2mac( uint8_t * outmac /* 6 bytes */, const char * s );
int supernode2sock(n2n_sock_t * sn, const n2n_sn_name_t addrIn);
uint8_t is_multi_broadcast(const uint8_t * dest_mac); uint8_t is_multi_broadcast(const uint8_t * dest_mac);
char* msg_type2str(uint16_t msg_type); char* msg_type2str(uint16_t msg_type);
void hexdump(const uint8_t * buf, size_t len); void hexdump(const uint8_t * buf, size_t len);
@ -497,6 +500,7 @@ int quick_edge_init(char *device_name, char *community_name,
int comm_init(struct sn_community *comm, char *cmn); int comm_init(struct sn_community *comm, char *cmn);
int sn_init(n2n_sn_t *sss); int sn_init(n2n_sn_t *sss);
void sn_term(n2n_sn_t *sss); void sn_term(n2n_sn_t *sss);
struct peer_info* add_sn_to_federation_by_mac_or_sock(n2n_sn_t *sss, n2n_sock_t *sock, n2n_mac_t *mac);
int run_sn_loop(n2n_sn_t *sss, int *keep_running); int run_sn_loop(n2n_sn_t *sss, int *keep_running);
int assign_one_ip_subnet(n2n_sn_t *sss, struct sn_community *comm); int assign_one_ip_subnet(n2n_sn_t *sss, struct sn_community *comm);
const char* compression_str(uint8_t cmpr); const char* compression_str(uint8_t cmpr);

View File

@ -169,8 +169,6 @@ typedef struct n2n_REGISTER_SUPER_ACK {
uint8_t num_sn; /**< Number of supernodes that were send uint8_t num_sn; /**< Number of supernodes that were send
* even if we cannot store them all. If * even if we cannot store them all. If
* non-zero then sn_bak is valid. */ * non-zero then sn_bak is valid. */
n2n_sock_t sn_bak; /**< Socket of the first backup supernode */
n2n_mac_t mac_addr;
} n2n_REGISTER_SUPER_ACK_t; } n2n_REGISTER_SUPER_ACK_t;

View File

@ -24,6 +24,7 @@
#define HASH_FIND_COMMUNITY(head, name, out) HASH_FIND_STR(head, name, out) #define HASH_FIND_COMMUNITY(head, name, out) HASH_FIND_STR(head, name, out)
static n2n_sn_t sss_node; static n2n_sn_t sss_node;
static const n2n_mac_t null_mac = {0, 0, 0, 0, 0, 0};
/** Load the list of allowed communities. Existing/previous ones will be removed /** Load the list of allowed communities. Existing/previous ones will be removed
* *
@ -176,8 +177,9 @@ static void help() {
"or\n" "or\n"
); );
printf("supernode "); printf("supernode ");
printf("-l <local port> "); printf("-p <local port> ");
printf("-c <path> "); printf("-c <path> ");
printf("-l <supernode:port> ");
#if defined(N2N_HAVE_DAEMON) #if defined(N2N_HAVE_DAEMON)
printf("[-f] "); printf("[-f] ");
#endif #endif
@ -191,8 +193,9 @@ static void help() {
printf("[-v] "); printf("[-v] ");
printf("\n\n"); printf("\n\n");
printf("-l <port> | Set UDP main listen port to <port>\n"); printf("-p <port> | Set UDP main listen port to <port>\n");
printf("-c <path> | File containing the allowed communities.\n"); printf("-c <path> | File containing the allowed communities.\n");
printf("-l <sn:port> | Supernode IP:port.\n");
#if defined(N2N_HAVE_DAEMON) #if defined(N2N_HAVE_DAEMON)
printf("-f | Run in foreground.\n"); printf("-f | Run in foreground.\n");
#endif /* #if defined(N2N_HAVE_DAEMON) */ #endif /* #if defined(N2N_HAVE_DAEMON) */
@ -219,7 +222,7 @@ static int setOption(int optkey, char *_optarg, n2n_sn_t *sss) {
//traceEvent(TRACE_NORMAL, "Option %c = %s", optkey, _optarg ? _optarg : ""); //traceEvent(TRACE_NORMAL, "Option %c = %s", optkey, _optarg ? _optarg : "");
switch (optkey) { switch (optkey) {
case 'l': /* local-port */ case 'p': /* local-port */
sss->lport = atoi(_optarg); sss->lport = atoi(_optarg);
break; break;
@ -227,6 +230,45 @@ static int setOption(int optkey, char *_optarg, n2n_sn_t *sss) {
sss->mport = atoi(_optarg); sss->mport = atoi(_optarg);
break; break;
case 'l': { /* supernode:port */
n2n_sock_t *socket;
struct peer_info *anchor_sn;
size_t length;
int rv;
length = strlen(_optarg);
if(length >= N2N_EDGE_SN_HOST_SIZE) {
traceEvent(TRACE_WARNING, "Size of -l argument too long: %zu. Maximum size is %d",length,N2N_EDGE_SN_HOST_SIZE);
break;
}
if(sss->federation != NULL) {
socket = (n2n_sock_t *)calloc(1,sizeof(n2n_sock_t));
anchor_sn = add_sn_to_federation_by_mac_or_sock(sss,socket, (n2n_mac_t*) null_mac);
if(anchor_sn != NULL){
anchor_sn->ip_addr = calloc(1,N2N_EDGE_SN_HOST_SIZE);
if(anchor_sn->ip_addr){
strncpy(anchor_sn->ip_addr,_optarg,N2N_EDGE_SN_HOST_SIZE-1);
rv = supernode2sock(socket,_optarg);
if(rv != 0){
traceEvent(TRACE_WARNING, "Invalid socket");
break;
}
memcpy(&(anchor_sn->sock), socket, sizeof(n2n_sock_t));
memcpy(&(anchor_sn->mac_addr),null_mac,sizeof(n2n_mac_t));
anchor_sn->purgeable = SN_UNPURGEABLE;
anchor_sn->last_valid_time_stamp = initial_time_stamp();
}
}
}
break;
}
case 'a': { case 'a': {
dec_ip_str_t ip_min_str = {'\0'}; dec_ip_str_t ip_min_str = {'\0'};
dec_ip_str_t ip_max_str = {'\0'}; dec_ip_str_t ip_max_str = {'\0'};
@ -280,15 +322,12 @@ static int setOption(int optkey, char *_optarg, n2n_sn_t *sss) {
#endif #endif
case 'F': { /* federation name */ case 'F': { /* federation name */
struct sn_community *fed;
HASH_FIND_COMMUNITY(sss->communities, FEDERATION_NAME, fed); if(sss->federation->community != NULL){
snprintf(sss->federation->community,N2N_COMMUNITY_SIZE-1,"*%s",_optarg);
if(fed != NULL){ sss->federation->community[N2N_COMMUNITY_SIZE-1] = '\0';
snprintf(fed->community,N2N_COMMUNITY_SIZE-1,"*%s",_optarg);
strncpy(sss->federation, fed->community, N2N_COMMUNITY_SIZE-1);
sss->federation[N2N_COMMUNITY_SIZE-1] = '\0';
} }
break; break;
} }
@ -327,7 +366,7 @@ static int setOption(int optkey, char *_optarg, n2n_sn_t *sss) {
static const struct option long_options[] = { static const struct option long_options[] = {
{"communities", required_argument, NULL, 'c'}, {"communities", required_argument, NULL, 'c'},
{"foreground", no_argument, NULL, 'f'}, {"foreground", no_argument, NULL, 'f'},
{"local-port", required_argument, NULL, 'l'}, {"local-port", required_argument, NULL, 'p'},
{"mgmt-port", required_argument, NULL, 't'}, {"mgmt-port", required_argument, NULL, 't'},
{"autoip", required_argument, NULL, 'a'}, {"autoip", required_argument, NULL, 'a'},
{"help", no_argument, NULL, 'h'}, {"help", no_argument, NULL, 'h'},
@ -341,7 +380,7 @@ static const struct option long_options[] = {
static int loadFromCLI(int argc, char * const argv[], n2n_sn_t *sss) { static int loadFromCLI(int argc, char * const argv[], n2n_sn_t *sss) {
u_char c; u_char c;
while((c = getopt_long(argc, argv, "fl:u:g:t:a:c:F:m:vh", while((c = getopt_long(argc, argv, "fp:l:u:g:t:a:c:F:m:vh",
long_options, NULL)) != '?') { long_options, NULL)) != '?') {
if(c == 255) break; if(c == 255) break;
setOption(c, optarg, sss); setOption(c, optarg, sss);
@ -437,26 +476,15 @@ static int loadFromFile(const char *path, n2n_sn_t *sss) {
/* Add the federation to the communities list of a supernode */ /* Add the federation to the communities list of a supernode */
static int add_federation_to_communities(n2n_sn_t *sss){ static int add_federation_to_communities(n2n_sn_t *sss){
struct sn_community *fed;
uint32_t num_communities = 0; uint32_t num_communities = 0;
fed = (struct sn_community *)calloc(1,sizeof(struct sn_community)); if(sss->federation != NULL) {
comm_init(fed,sss->federation); HASH_ADD_STR(sss->communities, community, sss->federation);
if(fed != NULL) {
/* enable the flag for federation */
fed->is_federation = IS_FEDERATION;
fed->purgeable = COMMUNITY_UNPURGEABLE;
/* header encryption enabled by default */
fed->header_encryption = HEADER_ENCRYPTION_ENABLED;
/*setup the encryption key */
packet_header_setup_key(fed->community, &(fed->header_encryption_ctx), &(fed->header_iv_ctx));
HASH_ADD_STR(sss->communities, community, fed);
num_communities = HASH_COUNT(sss->communities); num_communities = HASH_COUNT(sss->communities);
traceEvent(TRACE_INFO, "Added federation '%s' to the list of communities [total: %u]", traceEvent(TRACE_INFO, "Added federation '%s' to the list of communities [total: %u]",
(char*)fed->community, num_communities); (char*)sss->federation->community, num_communities);
} }
return 0; return 0;
@ -615,5 +643,3 @@ int main(int argc, char * const argv[]) {
keep_running = 1; keep_running = 1;
return run_sn_loop(&sss_node, &keep_running); return run_sn_loop(&sss_node, &keep_running);
} }

View File

@ -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);
HASH_ITER(hh, fed->edges, peer, tmp_peer) { tmp_sock = (void*)tmpbuf;
tmp_mac = (void*)tmpbuf + sizeof(n2n_sock_t);
// REVISIT: consider adding last_seen
/* 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 */