mirror of
https://github.com/ntop/n2n.git
synced 2024-09-20 00:51:10 +02:00
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:
parent
e3f64bfd1e
commit
c9eedd68f0
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
||||||
|
|
82
src/sn.c
82
src/sn.c
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
193
src/sn_utils.c
193
src/sn_utils.c
|
@ -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);
|
||||||
|
|
||||||
if(fed != NULL){
|
//REVISIT: make this dependent from last_seen and update socket
|
||||||
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 = now - TEST_TIME;
|
|
||||||
HASH_ADD_PEER(fed->edges, peer);
|
|
||||||
}
|
|
||||||
tmp_sock += sizeof(n2n_mac_t);
|
|
||||||
tmp_mac += sizeof(n2n_sock_t);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0; /* OK */
|
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(peer == NULL){
|
||||||
|
peer = (struct peer_info*)calloc(1,sizeof(struct peer_info));
|
||||||
|
if(peer){
|
||||||
|
memcpy(&(peer->sock),sock,sizeof(n2n_sock_t));
|
||||||
|
memcpy(&(peer->mac_addr),mac, sizeof(n2n_mac_t));
|
||||||
|
HASH_ADD_PEER(sss->federation->edges,peer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return peer;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/** Examine a datagram and determine what to do with it.
|
/** Examine a datagram and determine what to do with it.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
@ -1044,17 +1052,18 @@ 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;
|
||||||
struct peer_info *peer, *tmp_peer, *p;
|
struct peer_info *peer, *tmp_peer, *p;
|
||||||
int8_t allowed_match = -1;
|
int8_t allowed_match = -1;
|
||||||
uint8_t match = 0;
|
uint8_t match = 0;
|
||||||
int match_length = 0;
|
int match_length = 0;
|
||||||
n2n_ip_subnet_t ipaddr;
|
n2n_ip_subnet_t ipaddr;
|
||||||
int num = 0;
|
int num = 0;
|
||||||
n2n_sock_t *tmp_sock;
|
n2n_sock_t *tmp_sock;
|
||||||
n2n_mac_t *tmp_mac;
|
n2n_mac_t *tmp_mac;
|
||||||
|
|
||||||
if(from_supernode != comm->is_federation){
|
if(from_supernode != comm->is_federation){
|
||||||
traceEvent(TRACE_DEBUG, "process_udp dropped REGISTER_SUPER: from_supernode value doesn't correspond to the internal federation marking");
|
traceEvent(TRACE_DEBUG, "process_udp dropped REGISTER_SUPER: from_supernode value doesn't correspond to the internal federation marking");
|
||||||
|
@ -1107,7 +1116,7 @@ static int process_udp(n2n_sn_t * sss,
|
||||||
comm = (struct sn_community*)calloc(1,sizeof(struct sn_community));
|
comm = (struct sn_community*)calloc(1,sizeof(struct sn_community));
|
||||||
|
|
||||||
if(comm) {
|
if(comm) {
|
||||||
comm_init(comm,(char *)cmn.community);
|
comm_init(comm,(char *)cmn.community);
|
||||||
/* new communities introduced by REGISTERs could not have had encrypted header... */
|
/* new communities introduced by REGISTERs could not have had encrypted header... */
|
||||||
comm->header_encryption = HEADER_ENCRYPTION_NONE;
|
comm->header_encryption = HEADER_ENCRYPTION_NONE;
|
||||||
comm->header_encryption_ctx = NULL;
|
comm->header_encryption_ctx = NULL;
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
/* 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(((++num)*ENTRY_SIZE) > MAX_AVAILABLE_SPACE_FOR_ENTRIES) break; /* no more space available in REGISTER_SUPER_ACK payload */
|
||||||
|
memcpy((void*)tmpbuf, (void*)&(peer->sock), sizeof(n2n_sock_t));
|
||||||
|
memcpy((void*)tmpbuf, (void*)&(peer->mac_addr), sizeof(n2n_mac_t));
|
||||||
|
tmp_sock += ENTRY_SIZE;
|
||||||
|
tmp_mac += ENTRY_SIZE;
|
||||||
|
}
|
||||||
|
ack.num_sn = num;
|
||||||
|
|
||||||
HASH_ITER(hh, fed->edges, peer, tmp_peer) {
|
|
||||||
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 */
|
|
||||||
memcpy(tmp_sock, &(peer->sock), sizeof(n2n_sock_t));
|
|
||||||
memcpy(tmp_mac, &(peer->mac_addr), sizeof(n2n_mac_t));
|
|
||||||
tmp_sock += sizeof(n2n_mac_t);
|
|
||||||
tmp_mac += sizeof(n2n_sock_t);
|
|
||||||
}
|
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
@ -1342,7 +1376,7 @@ int run_sn_loop(n2n_sn_t *sss, int *keep_running)
|
||||||
|
|
||||||
if (rc > 0)
|
if (rc > 0)
|
||||||
{
|
{
|
||||||
if (FD_ISSET(sss->sock, &socket_mask))
|
if (FD_ISSET(sss->sock, &socket_mask))
|
||||||
{
|
{
|
||||||
struct sockaddr_in sender_sock;
|
struct sockaddr_in sender_sock;
|
||||||
socklen_t i;
|
socklen_t i;
|
||||||
|
@ -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 */
|
||||||
|
|
Loading…
Reference in New Issue
Block a user