Merge branch 'dev' into rp

This commit is contained in:
Luca Deri 2020-07-27 06:57:36 +02:00 committed by GitHub
commit e635926d2c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 93 additions and 39 deletions

View File

@ -363,6 +363,7 @@ typedef struct n2n_sn
sn_stats_t stats; sn_stats_t stats;
int daemon; /* If non-zero then daemonise. */ int daemon; /* If non-zero then daemonise. */
uint16_t lport; /* Local UDP port to bind to. */ 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. */ int sock; /* Main socket for UDP traffic with edges. */
int mgmt_sock; /* management socket. */ int mgmt_sock; /* management socket. */
int lock_communities; /* If true, only loaded communities can be used. */ int lock_communities; /* If true, only loaded communities can be used. */

View File

@ -35,6 +35,9 @@
#define IFACE_UPDATE_INTERVAL (30) /* sec. How long it usually takes to get an IP lease. */ #define IFACE_UPDATE_INTERVAL (30) /* sec. How long it usually takes to get an IP lease. */
#define TRANSOP_TICK_INTERVAL (10) /* sec */ #define TRANSOP_TICK_INTERVAL (10) /* sec */
#define PURGE_REGISTRATION_FREQUENCY 30
#define REGISTRATION_TIMEOUT 60
#define ETH_FRAMESIZE 14 #define ETH_FRAMESIZE 14
#define IP4_SRCOFFSET 12 #define IP4_SRCOFFSET 12
#define IP4_DSTOFFSET 16 #define IP4_DSTOFFSET 16

View File

@ -2504,6 +2504,7 @@ static int edge_init_routes(n2n_edge_t *eee, n2n_route_t *routes, uint16_t num_r
#ifdef WIN32 #ifdef WIN32
return edge_init_routes_win(eee, routes, num_routes); return edge_init_routes_win(eee, routes, num_routes);
#endif #endif
return 0;
} }
/* ************************************** */ /* ************************************** */

View File

@ -22,13 +22,13 @@
#include <assert.h> #include <assert.h>
#define PURGE_REGISTRATION_FREQUENCY 30 #define PURGE_REGISTRATION_FREQUENCY 30
#define REGISTRATION_TIMEOUT 60 #define REGISTRATION_TIMEOUT 60
#define TIME_STAMP_FRAME 0x0000001000000000LL /* clocks of different computers are allowed +/- 16 seconds to be off */ #define TIME_STAMP_FRAME 0x0000001000000000LL /* clocks of different computers are allowed +/- 16 seconds to be off */
#define TIME_STAMP_JITTER 0x0000000027100000LL /* we allow a packet to arrive 160 ms (== 0x27100 us) before another #define TIME_STAMP_JITTER 0x0000000027100000LL /* we allow a packet to arrive 160 ms (== 0x27100 us) before another
* set to 0x0000000000000000LL if increasing (or equal) time stamps allowed only */ * set to 0x0000000000000000LL if increasing (or equal) time stamps allowed only */
static const uint8_t broadcast_addr[6] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; static const uint8_t broadcast_addr[6] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
static const uint8_t multicast_addr[6] = { 0x01, 0x00, 0x5E, 0x00, 0x00, 0x00 }; /* First 3 bytes are meaningful */ static const uint8_t multicast_addr[6] = { 0x01, 0x00, 0x5E, 0x00, 0x00, 0x00 }; /* First 3 bytes are meaningful */
static const uint8_t ipv6_multicast_addr[6] = { 0x33, 0x33, 0x00, 0x00, 0x00, 0x00 }; /* First 2 bytes are meaningful */ static const uint8_t ipv6_multicast_addr[6] = { 0x33, 0x33, 0x00, 0x00, 0x00, 0x00 }; /* First 2 bytes are meaningful */

View File

