diff --git a/include/n2n.h b/include/n2n.h index 6f8cd05..b522dc2 100644 --- a/include/n2n.h +++ b/include/n2n.h @@ -382,6 +382,7 @@ typedef struct n2n_sn time_t start_time; /* Used to measure uptime. */ sn_stats_t stats; int daemon; /* If non-zero then daemonise. */ + n2n_mac_t mac_addr; uint16_t lport; /* Local UDP port to bind to. */ uint16_t mport; /* Management UDP port to bind to. */ int sock; /* Main socket for UDP traffic with edges. */ @@ -395,6 +396,7 @@ typedef struct n2n_sn int lock_communities; /* If true, only loaded and matching communities can be used. */ struct sn_community *communities; struct sn_community_regular_expression *rules; + char federation[N2N_COMMUNITY_SIZE]; } n2n_sn_t; /* ************************************** */ diff --git a/src/sn.c b/src/sn.c index 4187cf1..72fc08c 100644 --- a/src/sn.c +++ b/src/sn.c @@ -21,6 +21,8 @@ #include "n2n.h" #include "header_encryption.h" +#define HASH_FIND_COMMUNITY(head, name, out) HASH_FIND_STR(head, name, out) + static n2n_sn_t sss_node; /** Load the list of allowed communities. Existing/previous ones will be removed @@ -179,6 +181,8 @@ static void help() { #if defined(N2N_HAVE_DAEMON) printf("[-f] "); #endif + printf("[-F ] "); + printf("[-m ] "); #ifndef WIN32 printf("[-u -g ] "); #endif /* ifndef WIN32 */ @@ -192,6 +196,9 @@ static void help() { #if defined(N2N_HAVE_DAEMON) printf("-f | Run in foreground.\n"); #endif /* #if defined(N2N_HAVE_DAEMON) */ + printf("-F | Name of the supernodes federation (otherwise use '%s' by default)\n",(char *)FEDERATION_NAME); + printf("-m | Fix MAC address for the supernode (otherwise it may be random)\n" + " | eg. -m 01:02:03:04:05:06\n"); #ifndef WIN32 printf("-u | User ID (numeric) to use when privileges are dropped.\n"); printf("-g | Group ID (numeric) to use when privileges are dropped.\n"); @@ -272,6 +279,24 @@ static int setOption(int optkey, char *_optarg, n2n_sn_t *sss) { break; #endif + case 'F': { /* federation name */ + struct sn_community *fed; + + HASH_FIND_COMMUNITY(sss->communities, FEDERATION_NAME, fed); + + if(fed != NULL){ + 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; + } + + case 'm': {/* MAC address */ + str2mac(sss->mac_addr,_optarg); + break; + } + case 'c': /* community file */ load_allowed_sn_community(sss, _optarg); break; @@ -316,7 +341,7 @@ static const struct option long_options[] = { static int loadFromCLI(int argc, char * const argv[], n2n_sn_t *sss) { u_char c; - while((c = getopt_long(argc, argv, "fl:u:g:t:a:c:vh", + while((c = getopt_long(argc, argv, "fl:u:g:t:a:c:F:m:vh", long_options, NULL)) != '?') { if(c == 255) break; setOption(c, optarg, sss); @@ -410,6 +435,35 @@ static int loadFromFile(const char *path, n2n_sn_t *sss) { /* *************************************************** */ +/* Add the federation to the communities list of a supernode */ +static int add_federation_to_communities(n2n_sn_t *sss){ + struct sn_community *fed; + uint32_t num_communities = 0; + + fed = (struct sn_community *)calloc(1,sizeof(struct sn_community)); + comm_init(fed,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); + + traceEvent(TRACE_INFO, "Added federation '%s' to the list of communities [total: %u]", + (char*)fed->community, num_communities); + } + + return 0; +} + +/* *************************************************** */ + #ifdef __linux__ static void dump_registrations(int signo) { struct sn_community *comm, *ctmp; @@ -479,6 +533,7 @@ int main(int argc, char * const argv[]) { #endif sn_init(&sss_node); + add_federation_to_communities(&sss_node); if((argc >= 2) && (argv[1][0] != '-')) { rc = loadFromFile(argv[1], &sss_node); diff --git a/src/sn_utils.c b/src/sn_utils.c index e241199..1ab8573 100644 --- a/src/sn_utils.c +++ b/src/sn_utils.c @@ -234,9 +234,18 @@ 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 = ntohl(sss->max_auto_ip_net.net_addr); 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[N2N_COMMUNITY_SIZE-1] = '\0'; n2n_srand (n2n_seed()); + /* Random MAC address */ + for(i=0; i<6; i++){ + sss->mac_addr[i] = n2n_rand(); + } + sss->mac_addr[0] &= ~0x01; /* Clear multicast bit */ + sss->mac_addr[0] |= 0x02; /* Set locally-assigned bit */ + return 0; /* OK */ } @@ -396,6 +405,7 @@ int subnet_available(n2n_sn_t *sss, HASH_ITER(hh, sss->communities, cmn, tmpCmn) { if (cmn == comm) continue; + if(cmn->is_federation == IS_FEDERATION) continue; if( (net_id <= (cmn->auto_ip_net.net_addr + ~bitlen2mask(cmn->auto_ip_net.net_bitlen))) &&(net_id + ~mask >= cmn->auto_ip_net.net_addr) ) { success = 0;