mirror of
https://github.com/ntop/n2n.git
synced 2024-09-19 16:41:11 +02:00
Update REGISTER_SUPER_ACK handling on edge (#478)
This commit is contained in:
parent
8e9bf61469
commit
dcbc39c0fb
|
@ -199,11 +199,13 @@ struct peer_info {
|
|||
n2n_ip_subnet_t dev_addr;
|
||||
n2n_desc_t dev_desc;
|
||||
n2n_sock_t sock;
|
||||
n2n_cookie_t last_cookie;
|
||||
int timeout;
|
||||
uint8_t purgeable;
|
||||
time_t last_seen;
|
||||
time_t last_p2p;
|
||||
time_t last_sent_query;
|
||||
time_t ping_time;
|
||||
uint64_t last_valid_time_stamp;
|
||||
char *ip_addr;
|
||||
|
||||
|
@ -271,7 +273,7 @@ typedef struct n2n_tuntap_priv_config {
|
|||
|
||||
|
||||
typedef struct n2n_edge_conf {
|
||||
n2n_sn_name_t sn_ip_array[N2N_EDGE_NUM_SUPERNODES];
|
||||
struct peer_info *supernodes; /**< List of supernodes */
|
||||
n2n_route_t *routes; /**< Networks to route through n2n */
|
||||
n2n_community_t community_name; /**< The community. 16 full octets. */
|
||||
n2n_desc_t dev_desc; /**< The device description (hint) */
|
||||
|
@ -309,12 +311,11 @@ struct n2n_edge {
|
|||
n2n_edge_conf_t conf;
|
||||
|
||||
/* Status */
|
||||
uint8_t sn_idx; /**< Currently active supernode. */
|
||||
struct peer_info *curr_sn; /**< Currently active supernode. */
|
||||
uint8_t sn_wait; /**< Whether we are waiting for a supernode response. */
|
||||
size_t sup_attempts; /**< Number of remaining attempts to this supernode. */
|
||||
tuntap_dev device; /**< All about the TUNTAP device */
|
||||
n2n_trans_op_t transop; /**< The transop to use when encoding */
|
||||
n2n_cookie_t last_cookie; /**< Cookie sent in last REGISTER_SUPER. */
|
||||
n2n_route_t *sn_route_to_clean; /**< Supernode route to clean */
|
||||
n2n_edge_callbacks_t cb; /**< API callbacks */
|
||||
void *user_data; /**< Can hold user data */
|
||||
|
@ -339,6 +340,7 @@ struct n2n_edge {
|
|||
time_t last_register_req; /**< Check if time to re-register with super*/
|
||||
time_t last_p2p; /**< Last time p2p traffic was received. */
|
||||
time_t last_sup; /**< Last time a packet arrived from supernode. */
|
||||
time_t last_sweep; /**< Last time a sweep was performed. */
|
||||
time_t start_time; /**< For calculating uptime */
|
||||
|
||||
|
||||
|
@ -503,7 +505,7 @@ int comm_init(struct sn_community *comm, char *cmn);
|
|||
int sn_init(n2n_sn_t *sss);
|
||||
void sn_term(n2n_sn_t *sss);
|
||||
int supernode2sock(n2n_sock_t * sn, const n2n_sn_name_t addrIn);
|
||||
struct peer_info* add_sn_to_federation_by_mac_or_sock(n2n_sn_t *sss, n2n_sock_t *sock, n2n_mac_t *mac);
|
||||
struct peer_info* add_sn_to_list_by_mac_or_sock(struct peer_info **sn_list, n2n_sock_t *sock, n2n_mac_t *mac, int *skip_add);
|
||||
int run_sn_loop(n2n_sn_t *sss, int *keep_running);
|
||||
int assign_one_ip_subnet(n2n_sn_t *sss, struct sn_community *comm);
|
||||
const char* compression_str(uint8_t cmpr);
|
||||
|
|
|
@ -30,25 +30,29 @@
|
|||
#define MSG_TYPE_MAX_TYPE 10
|
||||
|
||||
/* Max available space to add supernodes' informations (sockets and MACs) in REGISTER_SUPER_ACK
|
||||
* Field sizes of REGISTER_SUPER_ACK as used in encode/decode fucntions in src/wire.c */
|
||||
* Field sizes of REGISTER_SUPER_ACK as used in encode/decode fucntions in src/wire.c
|
||||
* REVISIT: replace 255 by DEFAULT_MTU as soon as header encryption allows for longer packets to be encrypted. */
|
||||
#define MAX_AVAILABLE_SPACE_FOR_ENTRIES \
|
||||
DEFAULT_MTU-(1+1+2+sizeof(n2n_common_t)+sizeof(n2n_cookie_t)+sizeof(n2n_mac_t)+1+2+4+1+sizeof(n2n_sock_t)+1) \
|
||||
(255-(1+1+2+sizeof(n2n_common_t)+sizeof(n2n_cookie_t)+sizeof(n2n_mac_t)+1+2+4+1+sizeof(n2n_sock_t)+1)) \
|
||||
|
||||
/* Space needed to store socket and MAC address of a supernode */
|
||||
#define ENTRY_SIZE sizeof(n2n_sock_t)+sizeof(n2n_mac_t)
|
||||
#define ENTRY_SIZE (sizeof(n2n_sock_t)+sizeof(n2n_mac_t))
|
||||
|
||||
#define PURGE_REGISTRATION_FREQUENCY 30
|
||||
#define RE_REG_AND_PURGE_FREQUENCY 10
|
||||
#define REGISTRATION_TIMEOUT 60
|
||||
#define PURGE_FEDERATION_NODE_INTERVAL 90
|
||||
|
||||
#define SOCKET_TIMEOUT_INTERVAL_SECS 10
|
||||
#define REGISTER_SUPER_INTERVAL_DFL 20 /* sec, usually UDP NAT entries in a firewall expire after 30 seconds */
|
||||
#define ALLOWED_TIME 20 /* sec, indicates supernodes that are proven to be alive */
|
||||
#define TEST_TIME (PURGE_FEDERATION_NODE_INTERVAL - ALLOWED_TIME)/2 /* sec, indicates supernodes with unsure status, must be tested to check if they are alive */
|
||||
#define MAX_PING_TIME 3000 /* millisec, indicates default value for ping_time field in peer_info structure */
|
||||
#define SWEEP_TIME 30 /* sec, indicates the value after which we have to sort the hash list of supernodes in edges */
|
||||
|
||||
#define IFACE_UPDATE_INTERVAL (30) /* sec. How long it usually takes to get an IP lease. */
|
||||
#define TRANSOP_TICK_INTERVAL (10) /* sec */
|
||||
|
||||
#define PURGE_REGISTRATION_FREQUENCY 30
|
||||
#define REGISTRATION_TIMEOUT 60
|
||||
#define PURGE_FEDERATION_NODE_INTERVAL 90
|
||||
|
||||
#define SORT_COMMUNITIES_INTERVAL 90 /* sec. until supernode sorts communities' hash list again */
|
||||
|
||||
#define ETH_FRAMESIZE 14
|
||||
|
@ -83,7 +87,7 @@ enum federation{IS_NO_FEDERATION = 0,IS_FEDERATION = 1};
|
|||
#define COMMUNITY_PURGEABLE 1
|
||||
|
||||
/* (un)purgeable supernode indicator */
|
||||
enum sn_purge{SN_UNPURGEABLE = 0, SN_PURGEABLE = 1};
|
||||
enum sn_purge{SN_PURGEABLE = 0, SN_UNPURGEABLE = 1};
|
||||
|
||||
/* Header encryption indicators */
|
||||
#define HEADER_ENCRYPTION_UNKNOWN 0
|
||||
|
@ -103,6 +107,9 @@ enum sn_purge{SN_UNPURGEABLE = 0, SN_PURGEABLE = 1};
|
|||
#define N2N_EDGE_MGMT_PORT 5644
|
||||
#define N2N_SN_MGMT_PORT 5645
|
||||
|
||||
/* flag used in add_sn_to_list_by_mac_or_sock */
|
||||
enum skip_add{NO_SKIP = 0, SKIP = 1, ADDED = 2};
|
||||
|
||||
#define N2N_NETMASK_STR_SIZE 16 /* dotted decimal 12 numbers + 3 dots */
|
||||
#define N2N_MACNAMSIZ 18 /* AA:BB:CC:DD:EE:FF + NULL*/
|
||||
#define N2N_IF_MODE_SIZE 16 /* static | dhcp */
|
||||
|
|
|
@ -186,6 +186,7 @@ typedef struct n2n_REGISTER_SUPER_NAK
|
|||
|
||||
typedef struct n2n_PEER_INFO {
|
||||
uint16_t aflags;
|
||||
n2n_mac_t srcMac;
|
||||
n2n_mac_t mac;
|
||||
n2n_sock_t sock;
|
||||
} n2n_PEER_INFO_t;
|
||||
|
@ -195,6 +196,7 @@ typedef struct n2n_QUERY_PEER
|
|||
{
|
||||
n2n_mac_t srcMac;
|
||||
n2n_mac_t targetMac;
|
||||
uint8_t req_data; /* data we want the supernode to send back in the answer's payload (e.g. 0 = no payload, 1 = number of connected nodes ...) */
|
||||
} n2n_QUERY_PEER_t;
|
||||
|
||||
typedef struct n2n_buf n2n_buf_t;
|
||||
|
|
20
src/edge.c
20
src/edge.c
|
@ -172,9 +172,11 @@ static void help() {
|
|||
" | causes connections stall when not properly supported.\n");
|
||||
#endif
|
||||
printf("-r | Enable packet forwarding through n2n community.\n");
|
||||
printf("-A1 | Disable payload encryption. Do not use with key (defaulting to AES then).\n");
|
||||
printf("-A2 ... -A5 or -A | Choose a cipher for payload encryption, requires a key: -A2 = Twofish,\n");
|
||||
printf(" | -A3 or -A (deprecated) = AES (default), -A4 = ChaCha20, -A5 = Speck-CTR.\n");
|
||||
printf("-A1 | Disable payload encryption. Do not use with key (defaulting to Twofish then).\n");
|
||||
printf("-A2 ... -A5 or -A | Choose a cipher for payload encryption, requires a key: -A2 = Twofish (default),\n");
|
||||
printf(" | -A3 or -A (deprecated) = AES, "
|
||||
"-A4 = ChaCha20, "
|
||||
"-A5 = Speck-CTR.\n");
|
||||
printf("-H | Enable full header encryption. Requires supernode with fixed community.\n");
|
||||
printf("-z1 ... -z2 or -z | Enable compression for outgoing data packets: -z1 or -z = lzo1x"
|
||||
#ifdef N2N_HAVE_ZSTD
|
||||
|
@ -434,6 +436,12 @@ static int setOption(int optkey, char *optargument, n2n_tuntap_priv_config_t *ec
|
|||
case 'p':
|
||||
{
|
||||
conf->local_port = atoi(optargument);
|
||||
|
||||
if(conf->local_port == 0){
|
||||
traceEvent(TRACE_WARNING, "Bad local port format");
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -835,9 +843,9 @@ int main(int argc, char* argv[]) {
|
|||
|
||||
if(conf.transop_id == N2N_TRANSFORM_ID_NULL) {
|
||||
if(conf.encrypt_key) {
|
||||
/* make sure that AES is default cipher if key only (and no cipher) is specified */
|
||||
traceEvent(TRACE_WARNING, "Switching to AES as key was provided.");
|
||||
conf.transop_id = N2N_TRANSFORM_ID_AES;
|
||||
/* make sure that Twofish is default cipher if key only (and no cipher) is specified */
|
||||
traceEvent(TRACE_WARNING, "Switching to Twofish as key was provided.");
|
||||
conf.transop_id = N2N_TRANSFORM_ID_TWOFISH;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
264
src/edge_utils.c
264
src/edge_utils.c
|
@ -63,7 +63,7 @@ int edge_verify_conf(const n2n_edge_conf_t *conf) {
|
|||
((conf->encrypt_key != NULL) && (conf->transop_id == N2N_TRANSFORM_ID_NULL)))
|
||||
return(-4);
|
||||
|
||||
if (conf->dev_desc[0] == 0)
|
||||
if(HASH_COUNT(conf->supernodes) == 0)
|
||||
return(-5);
|
||||
|
||||
return(0);
|
||||
|
@ -176,7 +176,8 @@ static int is_ip6_discovery(const void * buf, size_t bufsize) {
|
|||
n2n_edge_t* edge_init(const n2n_edge_conf_t *conf, int *rv) {
|
||||
n2n_transform_t transop_id = conf->transop_id;
|
||||
n2n_edge_t *eee = calloc(1, sizeof(n2n_edge_t));
|
||||
int rc = -1, i;
|
||||
int rc = -1, i = 0;
|
||||
struct peer_info *scan, *tmp;
|
||||
|
||||
if((rc = edge_verify_conf(conf)) != 0) {
|
||||
traceEvent(TRACE_ERROR, "Invalid configuration");
|
||||
|
@ -193,6 +194,8 @@ n2n_edge_t* edge_init(const n2n_edge_conf_t *conf, int *rv) {
|
|||
#endif
|
||||
|
||||
memcpy(&eee->conf, conf, sizeof(*conf));
|
||||
eee->curr_sn = eee->conf.supernodes;
|
||||
//memcpy(&eee->supernode, &(eee->curr_sn->sock), sizeof(n2n_sock_t));
|
||||
eee->start_time = time(NULL);
|
||||
|
||||
eee->known_peers = NULL;
|
||||
|
@ -211,11 +214,11 @@ n2n_edge_t* edge_init(const n2n_edge_conf_t *conf, int *rv) {
|
|||
// zstd does not require initialization. if it were required, this would be a good place
|
||||
#endif
|
||||
|
||||
for(i=0; i<eee->conf.sn_num; ++i)
|
||||
traceEvent(TRACE_NORMAL, "supernode %u => %s\n", i, (eee->conf.sn_ip_array[i]));
|
||||
|
||||
/* Set the active supernode */
|
||||
supernode2sock(&(eee->supernode), eee->conf.sn_ip_array[eee->sn_idx]);
|
||||
traceEvent(TRACE_NORMAL, "Number of supernodes in the list: %d\n", HASH_COUNT(eee->conf.supernodes));
|
||||
HASH_ITER(hh, eee->conf.supernodes, scan, tmp){
|
||||
traceEvent(TRACE_NORMAL, "supernode %u => %s\n", i, (scan->ip_addr));
|
||||
i++;
|
||||
}
|
||||
|
||||
/* Set active transop */
|
||||
switch(transop_id) {
|
||||
|
@ -687,8 +690,73 @@ static void check_join_multicast_group(n2n_edge_t *eee) {
|
|||
|
||||
/* ************************************** */
|
||||
|
||||
/** Send a QUERY_PEER packet to the current supernode. */
|
||||
static void send_query_peer( n2n_edge_t * eee,
|
||||
const n2n_mac_t dstMac) {
|
||||
uint8_t pktbuf[N2N_PKT_BUF_SIZE];
|
||||
size_t idx;
|
||||
n2n_common_t cmn = {0};
|
||||
n2n_QUERY_PEER_t query = {{0}};
|
||||
struct peer_info *peer, *tmp;
|
||||
uint8_t tmp_pkt[N2N_PKT_BUF_SIZE];
|
||||
|
||||
cmn.ttl=N2N_DEFAULT_TTL;
|
||||
cmn.pc = n2n_query_peer;
|
||||
cmn.flags = 0;
|
||||
memcpy( cmn.community, eee->conf.community_name, N2N_COMMUNITY_SIZE );
|
||||
|
||||
idx=0;
|
||||
encode_mac( query.srcMac, &idx, eee->device.mac_addr );
|
||||
|
||||
idx=0;
|
||||
encode_mac( query.targetMac, &idx, dstMac );
|
||||
query.req_data = 0;
|
||||
|
||||
idx=0;
|
||||
|
||||
encode_QUERY_PEER( pktbuf, &idx, &cmn, &query );
|
||||
|
||||
if(memcmp(dstMac, null_mac, sizeof(n2n_mac_t)) != 0){
|
||||
|
||||
traceEvent( TRACE_DEBUG, "send QUERY_PEER to supernode" );
|
||||
|
||||
if(eee->conf.header_encryption == HEADER_ENCRYPTION_ENABLED){
|
||||
packet_header_encrypt (pktbuf, idx, eee->conf.header_encryption_ctx,
|
||||
eee->conf.header_iv_ctx,
|
||||
time_stamp (), pearson_hash_16 (pktbuf, idx));
|
||||
}
|
||||
|
||||
sendto_sock( eee->udp_sock, pktbuf, idx, &(eee->supernode) );
|
||||
|
||||
} else {
|
||||
traceEvent( TRACE_DEBUG, "send PING to supernodes" );
|
||||
|
||||
memcpy(tmp_pkt, pktbuf, idx);
|
||||
|
||||
HASH_ITER(hh, eee->conf.supernodes, peer, tmp){
|
||||
if(eee->conf.header_encryption == HEADER_ENCRYPTION_ENABLED){
|
||||
/* Re-encrypt the orginal message again for non-repeating IV. */
|
||||
memcpy(pktbuf, tmp_pkt, idx);
|
||||
packet_header_encrypt (pktbuf, idx, eee->conf.header_encryption_ctx,
|
||||
eee->conf.header_iv_ctx,
|
||||
time_stamp (), pearson_hash_16 (pktbuf, idx));
|
||||
}
|
||||
sendto_sock( eee->udp_sock, pktbuf, idx, &(peer->sock));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ******************************************************** */
|
||||
|
||||
static int ping_time_sort(struct peer_info *a, struct peer_info *b){
|
||||
// comparison function for sorting supernodes in ascending order of their
|
||||
// ping_time-fields
|
||||
return (a->ping_time - b->ping_time);
|
||||
}
|
||||
|
||||
|
||||
/** Send a REGISTER_SUPER packet to the current supernode. */
|
||||
static void send_register_super(n2n_edge_t *eee, const n2n_sock_t *supernode, int sn_idx) {
|
||||
static void send_register_super(n2n_edge_t *eee) {
|
||||
uint8_t pktbuf[N2N_PKT_BUF_SIZE] = {0};
|
||||
size_t idx;
|
||||
/* ssize_t sent; */
|
||||
|
@ -704,10 +772,10 @@ static void send_register_super(n2n_edge_t *eee, const n2n_sock_t *supernode, in
|
|||
cmn.flags = 0;
|
||||
memcpy(cmn.community, eee->conf.community_name, N2N_COMMUNITY_SIZE);
|
||||
|
||||
for (idx = 0; (sn_idx==0) && (idx < N2N_COOKIE_SIZE); ++idx)
|
||||
eee->last_cookie[idx] = n2n_rand() % 0xff;
|
||||
for (idx = 0; idx < N2N_COOKIE_SIZE; ++idx)
|
||||
eee->curr_sn->last_cookie[idx] = n2n_rand() % 0xff;
|
||||
|
||||
memcpy(reg.cookie, eee->last_cookie, N2N_COOKIE_SIZE);
|
||||
memcpy(reg.cookie, eee->curr_sn->last_cookie, N2N_COOKIE_SIZE);
|
||||
reg.dev_addr.net_addr = ntohl(eee->device.ip_addr);
|
||||
reg.dev_addr.net_bitlen = mask2bitlen(ntohl(eee->device.device_mask));
|
||||
memcpy(reg.dev_desc, eee->conf.dev_desc, N2N_DESC_SIZE);
|
||||
|
@ -720,47 +788,47 @@ static void send_register_super(n2n_edge_t *eee, const n2n_sock_t *supernode, in
|
|||
encode_REGISTER_SUPER(pktbuf, &idx, &cmn, ®);
|
||||
|
||||
traceEvent(TRACE_DEBUG, "send REGISTER_SUPER to %s",
|
||||
sock_to_cstr(sockbuf, supernode));
|
||||
sock_to_cstr(sockbuf, &(eee->curr_sn->sock)));
|
||||
|
||||
if (eee->conf.header_encryption == HEADER_ENCRYPTION_ENABLED)
|
||||
packet_header_encrypt(pktbuf, idx, eee->conf.header_encryption_ctx,
|
||||
eee->conf.header_iv_ctx,
|
||||
time_stamp(), pearson_hash_16(pktbuf, idx));
|
||||
|
||||
/* sent = */ sendto_sock(eee->udp_sock, pktbuf, idx, supernode);
|
||||
/* sent = */ sendto_sock(eee->udp_sock, pktbuf, idx, &(eee->curr_sn->sock));
|
||||
}
|
||||
|
||||
/* ************************************** */
|
||||
|
||||
/** Send a QUERY_PEER packet to the current supernode. */
|
||||
static void send_query_peer( n2n_edge_t * eee,
|
||||
const n2n_mac_t dstMac) {
|
||||
uint8_t pktbuf[N2N_PKT_BUF_SIZE];
|
||||
size_t idx;
|
||||
n2n_common_t cmn = {0};
|
||||
n2n_QUERY_PEER_t query = {{0}};
|
||||
static int sort_supernodes(n2n_edge_t *eee, time_t now){
|
||||
struct peer_info *scan, *tmp;
|
||||
|
||||
cmn.ttl=N2N_DEFAULT_TTL;
|
||||
cmn.pc = n2n_query_peer;
|
||||
cmn.flags = 0;
|
||||
memcpy( cmn.community, eee->conf.community_name, N2N_COMMUNITY_SIZE );
|
||||
if(eee->curr_sn != eee->conf.supernodes){
|
||||
eee->curr_sn = eee->conf.supernodes;
|
||||
memcpy(&eee->supernode, &(eee->curr_sn->sock), sizeof(n2n_sock_t));
|
||||
eee->sup_attempts = N2N_EDGE_SUP_ATTEMPTS;
|
||||
|
||||
idx=0;
|
||||
encode_mac( query.srcMac, &idx, eee->device.mac_addr );
|
||||
idx=0;
|
||||
encode_mac( query.targetMac, &idx, dstMac );
|
||||
traceEvent(TRACE_INFO, "Registering with supernode [%s][number of supernodes %d][attempts left %u]",
|
||||
supernode_ip(eee), HASH_COUNT(eee->conf.supernodes), (unsigned int)eee->sup_attempts);
|
||||
|
||||
idx=0;
|
||||
encode_QUERY_PEER( pktbuf, &idx, &cmn, &query );
|
||||
|
||||
traceEvent( TRACE_DEBUG, "send QUERY_PEER to supernode" );
|
||||
|
||||
if(eee->conf.header_encryption == HEADER_ENCRYPTION_ENABLED){
|
||||
packet_header_encrypt (pktbuf, idx, eee->conf.header_encryption_ctx,
|
||||
eee->conf.header_iv_ctx,
|
||||
time_stamp (), pearson_hash_16 (pktbuf, idx));
|
||||
send_register_super(eee);
|
||||
eee->sn_wait = 1;
|
||||
}
|
||||
sendto_sock( eee->udp_sock, pktbuf, idx, &(eee->supernode) );
|
||||
|
||||
if(now - eee->last_sweep > SWEEP_TIME){
|
||||
if(eee->sn_wait == 0){
|
||||
// this routine gets periodically called
|
||||
// it sorts supernodes in ascending order of their ping_time-fields
|
||||
HASH_SORT(eee->conf.supernodes, ping_time_sort);
|
||||
eee->last_sweep = now;
|
||||
|
||||
HASH_ITER(hh, eee->conf.supernodes, scan, tmp){
|
||||
scan->ping_time = MAX_PING_TIME;
|
||||
}
|
||||
}
|
||||
send_query_peer(eee, null_mac);
|
||||
}
|
||||
|
||||
return 0; /* OK */
|
||||
}
|
||||
|
||||
/** Send a REGISTER packet to another edge. */
|
||||
|
@ -866,7 +934,7 @@ static void send_register_ack(n2n_edge_t * eee,
|
|||
* This is frequently called by the main loop.
|
||||
*/
|
||||
void update_supernode_reg(n2n_edge_t * eee, time_t nowTime) {
|
||||
u_int sn_idx;
|
||||
struct peer_info *scan, *tmp;
|
||||
|
||||
if(eee->sn_wait && (nowTime > (eee->last_register_req + (eee->conf.register_interval/10)))) {
|
||||
/* fall through */
|
||||
|
@ -878,12 +946,10 @@ void update_supernode_reg(n2n_edge_t * eee, time_t nowTime) {
|
|||
|
||||
if(0 == eee->sup_attempts) {
|
||||
/* Give up on that supernode and try the next one. */
|
||||
++(eee->sn_idx);
|
||||
|
||||
if(eee->sn_idx >= eee->conf.sn_num) {
|
||||
/* Got to end of list, go back to the start. Also works for list of one entry. */
|
||||
eee->sn_idx=0;
|
||||
}
|
||||
eee->curr_sn->ping_time = MAX_PING_TIME;
|
||||
HASH_SORT(eee->conf.supernodes, ping_time_sort);
|
||||
eee->curr_sn = eee->conf.supernodes;
|
||||
memcpy(&eee->supernode, &(eee->curr_sn->sock), sizeof(n2n_sock_t));
|
||||
|
||||
traceEvent(TRACE_WARNING, "Supernode not responding, now trying %s", supernode_ip(eee));
|
||||
|
||||
|
@ -904,16 +970,14 @@ void update_supernode_reg(n2n_edge_t * eee, time_t nowTime) {
|
|||
else
|
||||
--(eee->sup_attempts);
|
||||
|
||||
for(sn_idx=0; sn_idx<eee->conf.sn_num; sn_idx++) {
|
||||
if(supernode2sock(&(eee->supernode), eee->conf.sn_ip_array[sn_idx]) == 0) {
|
||||
traceEvent(TRACE_INFO, "Registering with supernode [id: %u/%u][%s][attempts left %u]",
|
||||
sn_idx+1, eee->conf.sn_num,
|
||||
supernode_ip(eee), (unsigned int)eee->sup_attempts);
|
||||
if(supernode2sock(&(eee->supernode), eee->curr_sn->ip_addr) == 0) {
|
||||
traceEvent(TRACE_INFO, "Registering with supernode [%s][number of supernodes %d][attempts left %u]",
|
||||
supernode_ip(eee), HASH_COUNT(eee->conf.supernodes), (unsigned int)eee->sup_attempts);
|
||||
|
||||
send_register_super(eee, &(eee->supernode), sn_idx);
|
||||
}
|
||||
send_register_super(eee);
|
||||
}
|
||||
|
||||
|
||||
register_with_local_peers(eee);
|
||||
|
||||
eee->sn_wait=1;
|
||||
|
@ -940,7 +1004,7 @@ static void send_deregister(n2n_edge_t * eee,
|
|||
|
||||
/** Return the IP address of the current supernode in the ring. */
|
||||
static const char * supernode_ip(const n2n_edge_t * eee) {
|
||||
return (eee->conf.sn_ip_array)[eee->sn_idx];
|
||||
return (eee->curr_sn->ip_addr);
|
||||
}
|
||||
|
||||
/* ************************************** */
|
||||
|
@ -1632,9 +1696,6 @@ void edge_read_from_tap(n2n_edge_t * eee) {
|
|||
}
|
||||
}
|
||||
|
||||
/* ************************************** */
|
||||
|
||||
|
||||
/* ************************************** */
|
||||
|
||||
/** Read a datagram from the main UDP socket to the internet. */
|
||||
|
@ -1645,7 +1706,6 @@ void readFromIPSocket(n2n_edge_t * eee, int in_sock) {
|
|||
n2n_sock_str_t sockbuf2; /* don't clobber sockbuf1 if writing two addresses to trace */
|
||||
macstr_t mac_buf1;
|
||||
macstr_t mac_buf2;
|
||||
|
||||
uint8_t udp_buf[N2N_PKT_BUF_SIZE]; /* Compete UDP packet */
|
||||
ssize_t recvlen;
|
||||
size_t rem;
|
||||
|
@ -1680,6 +1740,10 @@ void readFromIPSocket(n2n_edge_t * eee, int in_sock) {
|
|||
|
||||
/* REVISIT: when UDP/IPv6 is supported we will need a flag to indicate which
|
||||
* IP transport version the packet arrived on. May need to UDP sockets. */
|
||||
|
||||
/* REVISIT: do not endprse use with several supernodes
|
||||
memset(&sender, 0, sizeof(n2n_sock_t)); */
|
||||
|
||||
sender.family = AF_INET; /* UDP socket was opened PF_INET v4 */
|
||||
sender.port = ntohs(sender_sock.sin_port);
|
||||
memcpy(&(sender.addr.v4), &(sender_sock.sin_addr.s_addr), IPV4_SIZE);
|
||||
|
@ -1850,6 +1914,11 @@ void readFromIPSocket(n2n_edge_t * eee, int in_sock) {
|
|||
char * ip_str = NULL;
|
||||
n2n_REGISTER_SUPER_ACK_t ra;
|
||||
uint8_t tmpbuf[MAX_AVAILABLE_SPACE_FOR_ENTRIES];
|
||||
n2n_sock_t *tmp_sock;
|
||||
n2n_mac_t *tmp_mac;
|
||||
int i;
|
||||
int skip_add;
|
||||
struct peer_info *sn;
|
||||
|
||||
memset(&ra, 0, sizeof(n2n_REGISTER_SUPER_ACK_t));
|
||||
|
||||
|
@ -1887,12 +1956,23 @@ void readFromIPSocket(n2n_edge_t * eee, int in_sock) {
|
|||
return;
|
||||
}
|
||||
|
||||
if(0 == memcmp(ra.cookie, eee->last_cookie, N2N_COOKIE_SIZE))
|
||||
if(0 == memcmp(ra.cookie, eee->curr_sn->last_cookie, N2N_COOKIE_SIZE))
|
||||
{
|
||||
if(ra.num_sn > 0)
|
||||
{
|
||||
traceEvent(TRACE_NORMAL, "Rx REGISTER_SUPER_ACK payload contains sockets and MACs of supernodes in the federation.");
|
||||
tmp_sock = (void*)&tmpbuf;
|
||||
tmp_mac = (void*)&tmpbuf[sizeof(n2n_sock_t)];
|
||||
|
||||
for(i=0; i<ra.num_sn; i++){
|
||||
skip_add = NO_SKIP;
|
||||
sn = add_sn_to_list_by_mac_or_sock(&(eee->conf.supernodes), tmp_sock, tmp_mac, &skip_add);
|
||||
if(skip_add == ADDED){
|
||||
traceEvent(TRACE_NORMAL, "Supernode added to the list of supernodes.");
|
||||
}
|
||||
|
||||
/* REVISIT: find a more elegant expression to increase following pointers. */
|
||||
tmp_sock = (void*)tmp_sock + ENTRY_SIZE;
|
||||
tmp_mac = (void*)tmp_sock + sizeof(n2n_sock_t);
|
||||
}
|
||||
|
||||
eee->last_sup = now;
|
||||
eee->sn_wait=0;
|
||||
eee->sup_attempts = N2N_EDGE_SUP_ATTEMPTS; /* refresh because we got a response */
|
||||
|
@ -1917,6 +1997,8 @@ void readFromIPSocket(n2n_edge_t * eee, int in_sock) {
|
|||
/* NOTE: the register_interval should be chosen by the edge node
|
||||
* based on its NAT configuration. */
|
||||
//eee->conf.register_interval = ra.lifetime;
|
||||
|
||||
eee->curr_sn->ping_time = (now - eee->last_register_req)*1000;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1932,6 +2014,8 @@ void readFromIPSocket(n2n_edge_t * eee, int in_sock) {
|
|||
case MSG_TYPE_PEER_INFO: {
|
||||
n2n_PEER_INFO_t pi;
|
||||
struct peer_info * scan;
|
||||
int skip_add;
|
||||
|
||||
decode_PEER_INFO( &pi, &cmn, udp_buf, &rem, &idx );
|
||||
|
||||
if(eee->conf.header_encryption == HEADER_ENCRYPTION_ENABLED) {
|
||||
|
@ -1948,18 +2032,29 @@ void readFromIPSocket(n2n_edge_t * eee, int in_sock) {
|
|||
break;
|
||||
}
|
||||
|
||||
if(memcmp(pi.mac, null_mac, sizeof(n2n_mac_t)) == 0){
|
||||
skip_add = SKIP;
|
||||
scan = add_sn_to_list_by_mac_or_sock(&(eee->conf.supernodes), &sender, &pi.srcMac, &skip_add);
|
||||
if(scan != NULL){
|
||||
scan->ping_time = (now - eee->last_sweep)*1000;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
HASH_FIND_PEER(eee->pending_peers, pi.mac, scan);
|
||||
|
||||
if(scan) {
|
||||
scan->sock = pi.sock;
|
||||
traceEvent(TRACE_INFO, "Rx PEER_INFO for %s: is at %s",
|
||||
macaddr_str(mac_buf1, pi.mac),
|
||||
sock_to_cstr(sockbuf1, &pi.sock));
|
||||
|
||||
send_register(eee, &scan->sock, scan->mac_addr);
|
||||
|
||||
} else {
|
||||
traceEvent(TRACE_INFO, "Rx PEER_INFO unknown peer %s",
|
||||
macaddr_str(mac_buf1, pi.mac) );
|
||||
}
|
||||
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
|
@ -2111,6 +2206,8 @@ int run_edge_loop(n2n_edge_t * eee, int *keep_running) {
|
|||
if (eee->cb.main_loop_period)
|
||||
eee->cb.main_loop_period(eee, nowTime);
|
||||
|
||||
sort_supernodes(eee, nowTime);
|
||||
|
||||
} /* while */
|
||||
|
||||
#ifdef WIN32
|
||||
|
@ -2494,7 +2591,7 @@ static int edge_init_routes_linux(n2n_edge_t *eee, n2n_route_t *routes, uint16_t
|
|||
return(-1);
|
||||
}
|
||||
|
||||
if (supernode2sock(&sn, eee->conf.sn_ip_array[0]) < 0)
|
||||
if (supernode2sock(&sn, eee->conf.supernodes->ip_addr) < 0)
|
||||
return(-1);
|
||||
|
||||
if (sn.family != AF_INET) {
|
||||
|
@ -2635,7 +2732,7 @@ void edge_init_conf_defaults(n2n_edge_conf_t *conf) {
|
|||
|
||||
if (getenv("N2N_KEY")) {
|
||||
conf->encrypt_key = strdup(getenv("N2N_KEY"));
|
||||
conf->transop_id = N2N_TRANSFORM_ID_AES;
|
||||
conf->transop_id = N2N_TRANSFORM_ID_TWOFISH;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2655,11 +2752,38 @@ const n2n_edge_conf_t* edge_get_conf(const n2n_edge_t *eee) {
|
|||
/* ************************************** */
|
||||
|
||||
int edge_conf_add_supernode(n2n_edge_conf_t *conf, const char *ip_and_port) {
|
||||
if(conf->sn_num >= N2N_EDGE_NUM_SUPERNODES)
|
||||
return(-1);
|
||||
struct peer_info *sn;
|
||||
n2n_sock_t *sock;
|
||||
int skip_add;
|
||||
int rv = -1;
|
||||
|
||||
strncpy((conf->sn_ip_array[conf->sn_num]), ip_and_port, N2N_EDGE_SN_HOST_SIZE);
|
||||
traceEvent(TRACE_NORMAL, "Adding supernode[%u] = %s", (unsigned int)conf->sn_num, (conf->sn_ip_array[conf->sn_num]));
|
||||
sock = (n2n_sock_t*)calloc(1,sizeof(n2n_sock_t));
|
||||
rv = supernode2sock(sock, ip_and_port);
|
||||
|
||||
if(rv != 0){
|
||||
traceEvent(TRACE_WARNING, "Invalid socket");
|
||||
free(sock);
|
||||
return(1);
|
||||
}
|
||||
|
||||
skip_add = NO_SKIP;
|
||||
sn = add_sn_to_list_by_mac_or_sock(&(conf->supernodes), sock, (n2n_mac_t *)null_mac, &skip_add);
|
||||
|
||||
if(sn != NULL){
|
||||
sn->ip_addr = calloc(1,N2N_EDGE_SN_HOST_SIZE);
|
||||
|
||||
if(sn->ip_addr != NULL){
|
||||
strncpy(sn->ip_addr, ip_and_port, N2N_EDGE_SN_HOST_SIZE-1);
|
||||
memcpy(&(sn->sock), sock, sizeof(n2n_sock_t));
|
||||
memcpy(&(sn->mac_addr), null_mac, sizeof(n2n_mac_t));
|
||||
sn->purgeable = SN_UNPURGEABLE;
|
||||
sn->last_valid_time_stamp = initial_time_stamp();
|
||||
}
|
||||
}
|
||||
|
||||
free(sock);
|
||||
|
||||
traceEvent(TRACE_NORMAL, "Adding supernode = %s", sn->ip_addr);
|
||||
conf->sn_num++;
|
||||
|
||||
return(0);
|
||||
|
@ -2680,7 +2804,7 @@ int quick_edge_init(char *device_name, char *community_name,
|
|||
/* Setup the configuration */
|
||||
edge_init_conf_defaults(&conf);
|
||||
conf.encrypt_key = encrypt_key;
|
||||
conf.transop_id = N2N_TRANSFORM_ID_AES;
|
||||
conf.transop_id = N2N_TRANSFORM_ID_TWOFISH;
|
||||
conf.compression = N2N_COMPRESSION_ID_NONE;
|
||||
snprintf((char*)conf.community_name, sizeof(conf.community_name), "%s", community_name);
|
||||
edge_conf_add_supernode(&conf, supernode_ip_address_port);
|
||||
|
|
42
src/n2n.c
42
src/n2n.c
|
@ -26,6 +26,7 @@
|
|||
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 ipv6_multicast_addr[6] = { 0x33, 0x33, 0x00, 0x00, 0x00, 0x00 }; /* First 2 bytes are meaningful */
|
||||
static const n2n_mac_t null_mac = {0, 0, 0, 0, 0, 0};
|
||||
|
||||
/* ************************************** */
|
||||
|
||||
|
@ -242,8 +243,9 @@ int supernode2sock(n2n_sock_t * sn, const n2n_sn_name_t addrIn) {
|
|||
struct addrinfo * ainfo = NULL;
|
||||
int nameerr;
|
||||
|
||||
if(supernode_port)
|
||||
if(supernode_port){
|
||||
sn->port = atoi(supernode_port);
|
||||
}
|
||||
else
|
||||
traceEvent(TRACE_WARNING, "Bad supernode parameter (-l <host:port>) %s %s:%s",
|
||||
addr, supernode_host, supernode_port);
|
||||
|
@ -287,6 +289,42 @@ int supernode2sock(n2n_sock_t * sn, const n2n_sn_name_t addrIn) {
|
|||
|
||||
/* ************************************** */
|
||||
|
||||
struct peer_info* add_sn_to_list_by_mac_or_sock(struct peer_info **sn_list, n2n_sock_t *sock, n2n_mac_t *mac, int *skip_add){
|
||||
struct peer_info *scan, *tmp, *peer = NULL;
|
||||
|
||||
if(memcmp(mac,null_mac,sizeof(n2n_mac_t)) != 0) { /* not zero MAC */
|
||||
HASH_FIND_PEER(*sn_list, mac, peer);
|
||||
|
||||
//REVISIT: make this dependent from last_seen and update socket
|
||||
}
|
||||
|
||||
if(peer == NULL) { /* zero MAC, search by socket */
|
||||
HASH_ITER(hh,*sn_list,scan,tmp) {
|
||||
if(memcmp(&(scan->sock), sock, sizeof(n2n_sock_t)) == 0) {
|
||||
HASH_DEL(*sn_list, scan);
|
||||
memcpy(&(scan->mac_addr), mac, sizeof(n2n_mac_t));
|
||||
HASH_ADD_PEER(*sn_list, scan);
|
||||
peer = scan;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if((peer == NULL) && (*skip_add == NO_SKIP)) {
|
||||
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(*sn_list, peer);
|
||||
*skip_add = ADDED;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return peer;
|
||||
}
|
||||
|
||||
/* ************************************************ */
|
||||
|
||||
uint8_t is_multi_broadcast(const uint8_t * dest_mac) {
|
||||
|
||||
int is_broadcast =(memcmp(broadcast_addr, dest_mac, 6) == 0);
|
||||
|
@ -370,7 +408,7 @@ size_t purge_peer_list(struct peer_info ** peer_list,
|
|||
size_t retval=0;
|
||||
|
||||
HASH_ITER(hh, *peer_list, scan, tmp) {
|
||||
if(scan->last_seen < purge_before) {
|
||||
if(scan->purgeable == SN_PURGEABLE && scan->last_seen < purge_before) {
|
||||
HASH_DEL(*peer_list, scan);
|
||||
retval++;
|
||||
free(scan);
|
||||
|
|
40
src/sn.c
40
src/sn.c
|
@ -195,7 +195,7 @@ static void help() {
|
|||
|
||||
printf("-p <port> | Set UDP main listen port to <port>\n");
|
||||
printf("-c <path> | File containing the allowed communities.\n");
|
||||
printf("-l <sn:port> | Supernode IP:port.\n");
|
||||
printf("-l <sn host:port> | Name/IP of a known supernode:port.\n");
|
||||
#if defined(N2N_HAVE_DAEMON)
|
||||
printf("-f | Run in foreground.\n");
|
||||
#endif /* #if defined(N2N_HAVE_DAEMON) */
|
||||
|
@ -224,10 +224,22 @@ static int setOption(int optkey, char *_optarg, n2n_sn_t *sss) {
|
|||
switch (optkey) {
|
||||
case 'p': /* local-port */
|
||||
sss->lport = atoi(_optarg);
|
||||
|
||||
if(sss->lport == 0){
|
||||
traceEvent(TRACE_WARNING, "Bad local port format");
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 't': /* mgmt-port */
|
||||
sss->mport = atoi(_optarg);
|
||||
|
||||
if(sss->mport == 0){
|
||||
traceEvent(TRACE_WARNING, "Bad management port format");
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 'l': { /* supernode:port */
|
||||
|
@ -235,6 +247,7 @@ static int setOption(int optkey, char *_optarg, n2n_sn_t *sss) {
|
|||
struct peer_info *anchor_sn;
|
||||
size_t length;
|
||||
int rv = -1;
|
||||
int skip_add;
|
||||
char *double_column = strchr(_optarg, ':');
|
||||
|
||||
length = strlen(_optarg);
|
||||
|
@ -243,36 +256,39 @@ static int setOption(int optkey, char *_optarg, n2n_sn_t *sss) {
|
|||
break;
|
||||
}
|
||||
|
||||
/* Need to check the format IP:port */
|
||||
if(!double_column){
|
||||
traceEvent(TRACE_WARNING, "Invalid -l format: ignored");
|
||||
return (-1);
|
||||
}
|
||||
|
||||
if(sss->federation != NULL) {
|
||||
socket = (n2n_sock_t *)calloc(1,sizeof(n2n_sock_t));
|
||||
rv = supernode2sock(socket, _optarg);
|
||||
|
||||
anchor_sn = add_sn_to_federation_by_mac_or_sock(sss,socket, (n2n_mac_t*) null_mac);
|
||||
if(rv != 0){
|
||||
traceEvent(TRACE_WARNING, "Invalid socket");
|
||||
free(socket);
|
||||
break;
|
||||
}
|
||||
|
||||
if(sss->federation != NULL) {
|
||||
|
||||
skip_add = NO_SKIP;
|
||||
anchor_sn = add_sn_to_list_by_mac_or_sock(&(sss->federation->edges), socket, (n2n_mac_t*) null_mac, &skip_add);
|
||||
|
||||
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();
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
free(socket);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -329,8 +345,10 @@ static int setOption(int optkey, char *_optarg, n2n_sn_t *sss) {
|
|||
#endif
|
||||
|
||||
case 'F': { /* federation name */
|
||||
|
||||
snprintf(sss->federation->community,N2N_COMMUNITY_SIZE-1,"*%s",_optarg);
|
||||
sss->federation->community[N2N_COMMUNITY_SIZE-1] = '\0';
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
142
src/sn_utils.c
142
src/sn_utils.c
|
@ -251,6 +251,7 @@ int sn_init(n2n_sn_t *sss) {
|
|||
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));
|
||||
sss->federation->edges = NULL;
|
||||
}
|
||||
|
||||
n2n_srand (n2n_seed());
|
||||
|
@ -511,17 +512,19 @@ static int find_edge_time_stamp_and_verify (struct peer_info * edges,
|
|||
return ( time_stamp_verify_and_update (stamp, previous_stamp, allow_jitter) );
|
||||
}
|
||||
|
||||
static int re_register_and_purge_supernodes(n2n_sn_t *sss, struct sn_community *comm, time_t now) {
|
||||
static int re_register_and_purge_supernodes(n2n_sn_t *sss, struct sn_community *comm, time_t *p_last_re_reg_and_purge, time_t now) {
|
||||
time_t time;
|
||||
struct peer_info *peer, *tmp;
|
||||
|
||||
if((now - (*p_last_re_reg_and_purge)) < RE_REG_AND_PURGE_FREQUENCY ) return 0;
|
||||
|
||||
if(comm != NULL) {
|
||||
HASH_ITER(hh,comm->edges,peer,tmp) {
|
||||
time = now - peer->last_seen;
|
||||
if(time <= ALLOWED_TIME) continue;
|
||||
|
||||
if((time < PURGE_FEDERATION_NODE_INTERVAL)
|
||||
|| (peer->purgeable == SN_UNPURGEABLE) /* FIX fcarli3 */
|
||||
|| (peer->purgeable == SN_UNPURGEABLE)
|
||||
) {
|
||||
/* re-regitser (send REGISTER_SUPER) */
|
||||
uint8_t pktbuf[N2N_PKT_BUF_SIZE] = {0};
|
||||
|
@ -537,10 +540,10 @@ static int re_register_and_purge_supernodes(n2n_sn_t *sss, struct sn_community *
|
|||
|
||||
cmn.ttl = N2N_DEFAULT_TTL;
|
||||
cmn.pc = n2n_register_super;
|
||||
cmn.flags = 0;
|
||||
cmn.flags = N2N_FLAGS_FROM_SUPERNODE;
|
||||
memcpy(cmn.community, comm->community, N2N_COMMUNITY_SIZE);
|
||||
|
||||
for (idx = 0; idx < N2N_COOKIE_SIZE; ++idx) /* aggiungi sn_idx */
|
||||
for (idx = 0; idx < N2N_COOKIE_SIZE; ++idx)
|
||||
cookie[idx] = n2n_rand() % 0xff;
|
||||
|
||||
memcpy(reg.cookie, cookie, N2N_COOKIE_SIZE);
|
||||
|
@ -549,7 +552,7 @@ static int re_register_and_purge_supernodes(n2n_sn_t *sss, struct sn_community *
|
|||
reg.auth.scheme = 0; /* No auth yet */
|
||||
|
||||
idx = 0;
|
||||
encode_mac(reg.edgeMac, &idx, peer->mac_addr);
|
||||
encode_mac(reg.edgeMac, &idx, sss->mac_addr);
|
||||
|
||||
idx = 0;
|
||||
encode_REGISTER_SUPER(pktbuf, &idx, &cmn, ®);
|
||||
|
@ -561,12 +564,14 @@ static int re_register_and_purge_supernodes(n2n_sn_t *sss, struct sn_community *
|
|||
comm->header_iv_ctx,
|
||||
time_stamp(), pearson_hash_16(pktbuf, idx));
|
||||
|
||||
/* sent = */ sendto_sock(sss, &(peer->sock), pktbuf, N2N_PKT_BUF_SIZE);
|
||||
/* sent = */ sendto_sock(sss, &(peer->sock), pktbuf, idx);
|
||||
}
|
||||
if(time >= PURGE_FEDERATION_NODE_INTERVAL) purge_expired_registrations(&(comm->edges),&time,PURGE_FEDERATION_NODE_INTERVAL);/* purge not-seen-long-time supernodes*/
|
||||
}
|
||||
}
|
||||
|
||||
(*p_last_re_reg_and_purge) = now;
|
||||
|
||||
return 0; /* OK */
|
||||
}
|
||||
|
||||
|
@ -735,46 +740,6 @@ static int sendto_mgmt(n2n_sn_t *sss,
|
|||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/** 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
|
||||
* Evaluate first the MAC parameter and if it's zero-MAC, then it can skip HASH_FIND_PEER by MAC and search by socket
|
||||
*/
|
||||
struct peer_info* add_sn_to_federation_by_mac_or_sock(n2n_sn_t *sss,n2n_sock_t *sock, n2n_mac_t *mac) {
|
||||
struct peer_info *scan, *tmp, *peer = NULL;
|
||||
int found = 0;
|
||||
|
||||
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(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.
|
||||
*
|
||||
*/
|
||||
|
@ -1059,6 +1024,7 @@ static int process_udp(n2n_sn_t * sss,
|
|||
n2n_common_t cmn2;
|
||||
uint8_t ackbuf[N2N_SN_PKTBUF_SIZE];
|
||||
uint8_t tmpbuf[MAX_AVAILABLE_SPACE_FOR_ENTRIES];
|
||||
uint8_t *tmp_dst;
|
||||
size_t encx=0;
|
||||
struct sn_community *fed;
|
||||
struct sn_community_regular_expression *re, *tmp_re;
|
||||
|
@ -1068,8 +1034,7 @@ static int process_udp(n2n_sn_t * sss,
|
|||
int match_length = 0;
|
||||
n2n_ip_subnet_t ipaddr;
|
||||
int num = 0;
|
||||
n2n_sock_t *tmp_sock;
|
||||
n2n_mac_t *tmp_mac;
|
||||
int skip_add;
|
||||
|
||||
memset(&ack, 0, sizeof(n2n_REGISTER_SUPER_ACK_t));
|
||||
|
||||
|
@ -1138,7 +1103,13 @@ static int process_udp(n2n_sn_t * sss,
|
|||
memcpy(cmn2.community, cmn.community, sizeof(n2n_community_t));
|
||||
|
||||
memcpy(&(ack.cookie), &(reg.cookie), sizeof(n2n_cookie_t));
|
||||
memcpy(ack.edgeMac, reg.edgeMac, sizeof(n2n_mac_t));
|
||||
|
||||
if(comm->is_federation == IS_FEDERATION){
|
||||
memcpy(&(ack.edgeMac), &(sss->mac_addr), sizeof(n2n_mac_t));
|
||||
}else{
|
||||
memcpy(&(ack.edgeMac), &(reg.edgeMac), sizeof(n2n_mac_t));
|
||||
}
|
||||
|
||||
if ((reg.dev_addr.net_addr == 0) || (reg.dev_addr.net_addr == 0xFFFFFFFF) || (reg.dev_addr.net_bitlen == 0) ||
|
||||
((reg.dev_addr.net_addr & 0xFFFF0000) == 0xA9FE0000 /* 169.254.0.0 */)) {
|
||||
memset(&ipaddr, 0, sizeof(n2n_ip_subnet_t));
|
||||
|
@ -1152,30 +1123,29 @@ static int process_udp(n2n_sn_t * sss,
|
|||
ack.sock.port = ntohs(sender_sock->sin_port);
|
||||
memcpy(ack.sock.addr.v4, &(sender_sock->sin_addr.s_addr), IPV4_SIZE);
|
||||
|
||||
if(from_supernode != comm->is_federation) {
|
||||
if((from_supernode == 0) != (comm->is_federation == IS_NO_FEDERATION)) {
|
||||
traceEvent(TRACE_DEBUG, "process_udp dropped REGISTER_SUPER: from_supernode value doesn't correspond to the internal federation marking");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Add sender's data to federation (or update it) */
|
||||
if(comm->is_federation == IS_FEDERATION) {
|
||||
p = add_sn_to_federation_by_mac_or_sock(sss,&(ack.sock),&(reg.edgeMac));
|
||||
if(p) p->last_seen = now;
|
||||
skip_add = NO_SKIP;
|
||||
p = add_sn_to_list_by_mac_or_sock(&(sss->federation->edges), &(ack.sock), &(reg.edgeMac), &skip_add);
|
||||
}
|
||||
|
||||
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 */
|
||||
tmp_dst = tmpbuf;
|
||||
HASH_ITER(hh, sss->federation->edges, peer, tmp_peer) {
|
||||
if(memcmp(&(peer->sock), &(ack.sock), sizeof(n2n_sock_t)) == 0) continue; /* a supernode doesn't add itself to the payload */
|
||||
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;
|
||||
memcpy((void*)tmp_dst, (void*)&(peer->sock), sizeof(n2n_sock_t));
|
||||
tmp_dst += sizeof(n2n_sock_t);
|
||||
memcpy((void*)tmp_dst, (void*)&(peer->mac_addr), sizeof(n2n_mac_t));
|
||||
tmp_dst += sizeof(n2n_mac_t);
|
||||
}
|
||||
ack.num_sn = num;
|
||||
|
||||
|
@ -1222,7 +1192,9 @@ static int process_udp(n2n_sn_t * sss,
|
|||
n2n_mac_t *tmp_mac;
|
||||
int i;
|
||||
uint8_t dec_tmpbuf[MAX_AVAILABLE_SPACE_FOR_ENTRIES];
|
||||
int skip_add;
|
||||
|
||||
memset(&sender, 0, sizeof(n2n_sock_t));
|
||||
sender.family = AF_INET;
|
||||
sender.port = ntohs(sender_sock->sin_port);
|
||||
memcpy(&(sender.addr.v4), &(sender_sock->sin_addr.s_addr), IPV4_SIZE);
|
||||
|
@ -1235,7 +1207,7 @@ static int process_udp(n2n_sn_t * sss,
|
|||
return -1;
|
||||
}
|
||||
|
||||
if(from_supernode != comm->is_federation) {
|
||||
if((from_supernode == 0) != (comm->is_federation == IS_NO_FEDERATION)) {
|
||||
traceEvent(TRACE_DEBUG, "process_udp dropped REGISTER_SUPER_ACK: from_supernode value doesn't correspond to the internal federation marking.");
|
||||
return -1;
|
||||
}
|
||||
|
@ -1258,7 +1230,8 @@ static int process_udp(n2n_sn_t * sss,
|
|||
sock_to_cstr(sockbuf2, orig_sender));
|
||||
|
||||
if(comm->is_federation == IS_FEDERATION) {
|
||||
HASH_FIND_PEER(sss->federation->edges, ack.edgeMac, scan);
|
||||
skip_add = SKIP;
|
||||
scan = add_sn_to_list_by_mac_or_sock(&(sss->federation->edges), &sender, &(ack.edgeMac), &skip_add);
|
||||
if(scan != NULL) {
|
||||
scan->last_seen = now;
|
||||
} else {
|
||||
|
@ -1267,18 +1240,20 @@ static int process_udp(n2n_sn_t * sss,
|
|||
}
|
||||
}
|
||||
|
||||
tmp_sock = (void*)&(ack.num_sn) + sizeof(ack.num_sn);
|
||||
tmp_mac = (void*)tmp_sock + sizeof(n2n_sock_t);
|
||||
tmp_sock = (void *)dec_tmpbuf;
|
||||
tmp_mac = (void*)dec_tmpbuf + 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);
|
||||
skip_add = NO_SKIP;
|
||||
tmp = add_sn_to_list_by_mac_or_sock(&(sss->federation->edges), tmp_sock, tmp_mac, &skip_add);
|
||||
|
||||
if(tmp) {
|
||||
if(skip_add == ADDED) {
|
||||
tmp->last_seen = now - TEST_TIME;
|
||||
}
|
||||
|
||||
tmp_sock += ENTRY_SIZE;
|
||||
tmp_mac += ENTRY_SIZE;
|
||||
/* REVISIT: find a more elegant expression to increase following pointers. */
|
||||
tmp_sock = (void*)tmp_sock + ENTRY_SIZE;
|
||||
tmp_mac = (void*)tmp_sock + sizeof(n2n_sock_t);
|
||||
}
|
||||
|
||||
break;
|
||||
|
@ -1305,6 +1280,34 @@ static int process_udp(n2n_sn_t * sss,
|
|||
}
|
||||
}
|
||||
|
||||
if(memcmp(query.targetMac, null_mac, sizeof(n2n_mac_t)) == 0){
|
||||
traceEvent( TRACE_DEBUG, "Rx PING from %s. Requested data: %d",
|
||||
macaddr_str( mac_buf, query.srcMac ),
|
||||
query.req_data );
|
||||
|
||||
cmn2.ttl = N2N_DEFAULT_TTL;
|
||||
cmn2.pc = n2n_peer_info;
|
||||
cmn2.flags = N2N_FLAGS_FROM_SUPERNODE;
|
||||
memcpy( cmn2.community, cmn.community, sizeof(n2n_community_t) );
|
||||
|
||||
pi.aflags = 0;
|
||||
memcpy( pi.mac, query.targetMac, sizeof(n2n_mac_t) );
|
||||
memcpy( pi.srcMac, sss->mac_addr, sizeof(n2n_mac_t) );
|
||||
|
||||
encode_PEER_INFO( encbuf, &encx, &cmn2, &pi );
|
||||
|
||||
if (comm->header_encryption == HEADER_ENCRYPTION_ENABLED)
|
||||
packet_header_encrypt (encbuf, encx, comm->header_encryption_ctx,
|
||||
comm->header_iv_ctx,
|
||||
time_stamp (), pearson_hash_16 (encbuf, encx));
|
||||
|
||||
sendto( sss->sock, encbuf, encx, 0,
|
||||
(struct sockaddr *)sender_sock, sizeof(struct sockaddr_in) );
|
||||
|
||||
traceEvent( TRACE_DEBUG, "Tx PING to %s",
|
||||
macaddr_str( mac_buf, query.srcMac ) );
|
||||
|
||||
} else {
|
||||
traceEvent( TRACE_DEBUG, "Rx QUERY_PEER from %s for %s",
|
||||
macaddr_str( mac_buf, query.srcMac ),
|
||||
macaddr_str( mac_buf2, query.targetMac ) );
|
||||
|
@ -1339,6 +1342,8 @@ static int process_udp(n2n_sn_t * sss,
|
|||
macaddr_str( mac_buf, query.targetMac ) );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
|
@ -1356,6 +1361,7 @@ int run_sn_loop(n2n_sn_t *sss, int *keep_running)
|
|||
uint8_t pktbuf[N2N_SN_PKTBUF_SIZE];
|
||||
time_t last_purge_edges = 0;
|
||||
time_t last_sort_communities = 0;
|
||||
time_t last_re_reg_and_purge = 0;
|
||||
|
||||
sss->start_time = time(NULL);
|
||||
|
||||
|
@ -1440,7 +1446,7 @@ int run_sn_loop(n2n_sn_t *sss, int *keep_running)
|
|||
traceEvent(TRACE_DEBUG, "timeout");
|
||||
}
|
||||
|
||||
re_register_and_purge_supernodes(sss, sss->federation, now);
|
||||
re_register_and_purge_supernodes(sss, sss->federation, &last_re_reg_and_purge, now);
|
||||
purge_expired_communities(sss, &last_purge_edges, now);
|
||||
sort_communities (sss, &last_sort_communities, now);
|
||||
} /* while */
|
||||
|
|
|
@ -514,6 +514,7 @@ int encode_PEER_INFO(uint8_t *base,
|
|||
int retval = 0;
|
||||
retval += encode_common(base, idx, common);
|
||||
retval += encode_uint16(base, idx, pkt->aflags);
|
||||
retval += encode_mac(base, idx, pkt->srcMac);
|
||||
retval += encode_mac(base, idx, pkt->mac);
|
||||
retval += encode_sock(base, idx, &pkt->sock);
|
||||
|
||||
|
@ -529,6 +530,7 @@ int decode_PEER_INFO(n2n_PEER_INFO_t *pkt,
|
|||
size_t retval = 0;
|
||||
memset(pkt, 0, sizeof(n2n_PEER_INFO_t));
|
||||
retval += decode_uint16(&(pkt->aflags), base, rem, idx);
|
||||
retval += decode_mac(pkt->srcMac, base, rem, idx);
|
||||
retval += decode_mac(pkt->mac, base, rem, idx);
|
||||
retval += decode_sock(&pkt->sock, base, rem, idx);
|
||||
|
||||
|
@ -545,6 +547,7 @@ int encode_QUERY_PEER( uint8_t * base,
|
|||
retval += encode_common( base, idx, common );
|
||||
retval += encode_mac( base, idx, pkt->srcMac );
|
||||
retval += encode_mac( base, idx, pkt->targetMac );
|
||||
retval += encode_uint8( base, idx, pkt->req_data);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
@ -559,6 +562,7 @@ int decode_QUERY_PEER( n2n_QUERY_PEER_t * pkt,
|
|||
memset( pkt, 0, sizeof(n2n_QUERY_PEER_t) );
|
||||
retval += decode_mac( pkt->srcMac, base, rem, idx );
|
||||
retval += decode_mac( pkt->targetMac, base, rem, idx );
|
||||
retval += decode_uint8( &pkt->req_data, base, rem, idx);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user