Browse Source

Packet forwarding between supernodes (#486)

* Packet forwarding between supernodes

* Update wire.c
pull/494/head
Francesco Carli 4 years ago
committed by GitHub
parent
commit
e65fd984d7
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 18
      include/n2n_define.h
  2. 1
      include/n2n_wire.h
  3. 20
      src/edge_utils.c
  4. 8
      src/n2n.c
  5. 2
      src/sn.c
  6. 204
      src/sn_utils.c
  7. 4
      src/wire.c

18
include/n2n_define.h

@ -32,23 +32,25 @@
/* Max available space to add supernodes' informations (sockets and MACs) in REGISTER_SUPER_ACK /* 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. */ * REVISIT: replace 255 by DEFAULT_MTU as soon as header encryption allows for longer packets to be encrypted. */
#define MAX_AVAILABLE_SPACE_FOR_ENTRIES \ #define REG_SUPER_ACK_PAYLOAD_SPACE \
(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)) \ (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 */ /* Space needed to store socket and MAC address of a supernode */
#define ENTRY_SIZE (sizeof(n2n_sock_t)+sizeof(n2n_mac_t)) #define REG_SUPER_ACK_PAYLOAD_ENTRY_SIZE (sizeof(n2n_sock_t)+sizeof(n2n_mac_t))
#define PURGE_REGISTRATION_FREQUENCY 30 #define PURGE_REGISTRATION_FREQUENCY 30
#define RE_REG_AND_PURGE_FREQUENCY 10 #define RE_REG_AND_PURGE_FREQUENCY 10
#define REGISTRATION_TIMEOUT 60 #define REGISTRATION_TIMEOUT 60
#define PURGE_FEDERATION_NODE_INTERVAL 90
#define SOCKET_TIMEOUT_INTERVAL_SECS 10 #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 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 MAX_PING_TIME 3000 /* millisec, indicates default value for ping_time field in peer_info structure */
#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 SWEEP_TIME 30 /* sec, indicates the value after which we have to sort the hash list of supernodes in edges */
#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 LAST_SEEN_SN_ACTIVE 20 /* sec, indicates supernodes that are proven to be active */
#define LAST_SEEN_SN_INACTIVE 90 /* sec, indicates supernodes that are proven to be inactive: they will be purged */
#define LAST_SEEN_SN_NEW (LAST_SEEN_SN_INACTIVE - LAST_SEEN_SN_ACTIVE)/2 /* sec, indicates supernodes with unsure status, must be tested to check if they are active */
#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 */
@ -108,7 +110,7 @@ enum sn_purge{SN_PURGEABLE = 0, SN_UNPURGEABLE = 1};
#define N2N_SN_MGMT_PORT 5645 #define N2N_SN_MGMT_PORT 5645
/* flag used in add_sn_to_list_by_mac_or_sock */ /* flag used in add_sn_to_list_by_mac_or_sock */
enum skip_add{NO_SKIP = 0, SKIP = 1, ADDED = 2}; enum skip_add{SN_ADD = 0, SN_ADD_SKIP = 1, SN_ADD_ADDED = 2};
#define N2N_NETMASK_STR_SIZE 16 /* dotted decimal 12 numbers + 3 dots */ #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_MACNAMSIZ 18 /* AA:BB:CC:DD:EE:FF + NULL*/

1
include/n2n_wire.h

@ -195,6 +195,7 @@ typedef struct n2n_PEER_INFO {
typedef struct n2n_QUERY_PEER typedef struct n2n_QUERY_PEER
{ {
n2n_mac_t srcMac; n2n_mac_t srcMac;
n2n_sock_t sock;
n2n_mac_t targetMac; 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 ...) */ 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; } n2n_QUERY_PEER_t;

20
src/edge_utils.c

@ -1956,12 +1956,12 @@ void readFromIPSocket(n2n_edge_t * eee, int in_sock) {
in_addr_t net; in_addr_t net;
char * ip_str = NULL; char * ip_str = NULL;
n2n_REGISTER_SUPER_ACK_t ra; n2n_REGISTER_SUPER_ACK_t ra;
uint8_t tmpbuf[MAX_AVAILABLE_SPACE_FOR_ENTRIES]; uint8_t tmpbuf[MAX_AVAILABLE_SPACE_FOR_ENTRIES];
n2n_sock_t *tmp_sock; n2n_sock_t *tmp_sock;
n2n_mac_t *tmp_mac; n2n_mac_t *tmp_mac;
int i; int i;
int skip_add; int skip_add;
struct peer_info *sn; struct peer_info *sn;
memset(&ra, 0, sizeof(n2n_REGISTER_SUPER_ACK_t)); memset(&ra, 0, sizeof(n2n_REGISTER_SUPER_ACK_t));
@ -2005,10 +2005,10 @@ void readFromIPSocket(n2n_edge_t * eee, int in_sock) {
tmp_mac = (void*)&tmpbuf[sizeof(n2n_sock_t)]; tmp_mac = (void*)&tmpbuf[sizeof(n2n_sock_t)];
for(i=0; i<ra.num_sn; i++){ for(i=0; i<ra.num_sn; i++){
skip_add = NO_SKIP; skip_add = SN_ADD;
sn = add_sn_to_list_by_mac_or_sock(&(eee->conf.supernodes), tmp_sock, tmp_mac, &skip_add); sn = add_sn_to_list_by_mac_or_sock(&(eee->conf.supernodes), tmp_sock, tmp_mac, &skip_add);
if(skip_add == ADDED){ if(skip_add == SN_ADD_ADDED){
sn->ip_addr = calloc(1,N2N_EDGE_SN_HOST_SIZE); sn->ip_addr = calloc(1,N2N_EDGE_SN_HOST_SIZE);
if(sn->ip_addr != NULL){ if(sn->ip_addr != NULL){
inet_ntop(tmp_sock->family, inet_ntop(tmp_sock->family,
@ -2085,7 +2085,7 @@ void readFromIPSocket(n2n_edge_t * eee, int in_sock) {
} }
if(memcmp(pi.mac, null_mac, sizeof(n2n_mac_t)) == 0){ if(memcmp(pi.mac, null_mac, sizeof(n2n_mac_t)) == 0){
skip_add = SKIP; skip_add = SN_ADD_SKIP;
scan = add_sn_to_list_by_mac_or_sock(&(eee->conf.supernodes), &sender, &pi.srcMac, &skip_add); scan = add_sn_to_list_by_mac_or_sock(&(eee->conf.supernodes), &sender, &pi.srcMac, &skip_add);
if(scan != NULL){ if(scan != NULL){
scan->ping_time = (now - eee->last_sweep)*1000; scan->ping_time = (now - eee->last_sweep)*1000;
@ -2818,7 +2818,7 @@ int edge_conf_add_supernode(n2n_edge_conf_t *conf, const char *ip_and_port) {
return(1); return(1);
} }
skip_add = NO_SKIP; skip_add = SN_ADD;
sn = add_sn_to_list_by_mac_or_sock(&(conf->supernodes), sock, (n2n_mac_t *)null_mac, &skip_add); sn = add_sn_to_list_by_mac_or_sock(&(conf->supernodes), sock, (n2n_mac_t *)null_mac, &skip_add);
if(sn != NULL){ if(sn != NULL){

8
src/n2n.c

@ -301,21 +301,21 @@ struct peer_info* add_sn_to_list_by_mac_or_sock(struct peer_info **sn_list, n2n_
if(peer == NULL) { /* zero MAC, search by socket */ if(peer == NULL) { /* zero MAC, search by socket */
HASH_ITER(hh,*sn_list,scan,tmp) { HASH_ITER(hh,*sn_list,scan,tmp) {
if(memcmp(&(scan->sock), sock, sizeof(n2n_sock_t)) == 0) { if(memcmp(&(scan->sock), sock, sizeof(n2n_sock_t)) == 0) {
HASH_DEL(*sn_list, scan); HASH_DEL(*sn_list, scan);
memcpy(&(scan->mac_addr), mac, sizeof(n2n_mac_t)); memcpy(&(scan->mac_addr), mac, sizeof(n2n_mac_t));
HASH_ADD_PEER(*sn_list, scan); HASH_ADD_PEER(*sn_list, scan);
peer = scan; peer = scan;
break; break;
} }
} }
if((peer == NULL) && (*skip_add == NO_SKIP)) { if((peer == NULL) && (*skip_add == SN_ADD)) {
peer = (struct peer_info*)calloc(1,sizeof(struct peer_info)); peer = (struct peer_info*)calloc(1,sizeof(struct peer_info));
if(peer) { if(peer) {
memcpy(&(peer->sock),sock,sizeof(n2n_sock_t)); memcpy(&(peer->sock),sock,sizeof(n2n_sock_t));
memcpy(&(peer->mac_addr),mac, sizeof(n2n_mac_t)); memcpy(&(peer->mac_addr),mac, sizeof(n2n_mac_t));
HASH_ADD_PEER(*sn_list, peer); HASH_ADD_PEER(*sn_list, peer);
*skip_add = ADDED; *skip_add = SN_ADD_ADDED;
} }
} }
} }

2
src/sn.c

@ -276,7 +276,7 @@ static int setOption(int optkey, char *_optarg, n2n_sn_t *sss) {
if(sss->federation != NULL) { if(sss->federation != NULL) {
skip_add = NO_SKIP; skip_add = SN_ADD;
anchor_sn = add_sn_to_list_by_mac_or_sock(&(sss->federation->edges), socket, (n2n_mac_t*) null_mac, &skip_add); 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){ if(anchor_sn != NULL){

204
src/sn_utils.c

@ -25,7 +25,8 @@ static int try_forward(n2n_sn_t * sss,
const n2n_common_t * cmn, const n2n_common_t * cmn,
const n2n_mac_t dstMac, const n2n_mac_t dstMac,
const uint8_t * pktbuf, const uint8_t * pktbuf,
size_t pktsize); size_t pktsize,
uint8_t from_supernode);
static ssize_t sendto_sock(n2n_sn_t *sss, static ssize_t sendto_sock(n2n_sn_t *sss,
const n2n_sock_t *sock, const n2n_sock_t *sock,
@ -42,7 +43,8 @@ static int try_broadcast(n2n_sn_t * sss,
const n2n_common_t * cmn, const n2n_common_t * cmn,
const n2n_mac_t srcMac, const n2n_mac_t srcMac,
const uint8_t * pktbuf, const uint8_t * pktbuf,
size_t pktsize); size_t pktsize,
uint8_t from_supernode);
static uint16_t reg_lifetime(n2n_sn_t *sss); static uint16_t reg_lifetime(n2n_sn_t *sss);
@ -81,7 +83,8 @@ static int try_forward(n2n_sn_t * sss,
const n2n_common_t * cmn, const n2n_common_t * cmn,
const n2n_mac_t dstMac, const n2n_mac_t dstMac,
const uint8_t * pktbuf, const uint8_t * pktbuf,
size_t pktsize) size_t pktsize,
uint8_t from_supernode)
{ {
struct peer_info * scan; struct peer_info * scan;
macstr_t mac_buf; macstr_t mac_buf;
@ -114,10 +117,15 @@ static int try_forward(n2n_sn_t * sss,
} }
else else
{ {
traceEvent(TRACE_DEBUG, "try_forward unknown MAC"); if(!from_supernode){
/* Forwarding packet to all federated supernodes. */
/* Not a known MAC so drop. */ traceEvent(TRACE_DEBUG, "Unknown MAC. Broadcasting packet to all federated supernodes.");
return(-2); try_broadcast(sss, NULL, cmn, sss->mac_addr, pktbuf, pktsize, from_supernode);
} else {
traceEvent(TRACE_DEBUG, "try_forward unknown MAC. Dropping the packet.");
/* Not a known MAC so drop. */
return(-2);
}
} }
return(0); return(0);
@ -167,7 +175,8 @@ static int try_broadcast(n2n_sn_t * sss,
const n2n_common_t * cmn, const n2n_common_t * cmn,
const n2n_mac_t srcMac, const n2n_mac_t srcMac,
const uint8_t * pktbuf, const uint8_t * pktbuf,
size_t pktsize) size_t pktsize,
uint8_t from_supernode)
{ {
struct peer_info *scan, *tmp; struct peer_info *scan, *tmp;
macstr_t mac_buf; macstr_t mac_buf;
@ -175,32 +184,63 @@ static int try_broadcast(n2n_sn_t * sss,
traceEvent(TRACE_DEBUG, "try_broadcast"); traceEvent(TRACE_DEBUG, "try_broadcast");
HASH_ITER(hh, comm->edges, scan, tmp) { /* We have to make sure that a broadcast reaches the other supernodes and edges
if(memcmp(srcMac, scan->mac_addr, sizeof(n2n_mac_t)) != 0) { * connected to them. try_broadcast needs a from_supernode parameter: if set
/* REVISIT: exclude if the destination socket is where the packet came from. */ * do forward to edges of community only. If unset. forward to all locally known
* nodes and all supernodes */
if (!from_supernode) {
HASH_ITER(hh, sss->federation->edges, scan, tmp) {
int data_sent_len; int data_sent_len;
data_sent_len = sendto_sock(sss, &(scan->sock), pktbuf, pktsize); data_sent_len = sendto_sock(sss, &(scan->sock), pktbuf, pktsize);
if(data_sent_len != pktsize) if(data_sent_len != pktsize)
{ {
++(sss->stats.errors); ++(sss->stats.errors);
traceEvent(TRACE_WARNING, "multicast %lu to [%s] %s failed %s", traceEvent(TRACE_WARNING, "multicast %lu to supernode [%s] %s failed %s",
pktsize,
sock_to_cstr(sockbuf, &(scan->sock)),
macaddr_str(mac_buf, scan->mac_addr),
strerror(errno));
}
else
{
++(sss->stats.broadcast);
traceEvent(TRACE_DEBUG, "multicast %lu to supernode [%s] %s",
pktsize,
sock_to_cstr(sockbuf, &(scan->sock)),
macaddr_str(mac_buf, scan->mac_addr));
}
}
}
if(comm){
HASH_ITER(hh, comm->edges, scan, tmp) {
if(memcmp(srcMac, scan->mac_addr, sizeof(n2n_mac_t)) != 0) {
/* REVISIT: exclude if the destination socket is where the packet came from. */
int data_sent_len;
data_sent_len = sendto_sock(sss, &(scan->sock), pktbuf, pktsize);
if(data_sent_len != pktsize){
++(sss->stats.errors);
traceEvent(TRACE_WARNING, "multicast %lu to [%s] %s failed %s",
pktsize, pktsize,
sock_to_cstr(sockbuf, &(scan->sock)), sock_to_cstr(sockbuf, &(scan->sock)),
macaddr_str(mac_buf, scan->mac_addr), macaddr_str(mac_buf, scan->mac_addr),
strerror(errno)); strerror(errno));
} else {
++(sss->stats.broadcast);
traceEvent(TRACE_DEBUG, "multicast %lu to [%s] %s",
pktsize,
sock_to_cstr(sockbuf, &(scan->sock)),
macaddr_str(mac_buf, scan->mac_addr));
}
} }
else }
{
++(sss->stats.broadcast);
traceEvent(TRACE_DEBUG, "multicast %lu to [%s] %s",
pktsize,
sock_to_cstr(sockbuf, &(scan->sock)),
macaddr_str(mac_buf, scan->mac_addr));
}
}
} }
return 0; return 0;
} }
@ -251,7 +291,7 @@ int sn_init(n2n_sn_t *sss) {
sss->federation->header_encryption = HEADER_ENCRYPTION_ENABLED; sss->federation->header_encryption = HEADER_ENCRYPTION_ENABLED;
/*setup the encryption key */ /*setup the encryption key */
packet_header_setup_key(sss->federation->community, &(sss->federation->header_encryption_ctx), &(sss->federation->header_iv_ctx)); packet_header_setup_key(sss->federation->community, &(sss->federation->header_encryption_ctx), &(sss->federation->header_iv_ctx));
sss->federation->edges = NULL; sss->federation->edges = NULL;
} }
n2n_srand (n2n_seed()); n2n_srand (n2n_seed());
@ -534,9 +574,9 @@ static int re_register_and_purge_supernodes(n2n_sn_t *sss, struct sn_community *
if(comm != NULL) { if(comm != NULL) {
HASH_ITER(hh,comm->edges,peer,tmp) { HASH_ITER(hh,comm->edges,peer,tmp) {
time = now - peer->last_seen; time = now - peer->last_seen;
if(time <= ALLOWED_TIME) continue; if(time <= LAST_SEEN_SN_ACTIVE) continue;
if((time < PURGE_FEDERATION_NODE_INTERVAL) if((time < LAST_SEEN_SN_INACTIVE)
|| (peer->purgeable == SN_UNPURGEABLE) || (peer->purgeable == SN_UNPURGEABLE)
) { ) {
/* re-regitser (send REGISTER_SUPER) */ /* re-regitser (send REGISTER_SUPER) */
@ -579,7 +619,7 @@ static int re_register_and_purge_supernodes(n2n_sn_t *sss, struct sn_community *
/* sent = */ sendto_sock(sss, &(peer->sock), pktbuf, idx); /* 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*/ if(time >= LAST_SEEN_SN_INACTIVE) purge_expired_registrations(&(comm->edges), &time, LAST_SEEN_SN_INACTIVE);/* purge not-seen-long-time supernodes*/
} }
} }
@ -692,7 +732,7 @@ static int process_mgmt(n2n_sn_t *sss,
} }
} }
ressize += snprintf(resbuf + ressize, N2N_SN_PKTBUF_SIZE - ressize, ressize += snprintf(resbuf + ressize, N2N_SN_PKTBUF_SIZE - ressize,
"--------------------------------------------------------------------------------------------------\n"); "----------------------------------------------------------------------------------------------------\n");
ressize += snprintf(resbuf + ressize, N2N_SN_PKTBUF_SIZE - ressize, ressize += snprintf(resbuf + ressize, N2N_SN_PKTBUF_SIZE - ressize,
"uptime %lu | ", (now - sss->start_time)); "uptime %lu | ", (now - sss->start_time));
@ -955,9 +995,9 @@ static int process_udp(n2n_sn_t * sss,
/* Common section to forward the final product. */ /* Common section to forward the final product. */
if(unicast) if(unicast)
try_forward(sss, comm, &cmn, pkt.dstMac, rec_buf, encx); try_forward(sss, comm, &cmn, pkt.dstMac, rec_buf, encx, from_supernode);
else else
try_broadcast(sss, comm, &cmn, pkt.srcMac, rec_buf, encx); try_broadcast(sss, comm, &cmn, pkt.srcMac, rec_buf, encx, from_supernode);
break; break;
} }
case MSG_TYPE_REGISTER: case MSG_TYPE_REGISTER:
@ -1022,7 +1062,7 @@ static int process_udp(n2n_sn_t * sss,
comm->header_iv_ctx, comm->header_iv_ctx,
time_stamp (), pearson_hash_16 (rec_buf, encx)); time_stamp (), pearson_hash_16 (rec_buf, encx));
try_forward(sss, comm, &cmn, reg.dstMac, rec_buf, encx); /* unicast only */ try_forward(sss, comm, &cmn, reg.dstMac, rec_buf, encx, from_supernode); /* unicast only */
} else } else
traceEvent(TRACE_ERROR, "Rx REGISTER with multicast destination"); traceEvent(TRACE_ERROR, "Rx REGISTER with multicast destination");
break; break;
@ -1036,17 +1076,17 @@ static int process_udp(n2n_sn_t * sss,
n2n_REGISTER_SUPER_ACK_t ack; n2n_REGISTER_SUPER_ACK_t ack;
n2n_common_t cmn2; n2n_common_t cmn2;
uint8_t ackbuf[N2N_SN_PKTBUF_SIZE]; uint8_t ackbuf[N2N_SN_PKTBUF_SIZE];
uint8_t tmpbuf[MAX_AVAILABLE_SPACE_FOR_ENTRIES]; uint8_t tmpbuf[REG_SUPER_ACK_PAYLOAD_SPACE];
uint8_t *tmp_dst; uint8_t *tmp_dst;
size_t encx=0; size_t encx=0;
struct sn_community *fed; struct sn_community *fed;
struct sn_community_regular_expression *re, *tmp_re; struct sn_community_regular_expression *re, *tmp_re;
struct peer_info *peer, *tmp_peer, *p; struct peer_info *peer, *tmp_peer, *p;
int8_t allowed_match = -1; int8_t allowed_match = -1;
uint8_t match = 0; uint8_t match = 0;
int match_length = 0; int match_length = 0;
n2n_ip_subnet_t ipaddr; n2n_ip_subnet_t ipaddr;
int num = 0; int num = 0;
int skip_add; int skip_add;
memset(&ack, 0, sizeof(n2n_REGISTER_SUPER_ACK_t)); memset(&ack, 0, sizeof(n2n_REGISTER_SUPER_ACK_t));
@ -1117,9 +1157,9 @@ static int process_udp(n2n_sn_t * sss,
memcpy(&(ack.cookie), &(reg.cookie), sizeof(n2n_cookie_t)); memcpy(&(ack.cookie), &(reg.cookie), sizeof(n2n_cookie_t));
if(comm->is_federation == IS_FEDERATION){ if(comm->is_federation == IS_FEDERATION){
memcpy(&(ack.edgeMac), &(sss->mac_addr), sizeof(n2n_mac_t)); memcpy(&(ack.edgeMac), &(sss->mac_addr), sizeof(n2n_mac_t));
}else{ } else {
memcpy(&(ack.edgeMac), &(reg.edgeMac), sizeof(n2n_mac_t)); 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) || if ((reg.dev_addr.net_addr == 0) || (reg.dev_addr.net_addr == 0xFFFFFFFF) || (reg.dev_addr.net_bitlen == 0) ||
@ -1142,7 +1182,7 @@ static int process_udp(n2n_sn_t * sss,
/* Add sender's data to federation (or update it) */ /* Add sender's data to federation (or update it) */
if(comm->is_federation == IS_FEDERATION) { if(comm->is_federation == IS_FEDERATION) {
skip_add = NO_SKIP; skip_add = SN_ADD;
p = add_sn_to_list_by_mac_or_sock(&(sss->federation->edges), &(ack.sock), &(reg.edgeMac), &skip_add); p = add_sn_to_list_by_mac_or_sock(&(sss->federation->edges), &(ack.sock), &(reg.edgeMac), &skip_add);
} }
@ -1152,8 +1192,8 @@ static int process_udp(n2n_sn_t * sss,
tmp_dst = tmpbuf; tmp_dst = tmpbuf;
HASH_ITER(hh, sss->federation->edges, peer, tmp_peer) { 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(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((now - peer->last_seen) >= LAST_SEEN_SN_ACTIVE) 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 */ if(((++num)*REG_SUPER_ACK_PAYLOAD_ENTRY_SIZE) > REG_SUPER_ACK_PAYLOAD_SPACE) break; /* no more space available in REGISTER_SUPER_ACK payload */
memcpy((void*)tmp_dst, (void*)&(peer->sock), sizeof(n2n_sock_t)); memcpy((void*)tmp_dst, (void*)&(peer->sock), sizeof(n2n_sock_t));
tmp_dst += sizeof(n2n_sock_t); tmp_dst += sizeof(n2n_sock_t);
memcpy((void*)tmp_dst, (void*)&(peer->mac_addr), sizeof(n2n_mac_t)); memcpy((void*)tmp_dst, (void*)&(peer->mac_addr), sizeof(n2n_mac_t));
@ -1194,19 +1234,19 @@ static int process_udp(n2n_sn_t * sss,
n2n_REGISTER_SUPER_ACK_t ack; n2n_REGISTER_SUPER_ACK_t ack;
size_t encx=0; size_t encx=0;
struct sn_community *fed; struct sn_community *fed;
struct peer_info *scan, *tmp_peer; struct peer_info *scan, *tmp;
n2n_sock_str_t sockbuf1; n2n_sock_str_t sockbuf1;
n2n_sock_str_t sockbuf2; n2n_sock_str_t sockbuf2;
macstr_t mac_buf1; macstr_t mac_buf1;
n2n_sock_t sender; n2n_sock_t sender;
n2n_sock_t *orig_sender; n2n_sock_t *orig_sender;
n2n_sock_t *tmp_sock; n2n_sock_t *tmp_sock;
n2n_mac_t *tmp_mac; n2n_mac_t *tmp_mac;
int i; int i;
uint8_t dec_tmpbuf[MAX_AVAILABLE_SPACE_FOR_ENTRIES]; uint8_t dec_tmpbuf[REG_SUPER_ACK_PAYLOAD_SPACE];
int skip_add; int skip_add;
memset(&sender, 0, sizeof(n2n_sock_t)); memset(&sender, 0, sizeof(n2n_sock_t));
sender.family = AF_INET; sender.family = AF_INET;
sender.port = ntohs(sender_sock->sin_port); sender.port = ntohs(sender_sock->sin_port);
@ -1243,7 +1283,7 @@ static int process_udp(n2n_sn_t * sss,
sock_to_cstr(sockbuf2, orig_sender)); sock_to_cstr(sockbuf2, orig_sender));
if(comm->is_federation == IS_FEDERATION) { if(comm->is_federation == IS_FEDERATION) {
skip_add = SKIP; skip_add = SN_ADD_SKIP;
scan = add_sn_to_list_by_mac_or_sock(&(sss->federation->edges), &sender, &(ack.edgeMac), &skip_add); scan = add_sn_to_list_by_mac_or_sock(&(sss->federation->edges), &sender, &(ack.edgeMac), &skip_add);
if(scan != NULL) { if(scan != NULL) {
scan->last_seen = now; scan->last_seen = now;
@ -1257,15 +1297,15 @@ static int process_udp(n2n_sn_t * sss,
tmp_mac = (void*)dec_tmpbuf + sizeof(n2n_sock_t); tmp_mac = (void*)dec_tmpbuf + sizeof(n2n_sock_t);
for(i=0; i<ack.num_sn; i++) { for(i=0; i<ack.num_sn; i++) {
skip_add = NO_SKIP; skip_add = SN_ADD;
tmp_peer = add_sn_to_list_by_mac_or_sock(&(sss->federation->edges), tmp_sock, tmp_mac, &skip_add); tmp = add_sn_to_list_by_mac_or_sock(&(sss->federation->edges), tmp_sock, tmp_mac, &skip_add);
if(skip_add == ADDED) { if(skip_add == SN_ADD_ADDED) {
tmp_peer->last_seen = now - TEST_TIME; tmp->last_seen = now - LAST_SEEN_SN_NEW;
} }
/* REVISIT: find a more elegant expression to increase following pointers. */ /* REVISIT: find a more elegant expression to increase following pointers. */
tmp_sock = (void*)tmp_sock + ENTRY_SIZE; tmp_sock = (void*)tmp_sock + REG_SUPER_ACK_PAYLOAD_ENTRY_SIZE;
tmp_mac = (void*)tmp_sock + sizeof(n2n_sock_t); tmp_mac = (void*)tmp_sock + sizeof(n2n_sock_t);
} }
@ -1278,10 +1318,11 @@ static int process_udp(n2n_sn_t * sss,
n2n_common_t cmn2; n2n_common_t cmn2;
n2n_PEER_INFO_t pi; n2n_PEER_INFO_t pi;
struct sn_community_regular_expression *re, *tmp_re; struct sn_community_regular_expression *re, *tmp_re;
struct peer_info *peer, *tmp_peer, *p; struct peer_info *peer, *tmp_peer, *p;
int8_t allowed_match = -1; int8_t allowed_match = -1;
uint8_t match = 0; uint8_t match = 0;
int match_length = 0; int match_length = 0;
uint8_t *rec_buf; /* either udp_buf or encbuf */
if(!comm && sss->lock_communities) { if(!comm && sss->lock_communities) {
HASH_ITER(hh, sss->rules, re, tmp_re) { HASH_ITER(hh, sss->rules, re, tmp_re) {
@ -1370,14 +1411,41 @@ static int process_udp(n2n_sn_t * sss,
comm->header_iv_ctx, comm->header_iv_ctx,
time_stamp (), pearson_hash_16 (encbuf, encx)); time_stamp (), pearson_hash_16 (encbuf, encx));
sendto( sss->sock, encbuf, encx, 0, if(cmn.flags & N2N_FLAGS_SOCKET){
(struct sockaddr *)sender_sock, sizeof(struct sockaddr_in) ); sendto_sock(sss, &query.sock, encbuf, encx);
} else {
traceEvent( TRACE_DEBUG, "Tx PEER_INFO to %s", sendto( sss->sock, encbuf, encx, 0,
(struct sockaddr *)sender_sock, sizeof(struct sockaddr_in) );
}
traceEvent( TRACE_DEBUG, "Tx PEER_INFO to %s",
macaddr_str( mac_buf, query.srcMac ) ); macaddr_str( mac_buf, query.srcMac ) );
} else { } else {
traceEvent( TRACE_DEBUG, "Ignoring QUERY_PEER for unknown edge %s",
macaddr_str( mac_buf, query.targetMac ) ); if(from_supernode){
traceEvent( TRACE_DEBUG, "QUERY_PEER on unknown edge from supernode %s. Dropping the packet.",
macaddr_str( mac_buf, query.srcMac ) );
} else {
traceEvent( TRACE_DEBUG, "QUERY_PEER from unknown edge %s. Forwarding to all other supernodes.",
macaddr_str( mac_buf, query.srcMac ) );
memcpy(&cmn2, &cmn, sizeof(n2n_common_t));
/* We are going to add socket even if it was not there before */
cmn2.flags |= N2N_FLAGS_SOCKET | N2N_FLAGS_FROM_SUPERNODE;
query.sock.family = AF_INET;
query.sock.port = ntohs(sender_sock->sin_port);
memcpy(query.sock.addr.v4, &(sender_sock->sin_addr.s_addr), IPV4_SIZE);
encode_QUERY_PEER( encbuf, &encx, &cmn2, &query );
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));
try_broadcast(sss, NULL, &cmn, query.srcMac, encbuf, encx, from_supernode);
}
} }
} }

4
src/wire.c

@ -410,7 +410,7 @@ int encode_REGISTER_SUPER_ACK(uint8_t *base,
retval += encode_uint16(base, idx, reg->lifetime); retval += encode_uint16(base, idx, reg->lifetime);
retval += encode_sock(base, idx, &(reg->sock)); retval += encode_sock(base, idx, &(reg->sock));
retval += encode_uint8(base, idx, reg->num_sn); retval += encode_uint8(base, idx, reg->num_sn);
retval += encode_buf(base, idx, tmpbuf, (reg->num_sn*ENTRY_SIZE)); retval += encode_buf(base, idx, tmpbuf, (reg->num_sn*REG_SUPER_ACK_PAYLOAD_ENTRY_SIZE));
return retval; return retval;
} }
@ -436,7 +436,7 @@ int decode_REGISTER_SUPER_ACK(n2n_REGISTER_SUPER_ACK_t *reg,
/* Following the edge socket are an array of backup supernodes. */ /* Following the edge socket are an array of backup supernodes. */
retval += decode_uint8(&(reg->num_sn), base, rem, idx); retval += decode_uint8(&(reg->num_sn), base, rem, idx);
retval += decode_buf(tmpbuf, (reg->num_sn*ENTRY_SIZE), base, rem, idx); retval += decode_buf(tmpbuf, (reg->num_sn*REG_SUPER_ACK_PAYLOAD_ENTRY_SIZE), base, rem, idx);
return retval; return retval;
} }

Loading…
Cancel
Save