@ -104,19 +104,21 @@ static void help() {
"or\n" "or\n"
); );
printf("supernode "); printf("supernode ");
printf("-l <lport> "); printf("-l <local port> ");
printf("-c <path> "); printf("-c <path> ");
#if defined(N2N_HAVE_DAEMON) #if defined(N2N_HAVE_DAEMON)
printf("[-f] "); printf("[-f] ");
#endif #endif
printf("[-t <mgmt port>] ");
printf("[-v] "); printf("[-v] ");
printf("\n\n"); printf("\n\n");
printf("-l <lport>\tSet UDP main listen port to <lport>\n"); printf("-l <port>\tSet UDP main listen port to <port>\n");
printf("-c <path>\tFile containing the allowed communities.\n"); printf("-c <path>\tFile containing the allowed communities.\n");
#if defined(N2N_HAVE_DAEMON) #if defined(N2N_HAVE_DAEMON)
printf("-f \tRun in foreground.\n"); printf("-f \tRun in foreground.\n");
#endif /* #if defined(N2N_HAVE_DAEMON) */ #endif /* #if defined(N2N_HAVE_DAEMON) */
printf("-t <port>\tManagement UDP Port (for multiple supernodes on a machine).\n");
printf("-v \tIncrease verbosity. Can be used multiple times.\n"); printf("-v \tIncrease verbosity. Can be used multiple times.\n");
printf("-h \tThis help message.\n"); printf("-h \tThis help message.\n");
printf("\n"); printf("\n");
@ -135,6 +137,10 @@ static int setOption(int optkey, char *_optarg, n2n_sn_t *sss) {
sss->lport = atoi(_optarg); sss->lport = atoi(_optarg);
break; break;
case 't': /* mgmt-port */
sss->mport = atoi(_optarg);
break;
case 'c': /* community file */ case 'c': /* community file */
load_allowed_sn_community(sss, _optarg); load_allowed_sn_community(sss, _optarg);
break; break;
@ -165,9 +171,10 @@ 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, 'l' },
{ "mgmt-port", required_argument, NULL, 't' },
{ "help" , no_argument, NULL, 'h' }, { "help" , no_argument, NULL, 'h' },
{ "verbose", no_argument, NULL, 'v' }, { "verbose", no_argument, NULL, 'v' },
{ NULL, 0, NULL, 0 } { NULL, 0, NULL, 0 }
}; };
/* *************************************************** */ /* *************************************************** */
@ -176,7 +183,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:c:vh", while((c = getopt_long(argc, argv, "fl:t:c:vh",
long_options, NULL)) != '?') { long_options, NULL)) != '?') {
if(c == 255) break; if(c == 255) break;
setOption(c, optarg, sss); setOption(c, optarg, sss);
@ -380,12 +387,12 @@ int main(int argc, char * const argv[]) {
traceEvent(TRACE_NORMAL, "supernode is listening on UDP %u (main)", sss_node.lport); traceEvent(TRACE_NORMAL, "supernode is listening on UDP %u (main)", sss_node.lport);
} }
sss_node.mgmt_sock = open_socket(N2N_SN_MGMT_PORT, 0 /* bind LOOPBACK */); sss_node.mgmt_sock = open_socket(sss_node.mport, 0 /* bind LOOPBACK */);
if(-1 == sss_node.mgmt_sock) { if(-1 == sss_node.mgmt_sock) {
traceEvent(TRACE_ERROR, "Failed to open management socket. %s", strerror(errno)); traceEvent(TRACE_ERROR, "Failed to open management socket. %s", strerror(errno));
exit(-2); exit(-2);
} else } else
traceEvent(TRACE_NORMAL, "supernode is listening on UDP %u (management)", N2N_SN_MGMT_PORT); traceEvent(TRACE_NORMAL, "supernode is listening on UDP %u (management)", sss_node.mport);
traceEvent(TRACE_NORMAL, "supernode started"); traceEvent(TRACE_NORMAL, "supernode started");

View File

