From a639e1d7350dfbb95000b8d9979706d8a48e8cae Mon Sep 17 00:00:00 2001 From: Logan oos Even <46396513+Logan007@users.noreply.github.com> Date: Mon, 18 Jan 2021 00:12:45 +0545 Subject: [PATCH] properly handled supernodes' timestamps (#591) --- include/n2n_typedefs.h | 1 - src/edge_utils.c | 39 ++++++++++++++++++++------------ src/n2n.c | 1 + src/sn_utils.c | 50 +++++++++++++++++++++++++++++++----------- 4 files changed, 63 insertions(+), 28 deletions(-) diff --git a/include/n2n_typedefs.h b/include/n2n_typedefs.h index fc5a8ff..43cee19 100644 --- a/include/n2n_typedefs.h +++ b/include/n2n_typedefs.h @@ -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 */ diff --git a/src/edge_utils.c b/src/edge_utils.c index 60b0fbb..b39117b 100644 --- a/src/edge_utils.c +++ b/src/edge_utils.c @@ -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(); } } diff --git a/src/n2n.c b/src/n2n.c index 55076a1..9229617 100644 --- a/src/n2n.c +++ b/src/n2n.c @@ -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); diff --git a/src/sn_utils.c b/src/sn_utils.c index 52805f8..8eb354c 100644 --- a/src/sn_utils.c +++ b/src/sn_utils.c @@ -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; }