properly handled supernodes' timestamps (#591)

This commit is contained in:
Logan oos Even 2021-01-18 00:12:45 +05:45 committed by GitHub
parent e4e6efacf0
commit a639e1d735
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 63 additions and 28 deletions

View File

@ -624,7 +624,6 @@ struct n2n_edge {
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 */
uint64_t sn_last_valid_time_stamp; /**< last valid time stamp from supernode */
SN_SELECTION_CRITERION_DATA_TYPE sn_selection_criterion_common_data;
/* Sockets */

View File

@ -211,7 +211,6 @@ n2n_edge_t* edge_init (const n2n_edge_conf_t *conf, int *rv) {
eee->known_peers = NULL;
eee->pending_peers = NULL;
eee->sup_attempts = N2N_EDGE_SUP_ATTEMPTS;
eee->sn_last_valid_time_stamp = initial_time_stamp ();
sn_selection_criterion_common_data_default(eee);
pearson_hash_init();
@ -354,7 +353,6 @@ static int is_valid_peer_sock (const n2n_sock_t *sock) {
/* ***************************************************** */
static const int definitely_from_supernode = 1;
/***
*
@ -362,14 +360,14 @@ static const int definitely_from_supernode = 1;
* and verify it (and also update, if applicable).
*/
static int find_peer_time_stamp_and_verify (n2n_edge_t * eee,
int from_supernode, const n2n_mac_t mac,
peer_info_t *sn, const n2n_mac_t mac,
uint64_t stamp, int allow_jitter) {
uint64_t * previous_stamp = NULL;
uint64_t *previous_stamp = NULL;
if(from_supernode) {
if(sn) {
// from supernode
previous_stamp = &(eee->sn_last_valid_time_stamp);
previous_stamp = &(sn->last_valid_time_stamp);
} else {
// from (peer) edge
struct peer_info *peer;
@ -386,9 +384,10 @@ static int find_peer_time_stamp_and_verify (n2n_edge_t * eee,
}
// failure --> 0; success --> 1
return (time_stamp_verify_and_update(stamp, previous_stamp, allow_jitter));
return time_stamp_verify_and_update(stamp, previous_stamp, allow_jitter);
}
/* ************************************** */
/***
@ -1887,12 +1886,14 @@ void readFromIPSocket (n2n_edge_t * eee, int in_sock) {
size_t idx;
size_t msg_type;
uint8_t from_supernode;
peer_info_t *sn = NULL;
struct sockaddr_in sender_sock;
n2n_sock_t sender;
n2n_sock_t * orig_sender = NULL;
time_t now = 0;
uint64_t stamp = 0;
size_t i;
int skip_add = 0;
i = sizeof(sender_sock);
recvlen = recvfrom(in_sock, udp_buf, N2N_PKT_BUF_SIZE, 0/*flags*/,
@ -1953,7 +1954,19 @@ void readFromIPSocket (n2n_edge_t * eee, int in_sock) {
now = time(NULL);
msg_type = cmn.pc; /* packet code */
// check if packet is from supernode and find the corresponding supernode in list
from_supernode = cmn.flags & N2N_FLAGS_FROM_SUPERNODE;
if(from_supernode) {
skip_add = SN_ADD_SKIP;
sn = add_sn_to_list_by_mac_or_sock (&(eee->conf.supernodes), &sender, null_mac, &skip_add);
// a REGISTER_SUPER_NAK could come from some supernode we do not know yet, especially not
// too soon after start-up -- so, we accept it no matter from what supernode
if((!sn) && (msg_type != MSG_TYPE_REGISTER_SUPER_NAK)) {
traceEvent(TRACE_DEBUG, "readFromIPSocket dropped incoming data from unknown supernode.");
return;
}
}
if(0 == memcmp(cmn.community, eee->conf.community_name, N2N_COMMUNITY_SIZE)) {
switch(msg_type) {
@ -1964,7 +1977,7 @@ void readFromIPSocket (n2n_edge_t * eee, int in_sock) {
decode_PACKET(&pkt, &cmn, udp_buf, &rem, &idx);
if(eee->conf.header_encryption == HEADER_ENCRYPTION_ENABLED) {
if(!find_peer_time_stamp_and_verify (eee, from_supernode, pkt.srcMac, stamp, TIME_STAMP_ALLOW_JITTER)) {
if(!find_peer_time_stamp_and_verify (eee, sn, pkt.srcMac, stamp, TIME_STAMP_ALLOW_JITTER)) {
traceEvent(TRACE_DEBUG, "readFromIPSocket dropped PACKET due to time stamp error.");
return;
}
@ -2011,7 +2024,7 @@ void readFromIPSocket (n2n_edge_t * eee, int in_sock) {
via_multicast = is_null_mac(reg.dstMac);
if(eee->conf.header_encryption == HEADER_ENCRYPTION_ENABLED) {
if(!find_peer_time_stamp_and_verify (eee, from_supernode, reg.srcMac, stamp,
if(!find_peer_time_stamp_and_verify (eee, sn, reg.srcMac, stamp,
via_multicast ? TIME_STAMP_ALLOW_JITTER : TIME_STAMP_NO_JITTER)) {
traceEvent(TRACE_DEBUG, "readFromIPSocket dropped REGISTER due to time stamp error.");
return;
@ -2060,7 +2073,7 @@ void readFromIPSocket (n2n_edge_t * eee, int in_sock) {
decode_REGISTER_ACK(&ra, &cmn, udp_buf, &rem, &idx);
if(eee->conf.header_encryption == HEADER_ENCRYPTION_ENABLED) {
if(!find_peer_time_stamp_and_verify (eee, !definitely_from_supernode, ra.srcMac, stamp, TIME_STAMP_NO_JITTER)) {
if(!find_peer_time_stamp_and_verify (eee, sn, ra.srcMac, stamp, TIME_STAMP_NO_JITTER)) {
traceEvent(TRACE_DEBUG, "readFromIPSocket dropped REGISTER_ACK due to time stamp error.");
return;
}
@ -2102,7 +2115,7 @@ void readFromIPSocket (n2n_edge_t * eee, int in_sock) {
decode_REGISTER_SUPER_ACK(&ra, &cmn, udp_buf, &rem, &idx, tmpbuf);
if(eee->conf.header_encryption == HEADER_ENCRYPTION_ENABLED) {
if(!find_peer_time_stamp_and_verify (eee, definitely_from_supernode, null_mac, stamp, TIME_STAMP_NO_JITTER)) {
if(!find_peer_time_stamp_and_verify (eee, sn, null_mac, stamp, TIME_STAMP_NO_JITTER)) {
traceEvent(TRACE_DEBUG, "readFromIPSocket dropped REGISTER_SUPER_ACK due to time stamp error.");
return;
}
@ -2139,7 +2152,6 @@ void readFromIPSocket (n2n_edge_t * eee, int in_sock) {
}
sn_selection_criterion_default(&(sn->selection_criterion));
sn->last_seen = now - LAST_SEEN_SN_NEW;
sn->last_valid_time_stamp = initial_time_stamp();
traceEvent(TRACE_NORMAL, "Supernode '%s' added to the list of supernodes.", sn->ip_addr);
}
// shfiting to the next payload entry
@ -2221,7 +2233,7 @@ void readFromIPSocket (n2n_edge_t * eee, int in_sock) {
decode_PEER_INFO(&pi, &cmn, udp_buf, &rem, &idx);
if(eee->conf.header_encryption == HEADER_ENCRYPTION_ENABLED) {
if(!find_peer_time_stamp_and_verify (eee, definitely_from_supernode, null_mac, stamp, TIME_STAMP_ALLOW_JITTER)) {
if(!find_peer_time_stamp_and_verify (eee, sn, null_mac, stamp, TIME_STAMP_ALLOW_JITTER)) {
traceEvent(TRACE_DEBUG, "readFromIPSocket dropped PEER_INFO due to time stamp error.");
return;
}
@ -3001,7 +3013,6 @@ int edge_conf_add_supernode (n2n_edge_conf_t *conf, const char *ip_and_port) {
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();
}
}

View File

@ -340,6 +340,7 @@ struct peer_info* add_sn_to_list_by_mac_or_sock (struct peer_info **sn_list, n2n
peer = (struct peer_info*)calloc(1, sizeof(struct peer_info));
if(peer) {
sn_selection_criterion_default(&(peer->selection_criterion));
peer->last_valid_time_stamp = initial_time_stamp();
memcpy(&(peer->sock), sock, sizeof(n2n_sock_t));
memcpy(peer->mac_addr, mac, sizeof(n2n_mac_t));
HASH_ADD_PEER(*sn_list, peer);

View File

@ -625,14 +625,17 @@ int assign_one_ip_subnet (n2n_sn_t *sss,
* and verify it (and also update, if applicable).
*/
static int find_edge_time_stamp_and_verify (struct peer_info * edges,
int from_supernode, n2n_mac_t mac,
peer_info_t *sn, n2n_mac_t mac,
uint64_t stamp, int allow_jitter) {
uint64_t * previous_stamp = NULL;
uint64_t *previous_stamp = NULL;
if(!from_supernode) {
if(sn) {
previous_stamp = &(sn->last_valid_time_stamp);
} else {
struct peer_info *edge;
HASH_FIND_PEER(edges, mac, edge);
if(edge) {
// time_stamp_verify_and_update allows the pointer a previous stamp to be NULL
// if it is a (so far) unknown edge
@ -641,9 +644,10 @@ static int find_edge_time_stamp_and_verify (struct peer_info * edges,
}
// failure --> 0; success --> 1
return (time_stamp_verify_and_update(stamp, previous_stamp, allow_jitter));
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 *p_last_re_reg_and_purge, time_t now) {
time_t time;
@ -901,12 +905,15 @@ static int process_udp (n2n_sn_t * sss,
size_t idx;
size_t msg_type;
uint8_t from_supernode;
peer_info_t *sn = NULL;
n2n_sock_t sender;
macstr_t mac_buf;
macstr_t mac_buf2;
n2n_sock_str_t sockbuf;
char buf[32];
struct sn_community *comm, *tmp;
uint64_t stamp;
int skip_add;
traceEvent(TRACE_DEBUG, "Processing incoming UDP packet [len: %lu][sender: %s:%u]",
udp_size, intoa(ntohl(sender_sock->sin_addr.s_addr), buf, sizeof(buf)),
@ -998,7 +1005,26 @@ static int process_udp (n2n_sn_t * sss,
}
msg_type = cmn.pc; /* packet code */
/* 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. */
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);
from_supernode = cmn.flags & N2N_FLAGS_FROM_SUPERNODE;
if(from_supernode) {
skip_add = SN_ADD_SKIP;
sn = add_sn_to_list_by_mac_or_sock (&(sss->federation->edges), &sender, null_mac, &skip_add);
// only REGISTER_SUPER allowed from unknown supernodes
if((!sn) && (msg_type != MSG_TYPE_REGISTER_SUPER)) {
traceEvent(TRACE_DEBUG, "process_udp dropped incoming data from unknown supernode.");
return -1;
}
}
if(cmn.ttl < 1) {
traceEvent(TRACE_WARNING, "Expired TTL");
@ -1030,7 +1056,7 @@ static int process_udp (n2n_sn_t * sss,
// already checked for valid comm
if(comm->header_encryption == HEADER_ENCRYPTION_ENABLED) {
if(!find_edge_time_stamp_and_verify(comm->edges, from_supernode, pkt.srcMac, stamp, TIME_STAMP_ALLOW_JITTER)) {
if(!find_edge_time_stamp_and_verify(comm->edges, sn, pkt.srcMac, stamp, TIME_STAMP_ALLOW_JITTER)) {
traceEvent(TRACE_DEBUG, "process_udp dropped PACKET due to time stamp error.");
return -1;
}
@ -1112,7 +1138,7 @@ static int process_udp (n2n_sn_t * sss,
// already checked for valid comm
if(comm->header_encryption == HEADER_ENCRYPTION_ENABLED) {
if(!find_edge_time_stamp_and_verify(comm->edges, from_supernode, reg.srcMac, stamp, TIME_STAMP_NO_JITTER)) {
if(!find_edge_time_stamp_and_verify(comm->edges, sn, reg.srcMac, stamp, TIME_STAMP_NO_JITTER)) {
traceEvent(TRACE_DEBUG, "process_udp dropped REGISTER due to time stamp error.");
return -1;
}
@ -1183,7 +1209,6 @@ static int process_udp (n2n_sn_t * sss,
int match_length = 0;
n2n_ip_subnet_t ipaddr;
int num = 0;
int skip_add;
int skip;
int ret_value;
@ -1197,7 +1222,7 @@ static int process_udp (n2n_sn_t * sss,
if(comm) {
if(comm->header_encryption == HEADER_ENCRYPTION_ENABLED) {
if(!find_edge_time_stamp_and_verify(comm->edges, from_supernode, reg.edgeMac, stamp, TIME_STAMP_NO_JITTER)) {
if(!find_edge_time_stamp_and_verify(comm->edges, sn, reg.edgeMac, stamp, TIME_STAMP_NO_JITTER)) {
traceEvent(TRACE_DEBUG, "process_udp dropped REGISTER_SUPER due to time stamp error.");
return -1;
}
@ -1404,7 +1429,7 @@ static int process_udp (n2n_sn_t * sss,
decode_UNREGISTER_SUPER(&unreg, &cmn, udp_buf, &rem, &idx);
if(comm->header_encryption == HEADER_ENCRYPTION_ENABLED) {
if(!find_edge_time_stamp_and_verify (comm->edges, from_supernode, unreg.srcMac, stamp, TIME_STAMP_NO_JITTER)) {
if(!find_edge_time_stamp_and_verify (comm->edges, sn, unreg.srcMac, stamp, TIME_STAMP_NO_JITTER)) {
traceEvent(TRACE_DEBUG, "process_udp dropped UNREGISTER_SUPER due to time stamp error.");
return -1;
}
@ -1437,7 +1462,6 @@ static int process_udp (n2n_sn_t * sss,
n2n_mac_t *tmp_mac;
int i;
uint8_t dec_tmpbuf[REG_SUPER_ACK_PAYLOAD_SPACE];
int skip_add;
n2n_REGISTER_SUPER_ACK_payload_t *payload;
memset(&sender, 0, sizeof(n2n_sock_t));
@ -1463,7 +1487,7 @@ static int process_udp (n2n_sn_t * sss,
if(comm) {
if(comm->header_encryption == HEADER_ENCRYPTION_ENABLED) {
if(!find_edge_time_stamp_and_verify (comm->edges, from_supernode, ack.edgeMac, stamp, TIME_STAMP_NO_JITTER)) {
if(!find_edge_time_stamp_and_verify (comm->edges, sn, ack.edgeMac, stamp, TIME_STAMP_NO_JITTER)) {
traceEvent(TRACE_DEBUG, "process_udp dropped REGISTER_SUPER_ACK due to time stamp error.");
return -1;
}
@ -1527,7 +1551,7 @@ static int process_udp (n2n_sn_t * sss,
if(comm) {
if(comm->header_encryption == HEADER_ENCRYPTION_ENABLED) {
if(!find_edge_time_stamp_and_verify (comm->edges, from_supernode, nak.srcMac, stamp, TIME_STAMP_NO_JITTER)) {
if(!find_edge_time_stamp_and_verify (comm->edges, sn, nak.srcMac, stamp, TIME_STAMP_NO_JITTER)) {
traceEvent(TRACE_DEBUG, "process_udp dropped REGISTER_SUPER_NAK due to time stamp error.");
return -1;
}
@ -1588,7 +1612,7 @@ static int process_udp (n2n_sn_t * sss,
// already checked for valid comm
if(comm) {
if(comm->header_encryption == HEADER_ENCRYPTION_ENABLED) {
if(!find_edge_time_stamp_and_verify (comm->edges, from_supernode, query.srcMac, stamp, TIME_STAMP_ALLOW_JITTER)) {
if(!find_edge_time_stamp_and_verify (comm->edges, sn, query.srcMac, stamp, TIME_STAMP_ALLOW_JITTER)) {
traceEvent(TRACE_DEBUG, "process_udp dropped QUERY_PEER due to time stamp error.");
return -1;
}