diff --git a/include/n2n_define.h b/include/n2n_define.h index abba7cb..d3827d7 100644 --- a/include/n2n_define.h +++ b/include/n2n_define.h @@ -29,8 +29,18 @@ #define MSG_TYPE_QUERY_PEER 10 #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 */ +#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) \ + +/* Space needed to store socket and MAC address of a supernode */ +#define ENTRY_SIZE sizeof(n2n_sock_t)+sizeof(n2n_mac_t) + #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 (SORT_COMMUNITIES_INTERVAL - ALLOWED_TIME)/2 /* sec, indicates supernodes with unsure status, must be tested to check if they are alive */ #define IFACE_UPDATE_INTERVAL (30) /* sec. How long it usually takes to get an IP lease. */ #define TRANSOP_TICK_INTERVAL (10) /* sec */ diff --git a/include/n2n_wire.h b/include/n2n_wire.h index 855a9a9..f1593f7 100644 --- a/include/n2n_wire.h +++ b/include/n2n_wire.h @@ -170,6 +170,7 @@ typedef struct n2n_REGISTER_SUPER_ACK { * even if we cannot store them all. If * non-zero then sn_bak is valid. */ n2n_sock_t sn_bak; /**< Socket of the first backup supernode */ + n2n_mac_t mac_addr; } n2n_REGISTER_SUPER_ACK_t; diff --git a/src/sn_utils.c b/src/sn_utils.c index 1ab8573..b5e719e 100644 --- a/src/sn_utils.c +++ b/src/sn_utils.c @@ -941,15 +941,25 @@ static int process_udp(n2n_sn_t * sss, n2n_common_t cmn2; uint8_t ackbuf[N2N_SN_PKTBUF_SIZE]; size_t encx=0; + struct sn_community *fed; struct sn_community_regular_expression *re, *tmp_re; + struct peer_info *peer, *tmp_peer, *p; int8_t allowed_match = -1; uint8_t match = 0; - int match_length = 0; + int match_length = 0; n2n_ip_subnet_t ipaddr; + int num = 0; + n2n_sock_t *tmp_sock; + n2n_mac_t *tmp_mac; + if(from_supernode != comm->is_federation){ + traceEvent(TRACE_DEBUG, "process_udp dropped REGISTER_SUPER: from_supernode value doesn't correspond to the internal federation marking"); + return -1; + } + memset(&ack, 0, sizeof(n2n_REGISTER_SUPER_ACK_t)); - /* Edge requesting registration with us. */ + /* Edge/supernode requesting registration with us. */ sss->stats.last_reg_super=now; ++(sss->stats.reg_super); decode_REGISTER_SUPER(®, &cmn, udp_buf, &rem, &idx); @@ -1008,6 +1018,7 @@ static int process_udp(n2n_sn_t * sss, } if(comm) { + HASH_FIND_COMMUNITY(sss->communities, sss->federation, fed); cmn2.ttl = N2N_DEFAULT_TTL; cmn2.pc = n2n_register_super_ack; cmn2.flags = N2N_FLAGS_SOCKET | N2N_FLAGS_FROM_SUPERNODE; @@ -1028,9 +1039,23 @@ 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); - ack.num_sn=0; /* No backup */ - - traceEvent(TRACE_DEBUG, "Rx REGISTER_SUPER for %s [%s]", + if(fed != NULL){ + HASH_FIND_PEER(fed->edges, reg.edgeMac, p); + p->last_seen = now; + tmp_sock = &(ack.sn_bak); + tmp_mac = &(ack.mac_addr); + HASH_ITER(hh, fed->edges, peer, tmp_peer){ + 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(tmp_sock, &(scan->sock), sizeof(n2n_sock_t)); + memcpy(tmp_mac, &(scan->mac_addr), sizeof(n2n_mac_t)); + tmp_sock += sizeof(n2n_mac_t); + tmp_mac += sizeof(n2n_sock_t); + } + ack.num_sn = num; + } + + traceEvent(TRACE_DEBUG, "Rx REGISTER_SUPER for %s [%s]", macaddr_str(mac_buf, reg.edgeMac), sock_to_cstr(sockbuf, &(ack.sock))); diff --git a/src/wire.c b/src/wire.c index d393dd0..0059571 100644 --- a/src/wire.c +++ b/src/wire.c @@ -408,6 +408,7 @@ int encode_REGISTER_SUPER_ACK(uint8_t *base, if (reg->num_sn > 0) { /* We only support 0 or 1 at this stage */ retval += encode_sock(base, idx, &(reg->sn_bak)); + retval += encode_mac(base, idx, reg->mac_addr); } return retval; @@ -436,7 +437,8 @@ int decode_REGISTER_SUPER_ACK(n2n_REGISTER_SUPER_ACK_t *reg, if (reg->num_sn > 0) { /* We only support 0 or 1 at this stage */ retval += decode_sock(&(reg->sn_bak), base, rem, idx); - } + retval += decode_mac(reg->mac_addr, base, rem, idx); + } return retval; }