|
@ -20,7 +20,6 @@ |
|
|
|
|
|
|
|
|
#include "n2n.h" |
|
|
#include "n2n.h" |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#define N2N_SN_LPORT_DEFAULT 7654 |
|
|
#define N2N_SN_LPORT_DEFAULT 7654 |
|
|
#define N2N_SN_PKTBUF_SIZE 2048 |
|
|
#define N2N_SN_PKTBUF_SIZE 2048 |
|
|
|
|
|
|
|
@ -50,6 +49,12 @@ struct n2n_sn { |
|
|
|
|
|
|
|
|
typedef struct n2n_sn n2n_sn_t; |
|
|
typedef struct n2n_sn n2n_sn_t; |
|
|
|
|
|
|
|
|
|
|
|
struct n2n_allowed_communities { |
|
|
|
|
|
char community[N2N_COMMUNITY_SIZE]; |
|
|
|
|
|
UT_hash_handle hh; /* makes this structure hashable */ |
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
static struct n2n_allowed_communities *allowed_communities = NULL; |
|
|
|
|
|
|
|
|
static int try_forward( n2n_sn_t * sss, |
|
|
static int try_forward( n2n_sn_t * sss, |
|
|
const n2n_common_t * cmn, |
|
|
const n2n_common_t * cmn, |
|
@ -107,8 +112,7 @@ static void deinit_sn( n2n_sn_t * sss ) |
|
|
* If the supernode has been put into a pre-shutdown phase then this lifetime |
|
|
* If the supernode has been put into a pre-shutdown phase then this lifetime |
|
|
* should not allow registrations to continue beyond the shutdown point. |
|
|
* should not allow registrations to continue beyond the shutdown point. |
|
|
*/ |
|
|
*/ |
|
|
static uint16_t reg_lifetime( n2n_sn_t * sss ) |
|
|
static uint16_t reg_lifetime( n2n_sn_t * sss ) { |
|
|
{ |
|
|
|
|
|
return 120; |
|
|
return 120; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
@ -119,8 +123,7 @@ static int update_edge( n2n_sn_t * sss, |
|
|
const n2n_mac_t edgeMac, |
|
|
const n2n_mac_t edgeMac, |
|
|
const n2n_community_t community, |
|
|
const n2n_community_t community, |
|
|
const n2n_sock_t * sender_sock, |
|
|
const n2n_sock_t * sender_sock, |
|
|
time_t now) |
|
|
time_t now) { |
|
|
{ |
|
|
|
|
|
macstr_t mac_buf; |
|
|
macstr_t mac_buf; |
|
|
n2n_sock_str_t sockbuf; |
|
|
n2n_sock_str_t sockbuf; |
|
|
struct peer_info * scan; |
|
|
struct peer_info * scan; |
|
@ -378,6 +381,61 @@ static int process_mgmt( n2n_sn_t * sss, |
|
|
return 0; |
|
|
return 0; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** Check if the specified community is allowed by the
|
|
|
|
|
|
* supernode configuration |
|
|
|
|
|
* @return 0 = community not allowed, 1 = community allowed |
|
|
|
|
|
* |
|
|
|
|
|
*/ |
|
|
|
|
|
static int allowed_n2n_community(n2n_common_t *cmn) { |
|
|
|
|
|
if(allowed_communities != NULL) { |
|
|
|
|
|
struct n2n_allowed_communities *c; |
|
|
|
|
|
|
|
|
|
|
|
HASH_FIND_STR(allowed_communities, (const char*)cmn->community, c); |
|
|
|
|
|
return((c == NULL) ? 0 : 1); |
|
|
|
|
|
} else { |
|
|
|
|
|
/* If no allowed community is defined, all communities are allowed */ |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
return(1); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** Load the list of allowed communities. Existing/previous ones will be removed
|
|
|
|
|
|
* |
|
|
|
|
|
*/ |
|
|
|
|
|
static int load_allowed_n2n_communities(char *path) { |
|
|
|
|
|
char buffer[4096], *line; |
|
|
|
|
|
FILE *fd = fopen(path, "r"); |
|
|
|
|
|
struct n2n_allowed_communities *s, *tmp; |
|
|
|
|
|
u_int32_t num_communities = 0; |
|
|
|
|
|
|
|
|
|
|
|
if(fd == NULL) { |
|
|
|
|
|
traceEvent(TRACE_WARNING, "File %s not found", path); |
|
|
|
|
|
return -1; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
HASH_ITER(hh, allowed_communities, s, tmp) |
|
|
|
|
|
free(s); |
|
|
|
|
|
|
|
|
|
|
|
while((line = fgets(buffer, sizeof(buffer), fd)) != NULL) { |
|
|
|
|
|
if((strlen(line) < 2) || line[0] == '#') |
|
|
|
|
|
continue; |
|
|
|
|
|
|
|
|
|
|
|
s = (struct n2n_allowed_communities*)malloc(sizeof(struct n2n_allowed_communities)); |
|
|
|
|
|
|
|
|
|
|
|
if(s != NULL) { |
|
|
|
|
|
strncpy((char*)s->community, line, N2N_COMMUNITY_SIZE); |
|
|
|
|
|
HASH_ADD_STR(allowed_communities, community, s); |
|
|
|
|
|
num_communities++; |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
fclose(fd); |
|
|
|
|
|
|
|
|
|
|
|
traceEvent(TRACE_NORMAL, "Loaded %u communities from %s", |
|
|
|
|
|
num_communities, path); |
|
|
|
|
|
|
|
|
|
|
|
return(0); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
/** Examine a datagram and determine what to do with it.
|
|
|
/** Examine a datagram and determine what to do with it.
|
|
|
* |
|
|
* |
|
@ -565,11 +623,17 @@ static int process_udp( n2n_sn_t * sss, |
|
|
size_t encx=0; |
|
|
size_t encx=0; |
|
|
|
|
|
|
|
|
/* Edge requesting registration with us. */ |
|
|
/* Edge requesting registration with us. */ |
|
|
|
|
|
|
|
|
sss->stats.last_reg_super=now; |
|
|
sss->stats.last_reg_super=now; |
|
|
++(sss->stats.reg_super); |
|
|
++(sss->stats.reg_super); |
|
|
decode_REGISTER_SUPER( ®, &cmn, udp_buf, &rem, &idx ); |
|
|
decode_REGISTER_SUPER( ®, &cmn, udp_buf, &rem, &idx ); |
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
Before we move any further, we need to check if the requested |
|
|
|
|
|
community is allowed by the supernode. In case it is not we do |
|
|
|
|
|
not report any message back to the edge to hide the supernode |
|
|
|
|
|
existance (better from the security standpoint) |
|
|
|
|
|
*/ |
|
|
|
|
|
if(allowed_n2n_community(&cmn)) { |
|
|
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; |
|
@ -600,7 +664,7 @@ static int process_udp( n2n_sn_t * sss, |
|
|
traceEvent( TRACE_DEBUG, "Tx REGISTER_SUPER_ACK for %s [%s]", |
|
|
traceEvent( TRACE_DEBUG, "Tx REGISTER_SUPER_ACK for %s [%s]", |
|
|
macaddr_str( mac_buf, reg.edgeMac ), |
|
|
macaddr_str( mac_buf, reg.edgeMac ), |
|
|
sock_to_cstr( sockbuf, &(ack.sock) ) ); |
|
|
sock_to_cstr( sockbuf, &(ack.sock) ) ); |
|
|
|
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
return 0; |
|
|
return 0; |
|
@ -618,6 +682,7 @@ static void help() |
|
|
); |
|
|
); |
|
|
printf("supernode "); |
|
|
printf("supernode "); |
|
|
printf("-l <lport> "); |
|
|
printf("-l <lport> "); |
|
|
|
|
|
printf("-c <community file path> "); |
|
|
printf("[-f] "); |
|
|
printf("[-f] "); |
|
|
printf("[-v] "); |
|
|
printf("[-v] "); |
|
|
printf("\n\n"); |
|
|
printf("\n\n"); |
|
@ -639,17 +704,21 @@ static int run_loop( n2n_sn_t * sss ); |
|
|
|
|
|
|
|
|
/* *************************************************** */ |
|
|
/* *************************************************** */ |
|
|
|
|
|
|
|
|
static int setOption(int optkey, char *optarg, n2n_sn_t *sss) { |
|
|
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 'l': /* local-port */ |
|
|
{ |
|
|
{ |
|
|
sss->lport = atoi(optarg); |
|
|
sss->lport = atoi(_optarg); |
|
|
break; |
|
|
break; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
case 'c': /* community file */ |
|
|
|
|
|
load_allowed_n2n_communities(optarg); |
|
|
|
|
|
break; |
|
|
|
|
|
|
|
|
case 'f': /* foreground */ |
|
|
case 'f': /* foreground */ |
|
|
{ |
|
|
{ |
|
|
sss->daemon = 0; |
|
|
sss->daemon = 0; |
|
@ -695,7 +764,7 @@ static int loadFromCLI(int argc, char * const argv[], n2n_sn_t *sss) { |
|
|
u_char c; |
|
|
u_char c; |
|
|
|
|
|
|
|
|
while((c = getopt_long(argc, argv, |
|
|
while((c = getopt_long(argc, argv, |
|
|
"fl:vh", |
|
|
"fl:c:vh", |
|
|
long_options, NULL)) != '?') { |
|
|
long_options, NULL)) != '?') { |
|
|
if(c == 255) break; |
|
|
if(c == 255) break; |
|
|
setOption(c, optarg, sss); |
|
|
setOption(c, optarg, sss); |
|
|