@ -14,6 +14,11 @@ static ssize_t sendto_sock(n2n_sn_t *sss,
const uint8_t *pktbuf, const uint8_t *pktbuf,
size_t pktsize); size_t pktsize);
static int sendto_mgmt(n2n_sn_t *sss,
const struct sockaddr_in *sender_sock,
const uint8_t *mgmt_buf,
size_t mgmt_size);
static int try_broadcast(n2n_sn_t * sss, static int try_broadcast(n2n_sn_t * sss,
const struct sn_community *comm, const struct sn_community *comm,
const n2n_common_t * cmn, const n2n_common_t * cmn,
@ -29,6 +34,10 @@ 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 purge_expired_communities(n2n_sn_t *sss,
time_t* p_last_purge,
time_t now);
static int process_mgmt(n2n_sn_t *sss, static int process_mgmt(n2n_sn_t *sss,
const struct sockaddr_in *sender_sock, const struct sockaddr_in *sender_sock,
const uint8_t *mgmt_buf, const uint8_t *mgmt_buf,
@ -185,6 +194,7 @@ int sn_init(n2n_sn_t *sss)
sss->daemon = 1; /* By defult run as a daemon. */ sss->daemon = 1; /* By defult run as a daemon. */
sss->lport = N2N_SN_LPORT_DEFAULT; sss->lport = N2N_SN_LPORT_DEFAULT;
sss->mport = N2N_SN_MGMT_PORT;
sss->sock = -1; sss->sock = -1;
sss->mgmt_sock = -1; sss->mgmt_sock = -1;
@ -313,6 +323,35 @@ static int find_edge_time_stamp_and_verify (struct peer_info * edges,
return ( time_stamp_verify_and_update (stamp, previous_stamp) ); return ( time_stamp_verify_and_update (stamp, previous_stamp) );
} }
static int purge_expired_communities(n2n_sn_t *sss,
time_t* p_last_purge,
time_t now)
{
struct sn_community *comm, *tmp;
size_t num_reg = 0;
if ((now - (*p_last_purge)) < PURGE_REGISTRATION_FREQUENCY) return 0;
traceEvent(TRACE_DEBUG, "Purging old communities and edges");
HASH_ITER(hh, sss->communities, comm, tmp) {
num_reg += purge_peer_list(&comm->edges, now - REGISTRATION_TIMEOUT);
if ((comm->edges == NULL) && (!sss->lock_communities)) {
traceEvent(TRACE_INFO, "Purging idle community %s", comm->community);
if (NULL != comm->header_encryption_ctx)
/* this should not happen as no 'locked' and thus only communities w/o encrypted header here */
free(comm->header_encryption_ctx);
HASH_DEL(sss->communities, comm);
free(comm);
}
}
(*p_last_purge) = now;
traceEvent(TRACE_DEBUG, "Remove %ld edges", num_reg);
return 0;
}
static int process_mgmt(n2n_sn_t *sss, static int process_mgmt(n2n_sn_t *sss,
const struct sockaddr_in *sender_sock, const struct sockaddr_in *sender_sock,
@ -323,10 +362,11 @@ static int process_mgmt(n2n_sn_t *sss,
char resbuf[N2N_SN_PKTBUF_SIZE]; char resbuf[N2N_SN_PKTBUF_SIZE];
size_t ressize = 0; size_t ressize = 0;
uint32_t num_edges = 0; uint32_t num_edges = 0;
ssize_t r; uint32_t num = 0;
struct sn_community *community, *tmp; struct sn_community *community, *tmp;
struct peer_info * peer, *tmpPeer; struct peer_info * peer, *tmpPeer;
macstr_t mac_buf; macstr_t mac_buf;
n2n_sock_str_t sockbuf;
traceEvent(TRACE_DEBUG, "process_mgmt"); traceEvent(TRACE_DEBUG, "process_mgmt");
@ -374,32 +414,48 @@ static int process_mgmt(n2n_sn_t *sss,
(long unsigned int)(now - sss->stats.last_reg_super)); (long unsigned int)(now - sss->stats.last_reg_super));
ressize += snprintf(resbuf+ressize, N2N_SN_PKTBUF_SIZE-ressize, ressize += snprintf(resbuf+ressize, N2N_SN_PKTBUF_SIZE-ressize,
"cur_cmnts"); "cur_cmnts %u\n", HASH_COUNT(sss->communities));
HASH_ITER(hh, sss->communities, community, tmp) { HASH_ITER(hh, sss->communities, community, tmp) {
ressize += snprintf(resbuf+ressize, N2N_SN_PKTBUF_SIZE-ressize, ressize += snprintf(resbuf + ressize, N2N_SN_PKTBUF_SIZE - ressize,
" [%s]", "community: %s\n", community->community);
community->community); sendto_mgmt(sss, sender_sock, resbuf, ressize);
ressize = 0;
num = 0;
HASH_ITER(hh, community->edges, peer, tmpPeer) { HASH_ITER(hh, community->edges, peer, tmpPeer) {
ressize += snprintf(resbuf+ressize, N2N_SN_PKTBUF_SIZE-ressize, ressize += snprintf(resbuf + ressize, N2N_SN_PKTBUF_SIZE - ressize,
" {%s}", "\t[id: %u][MAC: %s][edge: %s][last seen: %lu sec ago]\n",
macaddr_str(mac_buf, peer->mac_addr)); ++num, macaddr_str(mac_buf, peer->mac_addr),
sock_to_cstr(sockbuf, &(peer->sock)), now-peer->last_seen);
sendto_mgmt(sss, sender_sock, resbuf, ressize);
ressize = 0;
} }
} }
ressize += snprintf(resbuf+ressize, N2N_SN_PKTBUF_SIZE-ressize, ressize += snprintf(resbuf+ressize, N2N_SN_PKTBUF_SIZE-ressize,
"\n"); "\n");
sendto_mgmt(sss, sender_sock, resbuf, ressize);
r = sendto(sss->mgmt_sock, resbuf, ressize, 0 /*flags*/,
(struct sockaddr *)sender_sock, sizeof(struct sockaddr_in));
if (r <= 0)
{
++(sss->stats.errors);
traceEvent(TRACE_ERROR, "process_mgmt : sendto failed. %s", strerror(errno));
}
return 0; return 0;
} }
static int sendto_mgmt(n2n_sn_t *sss,
const struct sockaddr_in *sender_sock,
const uint8_t *mgmt_buf,
size_t mgmt_size)
{
ssize_t r = sendto(sss->mgmt_sock, mgmt_buf, mgmt_size, 0 /*flags*/,
(struct sockaddr *)sender_sock, sizeof (struct sockaddr_in));
if (r <= 0) {
++(sss->stats.errors);
traceEvent (TRACE_ERROR, "sendto_mgmt : sendto failed. %s", strerror (errno));
return -1;
}
return 0;
}
/** Examine a datagram and determine what to do with it. /** Examine a datagram and determine what to do with it.
* *
*/ */
@ -830,7 +886,6 @@ int run_sn_loop(n2n_sn_t *sss, int *keep_running)
{ {
uint8_t pktbuf[N2N_SN_PKTBUF_SIZE]; uint8_t pktbuf[N2N_SN_PKTBUF_SIZE];
time_t last_purge_edges = 0; time_t last_purge_edges = 0;
struct sn_community *comm, *tmp;
sss->start_time = time(NULL); sss->start_time = time(NULL);
@ -915,20 +970,7 @@ int run_sn_loop(n2n_sn_t *sss, int *keep_running)
traceEvent(TRACE_DEBUG, "timeout"); traceEvent(TRACE_DEBUG, "timeout");
} }
HASH_ITER(hh, sss->communities, comm, tmp) purge_expired_communities(sss, &last_purge_edges, now);
{
purge_expired_registrations(&comm->edges, &last_purge_edges);
if ((comm->edges == NULL) && (!sss->lock_communities))
{
traceEvent(TRACE_INFO, "Purging idle community %s", comm->community);
if (NULL != comm->header_encryption_ctx)
/* this should not happen as no 'locked' and thus only communities w/o encrypted header here */
free (comm->header_encryption_ctx);
HASH_DEL(sss->communities, comm);
free(comm);
}
}
} /* while */ } /* while */