|
@ -85,29 +85,25 @@ static int try_forward(n2n_sn_t * sss, |
|
|
const n2n_mac_t dstMac, |
|
|
const n2n_mac_t dstMac, |
|
|
uint8_t from_supernode, |
|
|
uint8_t from_supernode, |
|
|
const uint8_t * pktbuf, |
|
|
const uint8_t * pktbuf, |
|
|
size_t pktsize) |
|
|
size_t pktsize) { |
|
|
{ |
|
|
|
|
|
struct peer_info * scan; |
|
|
struct peer_info * scan; |
|
|
macstr_t mac_buf; |
|
|
macstr_t mac_buf; |
|
|
n2n_sock_str_t sockbuf; |
|
|
n2n_sock_str_t sockbuf; |
|
|
|
|
|
|
|
|
HASH_FIND_PEER(comm->edges, dstMac, scan); |
|
|
HASH_FIND_PEER(comm->edges, dstMac, scan); |
|
|
|
|
|
|
|
|
if(NULL != scan) |
|
|
if(NULL != scan) { |
|
|
{ |
|
|
|
|
|
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.fwd); |
|
|
++(sss->stats.fwd); |
|
|
traceEvent(TRACE_DEBUG, "unicast %lu to [%s] %s", |
|
|
traceEvent(TRACE_DEBUG, "unicast %lu to [%s] %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)); |
|
|
} |
|
|
} else { |
|
|
else |
|
|
|
|
|
{ |
|
|
|
|
|
++(sss->stats.errors); |
|
|
++(sss->stats.errors); |
|
|
traceEvent(TRACE_ERROR, "unicast %lu to [%s] %s FAILED (%d: %s)", |
|
|
traceEvent(TRACE_ERROR, "unicast %lu to [%s] %s FAILED (%d: %s)", |
|
|
pktsize, |
|
|
pktsize, |
|
@ -115,9 +111,7 @@ static int try_forward(n2n_sn_t * sss, |
|
|
macaddr_str(mac_buf, scan->mac_addr), |
|
|
macaddr_str(mac_buf, scan->mac_addr), |
|
|
errno, strerror(errno)); |
|
|
errno, strerror(errno)); |
|
|
} |
|
|
} |
|
|
} |
|
|
} else { |
|
|
else |
|
|
|
|
|
{ |
|
|
|
|
|
if(!from_supernode) { |
|
|
if(!from_supernode) { |
|
|
/* Forwarding packet to all federated supernodes. */ |
|
|
/* Forwarding packet to all federated supernodes. */ |
|
|
traceEvent(TRACE_DEBUG, "Unknown MAC. Broadcasting packet to all federated supernodes."); |
|
|
traceEvent(TRACE_DEBUG, "Unknown MAC. Broadcasting packet to all federated supernodes."); |
|
@ -139,12 +133,11 @@ static int try_forward(n2n_sn_t * sss, |
|
|
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, |
|
|
const uint8_t *pktbuf, |
|
|
const uint8_t *pktbuf, |
|
|
size_t pktsize) |
|
|
size_t pktsize) { |
|
|
{ |
|
|
|
|
|
n2n_sock_str_t sockbuf; |
|
|
n2n_sock_str_t sockbuf; |
|
|
|
|
|
|
|
|
if (AF_INET == sock->family) |
|
|
if(AF_INET == sock->family) { |
|
|
{ |
|
|
|
|
|
struct sockaddr_in udpsock; |
|
|
struct sockaddr_in udpsock; |
|
|
|
|
|
|
|
|
udpsock.sin_family = AF_INET; |
|
|
udpsock.sin_family = AF_INET; |
|
@ -157,9 +150,7 @@ static ssize_t sendto_sock(n2n_sn_t *sss, |
|
|
|
|
|
|
|
|
return sendto(sss->sock, pktbuf, pktsize, 0, |
|
|
return sendto(sss->sock, pktbuf, pktsize, 0, |
|
|
(const struct sockaddr *)&udpsock, sizeof(struct sockaddr_in)); |
|
|
(const struct sockaddr *)&udpsock, sizeof(struct sockaddr_in)); |
|
|
} |
|
|
} else { |
|
|
else |
|
|
|
|
|
{ |
|
|
|
|
|
/* AF_INET6 not implemented */ |
|
|
/* AF_INET6 not implemented */ |
|
|
errno = EAFNOSUPPORT; |
|
|
errno = EAFNOSUPPORT; |
|
|
return -1; |
|
|
return -1; |
|
@ -177,8 +168,8 @@ static int try_broadcast(n2n_sn_t * sss, |
|
|
const n2n_mac_t srcMac, |
|
|
const n2n_mac_t srcMac, |
|
|
uint8_t from_supernode, |
|
|
uint8_t from_supernode, |
|
|
const uint8_t * pktbuf, |
|
|
const uint8_t * pktbuf, |
|
|
size_t pktsize) |
|
|
size_t pktsize) { |
|
|
{ |
|
|
|
|
|
struct peer_info *scan, *tmp; |
|
|
struct peer_info *scan, *tmp; |
|
|
macstr_t mac_buf; |
|
|
macstr_t mac_buf; |
|
|
n2n_sock_str_t sockbuf; |
|
|
n2n_sock_str_t sockbuf; |
|
@ -196,17 +187,14 @@ static int try_broadcast(n2n_sn_t * sss, |
|
|
|
|
|
|
|
|
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 supernode [%s] %s failed %s", |
|
|
traceEvent(TRACE_WARNING, "multicast %lu to supernode [%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 { |
|
|
else |
|
|
|
|
|
{ |
|
|
|
|
|
++(sss->stats.broadcast); |
|
|
++(sss->stats.broadcast); |
|
|
traceEvent(TRACE_DEBUG, "multicast %lu to supernode [%s] %s", |
|
|
traceEvent(TRACE_DEBUG, "multicast %lu to supernode [%s] %s", |
|
|
pktsize, |
|
|
pktsize, |
|
@ -258,6 +246,7 @@ int comm_init(struct sn_community *comm, char *cmn) { |
|
|
|
|
|
|
|
|
/** Initialise the supernode structure */ |
|
|
/** Initialise the supernode structure */ |
|
|
int sn_init(n2n_sn_t *sss) { |
|
|
int sn_init(n2n_sn_t *sss) { |
|
|
|
|
|
|
|
|
int i; |
|
|
int i; |
|
|
size_t idx; |
|
|
size_t idx; |
|
|
|
|
|
|
|
@ -301,8 +290,9 @@ int sn_init(n2n_sn_t *sss) { |
|
|
/* Random auth token */ |
|
|
/* Random auth token */ |
|
|
sss->auth.scheme = n2n_auth_simple_id; |
|
|
sss->auth.scheme = n2n_auth_simple_id; |
|
|
|
|
|
|
|
|
for (idx = 0; idx < N2N_AUTH_TOKEN_SIZE; ++idx) |
|
|
for(idx = 0; idx < N2N_AUTH_TOKEN_SIZE; ++idx) { |
|
|
sss->auth.token[idx] = n2n_rand() % 0xff; |
|
|
sss->auth.token[idx] = n2n_rand() % 0xff; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
sss->auth.toksize = sizeof(sss->auth.token); |
|
|
sss->auth.toksize = sizeof(sss->auth.token); |
|
|
|
|
|
|
|
@ -318,28 +308,26 @@ int sn_init(n2n_sn_t *sss) { |
|
|
|
|
|
|
|
|
/** Deinitialise the supernode structure and deallocate any memory owned by
|
|
|
/** Deinitialise the supernode structure and deallocate any memory owned by
|
|
|
* it. */ |
|
|
* it. */ |
|
|
void sn_term(n2n_sn_t *sss) |
|
|
void sn_term (n2n_sn_t *sss) { |
|
|
{ |
|
|
|
|
|
struct sn_community *community, *tmp; |
|
|
struct sn_community *community, *tmp; |
|
|
struct sn_community_regular_expression *re, *tmp_re; |
|
|
struct sn_community_regular_expression *re, *tmp_re; |
|
|
|
|
|
|
|
|
if (sss->sock >= 0) |
|
|
if(sss->sock >= 0) { |
|
|
{ |
|
|
|
|
|
closesocket(sss->sock); |
|
|
closesocket(sss->sock); |
|
|
} |
|
|
} |
|
|
sss->sock = -1; |
|
|
sss->sock = -1; |
|
|
|
|
|
|
|
|
if (sss->mgmt_sock >= 0) |
|
|
if(sss->mgmt_sock >= 0) { |
|
|
{ |
|
|
|
|
|
closesocket(sss->mgmt_sock); |
|
|
closesocket(sss->mgmt_sock); |
|
|
} |
|
|
} |
|
|
sss->mgmt_sock = -1; |
|
|
sss->mgmt_sock = -1; |
|
|
|
|
|
|
|
|
HASH_ITER(hh, sss->communities, community, tmp) |
|
|
HASH_ITER(hh, sss->communities, community, tmp) { |
|
|
{ |
|
|
|
|
|
clear_peer_list(&community->edges); |
|
|
clear_peer_list(&community->edges); |
|
|
if (NULL != community->header_encryption_ctx) |
|
|
if(NULL != community->header_encryption_ctx) { |
|
|
free(community->header_encryption_ctx); |
|
|
free(community->header_encryption_ctx); |
|
|
|
|
|
} |
|
|
HASH_DEL(sss->communities, community); |
|
|
HASH_DEL(sss->communities, community); |
|
|
free(community); |
|
|
free(community); |
|
|
} |
|
|
} |
|
@ -362,8 +350,8 @@ void sn_term(n2n_sn_t *sss) |
|
|
* If the supernode has been put into a pre-shutdown phase then this lifetime |
|
|
* If the supernode has been put into a pre-shutdown phase then this lifetime |
|
|
* should not allow registrations to continue beyond the shutdown point. |
|
|
* should not allow registrations to continue beyond the shutdown point. |
|
|
*/ |
|
|
*/ |
|
|
static uint16_t reg_lifetime(n2n_sn_t *sss) |
|
|
static uint16_t reg_lifetime (n2n_sn_t *sss) { |
|
|
{ |
|
|
|
|
|
/* NOTE: UDP firewalls usually have a 30 seconds timeout */ |
|
|
/* NOTE: UDP firewalls usually have a 30 seconds timeout */ |
|
|
return 15; |
|
|
return 15; |
|
|
} |
|
|
} |
|
@ -373,6 +361,7 @@ static uint16_t reg_lifetime(n2n_sn_t *sss) |
|
|
* with the one received from the packet. |
|
|
* with the one received from the packet. |
|
|
*/ |
|
|
*/ |
|
|
static int auth_edge (const n2n_auth_t *auth1, const n2n_auth_t *auth2) { |
|
|
static int auth_edge (const n2n_auth_t *auth1, const n2n_auth_t *auth2) { |
|
|
|
|
|
|
|
|
/* 0 = success (tokens are equal). */ |
|
|
/* 0 = success (tokens are equal). */ |
|
|
return (memcmp(auth1, auth2, sizeof(n2n_auth_t))); |
|
|
return (memcmp(auth1, auth2, sizeof(n2n_auth_t))); |
|
|
} |
|
|
} |
|
@ -385,6 +374,7 @@ static int update_edge(n2n_sn_t *sss, |
|
|
const n2n_sock_t *sender_sock, |
|
|
const n2n_sock_t *sender_sock, |
|
|
int skip_add, |
|
|
int skip_add, |
|
|
time_t now) { |
|
|
time_t now) { |
|
|
|
|
|
|
|
|
macstr_t mac_buf; |
|
|
macstr_t mac_buf; |
|
|
n2n_sock_str_t sockbuf; |
|
|
n2n_sock_str_t sockbuf; |
|
|
struct peer_info *scan, *iter, *tmp; |
|
|
struct peer_info *scan, *iter, *tmp; |
|
@ -413,9 +403,7 @@ static int update_edge(n2n_sn_t *sss, |
|
|
if(NULL == scan) { |
|
|
if(NULL == scan) { |
|
|
/* Not known */ |
|
|
/* Not known */ |
|
|
if(skip_add == SN_ADD) { |
|
|
if(skip_add == SN_ADD) { |
|
|
scan = (struct peer_info *) calloc(1, |
|
|
scan = (struct peer_info *) calloc(1, sizeof(struct peer_info)); /* deallocated in purge_expired_registrations */ |
|
|
sizeof(struct peer_info)); /* deallocated in purge_expired_registrations */ |
|
|
|
|
|
|
|
|
|
|
|
memcpy(&(scan->mac_addr), reg->edgeMac, sizeof(n2n_mac_t)); |
|
|
memcpy(&(scan->mac_addr), reg->edgeMac, sizeof(n2n_mac_t)); |
|
|
scan->dev_addr.net_addr = reg->dev_addr.net_addr; |
|
|
scan->dev_addr.net_addr = reg->dev_addr.net_addr; |
|
|
scan->dev_addr.net_bitlen = reg->dev_addr.net_bitlen; |
|
|
scan->dev_addr.net_bitlen = reg->dev_addr.net_bitlen; |
|
@ -431,7 +419,6 @@ static int update_edge(n2n_sn_t *sss, |
|
|
macaddr_str(mac_buf, reg->edgeMac), |
|
|
macaddr_str(mac_buf, reg->edgeMac), |
|
|
sock_to_cstr(sockbuf, sender_sock)); |
|
|
sock_to_cstr(sockbuf, sender_sock)); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
ret = update_edge_new_sn; |
|
|
ret = update_edge_new_sn; |
|
|
} else { |
|
|
} else { |
|
|
/* Known */ |
|
|
/* Known */ |
|
@ -449,7 +436,6 @@ static int update_edge(n2n_sn_t *sss, |
|
|
|
|
|
|
|
|
ret = update_edge_auth_fail; |
|
|
ret = update_edge_auth_fail; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
} else { |
|
|
} else { |
|
|
memcpy(&(scan->last_cookie), reg->cookie, sizeof(N2N_COOKIE_SIZE)); |
|
|
memcpy(&(scan->last_cookie), reg->cookie, sizeof(N2N_COOKIE_SIZE)); |
|
|
|
|
|
|
|
@ -470,8 +456,10 @@ static int update_edge(n2n_sn_t *sss, |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static signed int peer_tap_ip_sort (struct peer_info *a, struct peer_info *b) { |
|
|
static signed int peer_tap_ip_sort (struct peer_info *a, struct peer_info *b) { |
|
|
|
|
|
|
|
|
uint32_t a_host_id = a->dev_addr.net_addr & (~bitlen2mask(a->dev_addr.net_bitlen)); |
|
|
uint32_t a_host_id = a->dev_addr.net_addr & (~bitlen2mask(a->dev_addr.net_bitlen)); |
|
|
uint32_t b_host_id = b->dev_addr.net_addr & (~bitlen2mask(b->dev_addr.net_bitlen)); |
|
|
uint32_t b_host_id = b->dev_addr.net_addr & (~bitlen2mask(b->dev_addr.net_bitlen)); |
|
|
|
|
|
|
|
|
return ((signed int)a_host_id - (signed int)b_host_id); |
|
|
return ((signed int)a_host_id - (signed int)b_host_id); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
@ -479,6 +467,7 @@ static signed int peer_tap_ip_sort(struct peer_info *a, struct peer_info *b) { |
|
|
/** The IP address assigned to the edge by the auto ip address function of sn. */ |
|
|
/** The IP address assigned to the edge by the auto ip address function of sn. */ |
|
|
static int assign_one_ip_addr (struct sn_community *comm, |
|
|
static int assign_one_ip_addr (struct sn_community *comm, |
|
|
n2n_ip_subnet_t *ipaddr) { |
|
|
n2n_ip_subnet_t *ipaddr) { |
|
|
|
|
|
|
|
|
struct peer_info *peer, *tmpPeer; |
|
|
struct peer_info *peer, *tmpPeer; |
|
|
uint32_t net_id, mask, max_host, host_id = 1; |
|
|
uint32_t net_id, mask, max_host, host_id = 1; |
|
|
dec_ip_bit_str_t ip_bit_str = {'\0'}; |
|
|
dec_ip_bit_str_t ip_bit_str = {'\0'}; |
|
@ -508,6 +497,7 @@ static int assign_one_ip_addr(struct sn_community *comm, |
|
|
ipaddr->net_bitlen = comm->auto_ip_net.net_bitlen; |
|
|
ipaddr->net_bitlen = comm->auto_ip_net.net_bitlen; |
|
|
|
|
|
|
|
|
traceEvent(TRACE_INFO, "Assign IP %s to tap adapter of edge.", ip_subnet_to_str(ip_bit_str, ipaddr)); |
|
|
traceEvent(TRACE_INFO, "Assign IP %s to tap adapter of edge.", ip_subnet_to_str(ip_bit_str, ipaddr)); |
|
|
|
|
|
|
|
|
return 0; |
|
|
return 0; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
@ -522,8 +512,12 @@ int subnet_available(n2n_sn_t *sss, |
|
|
int success = 1; |
|
|
int success = 1; |
|
|
|
|
|
|
|
|
HASH_ITER(hh, sss->communities, cmn, tmpCmn) { |
|
|
HASH_ITER(hh, sss->communities, cmn, tmpCmn) { |
|
|
if (cmn == comm) continue; |
|
|
if(cmn == comm) { |
|
|
if(cmn->is_federation == IS_FEDERATION) continue; |
|
|
continue; |
|
|
|
|
|
} |
|
|
|
|
|
if(cmn->is_federation == IS_FEDERATION) { |
|
|
|
|
|
continue; |
|
|
|
|
|
} |
|
|
if((net_id <= (cmn->auto_ip_net.net_addr + ~bitlen2mask(cmn->auto_ip_net.net_bitlen))) |
|
|
if((net_id <= (cmn->auto_ip_net.net_addr + ~bitlen2mask(cmn->auto_ip_net.net_bitlen))) |
|
|
&&(net_id + ~mask >= cmn->auto_ip_net.net_addr)) { |
|
|
&&(net_id + ~mask >= cmn->auto_ip_net.net_addr)) { |
|
|
success = 0; |
|
|
success = 0; |
|
@ -558,13 +552,17 @@ int assign_one_ip_subnet(n2n_sn_t *sss, |
|
|
net_increment = (~mask+1); |
|
|
net_increment = (~mask+1); |
|
|
for(net_id_i = net_id; net_id_i >= sss->min_auto_ip_net.net_addr; net_id_i -= net_increment) { |
|
|
for(net_id_i = net_id; net_id_i >= sss->min_auto_ip_net.net_addr; net_id_i -= net_increment) { |
|
|
success = subnet_available(sss, comm, net_id_i, mask); |
|
|
success = subnet_available(sss, comm, net_id_i, mask); |
|
|
if(success) break; |
|
|
if(success) { |
|
|
|
|
|
break; |
|
|
|
|
|
} |
|
|
} |
|
|
} |
|
|
// ... then upwards
|
|
|
// ... then upwards
|
|
|
if(!success) { |
|
|
if(!success) { |
|
|
for(net_id_i = net_id + net_increment; net_id_i <= sss->max_auto_ip_net.net_addr; net_id_i += net_increment) { |
|
|
for(net_id_i = net_id + net_increment; net_id_i <= sss->max_auto_ip_net.net_addr; net_id_i += net_increment) { |
|
|
success = subnet_available(sss, comm, net_id_i, mask); |
|
|
success = subnet_available(sss, comm, net_id_i, mask); |
|
|
if(success) break; |
|
|
if(success) { |
|
|
|
|
|
break; |
|
|
|
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
@ -613,19 +611,23 @@ static int find_edge_time_stamp_and_verify (struct peer_info * edges, |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
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) { |
|
|
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; |
|
|
time_t time; |
|
|
struct peer_info *peer, *tmp; |
|
|
struct peer_info *peer, *tmp; |
|
|
|
|
|
|
|
|
if((now - (*p_last_re_reg_and_purge)) < RE_REG_AND_PURGE_FREQUENCY ) return 0; |
|
|
if((now - (*p_last_re_reg_and_purge)) < RE_REG_AND_PURGE_FREQUENCY) { |
|
|
|
|
|
return 0; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
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 <= LAST_SEEN_SN_ACTIVE) continue; |
|
|
if(time <= LAST_SEEN_SN_ACTIVE) { |
|
|
|
|
|
continue; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
if((time < LAST_SEEN_SN_INACTIVE) |
|
|
if((time < LAST_SEEN_SN_INACTIVE) |
|
|
|| (peer->purgeable == SN_UNPURGEABLE) |
|
|
|| (peer->purgeable == SN_UNPURGEABLE)) { |
|
|
) { |
|
|
|
|
|
/* re-regitser (send REGISTER_SUPER) */ |
|
|
/* re-regitser (send REGISTER_SUPER) */ |
|
|
uint8_t pktbuf[N2N_PKT_BUF_SIZE] = {0}; |
|
|
uint8_t pktbuf[N2N_PKT_BUF_SIZE] = {0}; |
|
|
size_t idx; |
|
|
size_t idx; |
|
@ -643,8 +645,9 @@ static int re_register_and_purge_supernodes(n2n_sn_t *sss, struct sn_community * |
|
|
cmn.flags = N2N_FLAGS_FROM_SUPERNODE; |
|
|
cmn.flags = N2N_FLAGS_FROM_SUPERNODE; |
|
|
memcpy(cmn.community, comm->community, N2N_COMMUNITY_SIZE); |
|
|
memcpy(cmn.community, comm->community, N2N_COMMUNITY_SIZE); |
|
|
|
|
|
|
|
|
for (idx = 0; idx < N2N_COOKIE_SIZE; ++idx) |
|
|
for(idx = 0; idx < N2N_COOKIE_SIZE; ++idx) { |
|
|
cookie[idx] = n2n_rand() % 0xff; |
|
|
cookie[idx] = n2n_rand() % 0xff; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
memcpy(reg.cookie, cookie, N2N_COOKIE_SIZE); |
|
|
memcpy(reg.cookie, cookie, N2N_COOKIE_SIZE); |
|
|
reg.dev_addr.net_addr = ntohl(peer->dev_addr.net_addr); |
|
|
reg.dev_addr.net_addr = ntohl(peer->dev_addr.net_addr); |
|
@ -666,7 +669,9 @@ 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 >= LAST_SEEN_SN_INACTIVE) purge_expired_registrations(&(comm->edges), &time, LAST_SEEN_SN_INACTIVE);/* 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*/ |
|
|
|
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
@ -677,12 +682,14 @@ static int re_register_and_purge_supernodes(n2n_sn_t *sss, struct sn_community * |
|
|
|
|
|
|
|
|
static int purge_expired_communities (n2n_sn_t *sss, |
|
|
static int purge_expired_communities (n2n_sn_t *sss, |
|
|
time_t* p_last_purge, |
|
|
time_t* p_last_purge, |
|
|
time_t now) |
|
|
time_t now) { |
|
|
{ |
|
|
|
|
|
struct sn_community *comm, *tmp; |
|
|
struct sn_community *comm, *tmp; |
|
|
size_t num_reg = 0; |
|
|
size_t num_reg = 0; |
|
|
|
|
|
|
|
|
if ((now - (*p_last_purge)) < PURGE_REGISTRATION_FREQUENCY) return 0; |
|
|
if((now - (*p_last_purge)) < PURGE_REGISTRATION_FREQUENCY) { |
|
|
|
|
|
return 0; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
traceEvent(TRACE_DEBUG, "Purging old communities and edges"); |
|
|
traceEvent(TRACE_DEBUG, "Purging old communities and edges"); |
|
|
|
|
|
|
|
@ -690,9 +697,10 @@ static int purge_expired_communities(n2n_sn_t *sss, |
|
|
num_reg += purge_peer_list(&comm->edges, now - REGISTRATION_TIMEOUT); |
|
|
num_reg += purge_peer_list(&comm->edges, now - REGISTRATION_TIMEOUT); |
|
|
if((comm->edges == NULL) && (comm->purgeable == COMMUNITY_PURGEABLE)) { |
|
|
if((comm->edges == NULL) && (comm->purgeable == COMMUNITY_PURGEABLE)) { |
|
|
traceEvent(TRACE_INFO, "Purging idle community %s", comm->community); |
|
|
traceEvent(TRACE_INFO, "Purging idle community %s", comm->community); |
|
|
if (NULL != comm->header_encryption_ctx) |
|
|
if(NULL != comm->header_encryption_ctx) { |
|
|
/* this should not happen as 'purgeable' and thus only communities w/o encrypted header here */ |
|
|
/* this should not happen as 'purgeable' and thus only communities w/o encrypted header here */ |
|
|
free(comm->header_encryption_ctx); |
|
|
free(comm->header_encryption_ctx); |
|
|
|
|
|
} |
|
|
HASH_DEL(sss->communities, comm); |
|
|
HASH_DEL(sss->communities, comm); |
|
|
free(comm); |
|
|
free(comm); |
|
|
} |
|
|
} |
|
@ -706,6 +714,7 @@ static int purge_expired_communities(n2n_sn_t *sss, |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static int number_enc_packets_sort (struct sn_community *a, struct sn_community *b) { |
|
|
static int number_enc_packets_sort (struct sn_community *a, struct sn_community *b) { |
|
|
|
|
|
|
|
|
// comparison function for sorting communities in descending order of their
|
|
|
// comparison function for sorting communities in descending order of their
|
|
|
// number_enc_packets-fields
|
|
|
// number_enc_packets-fields
|
|
|
return (b->number_enc_packets - a->number_enc_packets); |
|
|
return (b->number_enc_packets - a->number_enc_packets); |
|
@ -713,11 +722,13 @@ static int number_enc_packets_sort (struct sn_community *a, struct sn_community |
|
|
|
|
|
|
|
|
static int sort_communities (n2n_sn_t *sss, |
|
|
static int sort_communities (n2n_sn_t *sss, |
|
|
time_t* p_last_sort, |
|
|
time_t* p_last_sort, |
|
|
time_t now) |
|
|
time_t now) { |
|
|
{ |
|
|
|
|
|
struct sn_community *comm, *tmp; |
|
|
struct sn_community *comm, *tmp; |
|
|
|
|
|
|
|
|
if ((now - (*p_last_sort)) < SORT_COMMUNITIES_INTERVAL) return 0; |
|
|
if((now - (*p_last_sort)) < SORT_COMMUNITIES_INTERVAL) { |
|
|
|
|
|
return 0; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
// this routine gets periodically called as defined in SORT_COMMUNITIES_INTERVAL
|
|
|
// this routine gets periodically called as defined in SORT_COMMUNITIES_INTERVAL
|
|
|
// it sorts the communities in descending order of their number_enc_packets-fields...
|
|
|
// it sorts the communities in descending order of their number_enc_packets-fields...
|
|
@ -740,6 +751,7 @@ static int process_mgmt(n2n_sn_t *sss, |
|
|
const uint8_t *mgmt_buf, |
|
|
const uint8_t *mgmt_buf, |
|
|
size_t mgmt_size, |
|
|
size_t mgmt_size, |
|
|
time_t now) { |
|
|
time_t now) { |
|
|
|
|
|
|
|
|
char resbuf[N2N_SN_PKTBUF_SIZE]; |
|
|
char resbuf[N2N_SN_PKTBUF_SIZE]; |
|
|
size_t ressize = 0; |
|
|
size_t ressize = 0; |
|
|
uint32_t num_edges = 0; |
|
|
uint32_t num_edges = 0; |
|
@ -827,8 +839,8 @@ static int process_mgmt(n2n_sn_t *sss, |
|
|
static int sendto_mgmt (n2n_sn_t *sss, |
|
|
static int sendto_mgmt (n2n_sn_t *sss, |
|
|
const struct sockaddr_in *sender_sock, |
|
|
const struct sockaddr_in *sender_sock, |
|
|
const uint8_t *mgmt_buf, |
|
|
const uint8_t *mgmt_buf, |
|
|
size_t mgmt_size) |
|
|
size_t mgmt_size) { |
|
|
{ |
|
|
|
|
|
ssize_t r = sendto(sss->mgmt_sock, mgmt_buf, mgmt_size, 0 /*flags*/, |
|
|
ssize_t r = sendto(sss->mgmt_sock, mgmt_buf, mgmt_size, 0 /*flags*/, |
|
|
(struct sockaddr *)sender_sock, sizeof (struct sockaddr_in)); |
|
|
(struct sockaddr *)sender_sock, sizeof (struct sockaddr_in)); |
|
|
|
|
|
|
|
@ -837,6 +849,7 @@ static int sendto_mgmt(n2n_sn_t *sss, |
|
|
traceEvent (TRACE_ERROR, "sendto_mgmt : sendto failed. %s", strerror (errno)); |
|
|
traceEvent (TRACE_ERROR, "sendto_mgmt : sendto failed. %s", strerror (errno)); |
|
|
return -1; |
|
|
return -1; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
return 0; |
|
|
return 0; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
@ -847,8 +860,8 @@ static int process_udp(n2n_sn_t * sss, |
|
|
const struct sockaddr_in * sender_sock, |
|
|
const struct sockaddr_in * sender_sock, |
|
|
uint8_t * udp_buf, |
|
|
uint8_t * udp_buf, |
|
|
size_t udp_size, |
|
|
size_t udp_size, |
|
|
time_t now) |
|
|
time_t now) { |
|
|
{ |
|
|
|
|
|
n2n_common_t cmn; /* common fields in the packet header */ |
|
|
n2n_common_t cmn; /* common fields in the packet header */ |
|
|
size_t rem; |
|
|
size_t rem; |
|
|
size_t idx; |
|
|
size_t idx; |
|
@ -903,8 +916,9 @@ static int process_udp(n2n_sn_t * sss, |
|
|
uint32_t ret = 0; |
|
|
uint32_t ret = 0; |
|
|
HASH_ITER(hh, sss->communities, comm, tmp) { |
|
|
HASH_ITER(hh, sss->communities, comm, tmp) { |
|
|
/* skip the definitely unencrypted communities */ |
|
|
/* skip the definitely unencrypted communities */ |
|
|
if (comm->header_encryption == HEADER_ENCRYPTION_NONE) |
|
|
if(comm->header_encryption == HEADER_ENCRYPTION_NONE) { |
|
|
continue; |
|
|
continue; |
|
|
|
|
|
} |
|
|
uint16_t checksum = 0; |
|
|
uint16_t checksum = 0; |
|
|
if((ret = packet_header_decrypt(udp_buf, udp_size, comm->community, comm->header_encryption_ctx, |
|
|
if((ret = packet_header_decrypt(udp_buf, udp_size, comm->community, comm->header_encryption_ctx, |
|
|
comm->header_iv_ctx, |
|
|
comm->header_iv_ctx, |
|
@ -964,8 +978,7 @@ static int process_udp(n2n_sn_t * sss, |
|
|
--(cmn.ttl); /* The value copied into all forwarded packets. */ |
|
|
--(cmn.ttl); /* The value copied into all forwarded packets. */ |
|
|
|
|
|
|
|
|
switch(msg_type) { |
|
|
switch(msg_type) { |
|
|
case MSG_TYPE_PACKET: |
|
|
case MSG_TYPE_PACKET: { |
|
|
{ |
|
|
|
|
|
/* PACKET from one edge to another edge via supernode. */ |
|
|
/* PACKET from one edge to another edge via supernode. */ |
|
|
|
|
|
|
|
|
/* pkt will be modified in place and recoded to an output of potentially
|
|
|
/* pkt will be modified in place and recoded to an output of potentially
|
|
@ -1012,7 +1025,6 @@ static int process_udp(n2n_sn_t * sss, |
|
|
memcpy(pkt.sock.addr.v4, &(sender_sock->sin_addr.s_addr), IPV4_SIZE); |
|
|
memcpy(pkt.sock.addr.v4, &(sender_sock->sin_addr.s_addr), IPV4_SIZE); |
|
|
|
|
|
|
|
|
rec_buf = encbuf; |
|
|
rec_buf = encbuf; |
|
|
|
|
|
|
|
|
/* Re-encode the header. */ |
|
|
/* Re-encode the header. */ |
|
|
encode_PACKET(encbuf, &encx, &cmn2, &pkt); |
|
|
encode_PACKET(encbuf, &encx, &cmn2, &pkt); |
|
|
uint16_t oldEncx = encx; |
|
|
uint16_t oldEncx = encx; |
|
@ -1020,11 +1032,11 @@ static int process_udp(n2n_sn_t * sss, |
|
|
/* Copy the original payload unchanged */ |
|
|
/* Copy the original payload unchanged */ |
|
|
encode_buf(encbuf, &encx, (udp_buf + idx), (udp_size - idx)); |
|
|
encode_buf(encbuf, &encx, (udp_buf + idx), (udp_size - idx)); |
|
|
|
|
|
|
|
|
if (comm->header_encryption == HEADER_ENCRYPTION_ENABLED) |
|
|
if(comm->header_encryption == HEADER_ENCRYPTION_ENABLED) { |
|
|
packet_header_encrypt(rec_buf, oldEncx, comm->header_encryption_ctx, |
|
|
packet_header_encrypt(rec_buf, oldEncx, comm->header_encryption_ctx, |
|
|
comm->header_iv_ctx, |
|
|
comm->header_iv_ctx, |
|
|
time_stamp(), pearson_hash_16(rec_buf, encx)); |
|
|
time_stamp(), pearson_hash_16(rec_buf, encx)); |
|
|
|
|
|
} |
|
|
} else { |
|
|
} else { |
|
|
/* Already from a supernode. Nothing to modify, just pass to
|
|
|
/* Already from a supernode. Nothing to modify, just pass to
|
|
|
* destination. */ |
|
|
* destination. */ |
|
@ -1034,21 +1046,23 @@ static int process_udp(n2n_sn_t * sss, |
|
|
rec_buf = udp_buf; |
|
|
rec_buf = udp_buf; |
|
|
encx = udp_size; |
|
|
encx = udp_size; |
|
|
|
|
|
|
|
|
if (comm->header_encryption == HEADER_ENCRYPTION_ENABLED) |
|
|
if(comm->header_encryption == HEADER_ENCRYPTION_ENABLED) { |
|
|
packet_header_encrypt(rec_buf, idx, comm->header_encryption_ctx, |
|
|
packet_header_encrypt(rec_buf, idx, comm->header_encryption_ctx, |
|
|
comm->header_iv_ctx, |
|
|
comm->header_iv_ctx, |
|
|
time_stamp(), pearson_hash_16(rec_buf, udp_size)); |
|
|
time_stamp(), pearson_hash_16(rec_buf, udp_size)); |
|
|
} |
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
/* 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, from_supernode, rec_buf, encx); |
|
|
try_forward(sss, comm, &cmn, pkt.dstMac, from_supernode, rec_buf, encx); |
|
|
else |
|
|
} else { |
|
|
try_broadcast(sss, comm, &cmn, pkt.srcMac, from_supernode, rec_buf, encx); |
|
|
try_broadcast(sss, comm, &cmn, pkt.srcMac, from_supernode, rec_buf, encx); |
|
|
|
|
|
} |
|
|
break; |
|
|
break; |
|
|
} |
|
|
} |
|
|
case MSG_TYPE_REGISTER: |
|
|
|
|
|
{ |
|
|
case MSG_TYPE_REGISTER: { |
|
|
/* Forwarding a REGISTER from one edge to the next */ |
|
|
/* Forwarding a REGISTER from one edge to the next */ |
|
|
|
|
|
|
|
|
n2n_REGISTER_t reg; |
|
|
n2n_REGISTER_t reg; |
|
@ -1104,20 +1118,24 @@ static int process_udp(n2n_sn_t * sss, |
|
|
encx = udp_size; |
|
|
encx = udp_size; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
if (comm->header_encryption == HEADER_ENCRYPTION_ENABLED) |
|
|
if(comm->header_encryption == HEADER_ENCRYPTION_ENABLED) { |
|
|
packet_header_encrypt(rec_buf, encx, comm->header_encryption_ctx, |
|
|
packet_header_encrypt(rec_buf, encx, comm->header_encryption_ctx, |
|
|
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, from_supernode, rec_buf, encx); /* unicast only */ |
|
|
try_forward(sss, comm, &cmn, reg.dstMac, from_supernode, rec_buf, encx); /* unicast only */ |
|
|
} else |
|
|
} else { |
|
|
traceEvent(TRACE_ERROR, "Rx REGISTER with multicast destination"); |
|
|
traceEvent(TRACE_ERROR, "Rx REGISTER with multicast destination"); |
|
|
|
|
|
} |
|
|
break; |
|
|
break; |
|
|
} |
|
|
} |
|
|
case MSG_TYPE_REGISTER_ACK: |
|
|
|
|
|
|
|
|
case MSG_TYPE_REGISTER_ACK: { |
|
|
traceEvent(TRACE_DEBUG, "Rx REGISTER_ACK (NOT IMPLEMENTED) Should not be via supernode"); |
|
|
traceEvent(TRACE_DEBUG, "Rx REGISTER_ACK (NOT IMPLEMENTED) Should not be via supernode"); |
|
|
break; |
|
|
break; |
|
|
case MSG_TYPE_REGISTER_SUPER: |
|
|
} |
|
|
{ |
|
|
|
|
|
|
|
|
case MSG_TYPE_REGISTER_SUPER: { |
|
|
n2n_REGISTER_SUPER_t reg; |
|
|
n2n_REGISTER_SUPER_t reg; |
|
|
n2n_REGISTER_SUPER_ACK_t ack; |
|
|
n2n_REGISTER_SUPER_ACK_t ack; |
|
|
n2n_REGISTER_SUPER_NAK_t nak; |
|
|
n2n_REGISTER_SUPER_NAK_t nak; |
|
@ -1248,11 +1266,9 @@ static int process_udp(n2n_sn_t * sss, |
|
|
continue; |
|
|
continue; |
|
|
} |
|
|
} |
|
|
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) >= (2*LAST_SEEN_SN_ACTIVE)) continue; /* skip long-time-not-seen supernodes.
|
|
|
if((now - peer->last_seen) >= (2*LAST_SEEN_SN_ACTIVE)) continue; /* skip long-time-not-seen supernodes.
|
|
|
* We need to allow for a little extra time because supernodes sometimes exceed |
|
|
* We need to allow for a little extra time because supernodes sometimes exceed |
|
|
* their SN_ACTIVE time before they get re-registred to. */ |
|
|
* their SN_ACTIVE time before they get re-registred to. */ |
|
|
|
|
|
|
|
|
if(((++num)*REG_SUPER_ACK_PAYLOAD_ENTRY_SIZE) > REG_SUPER_ACK_PAYLOAD_SPACE) 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(&(payload->sock), &(peer->sock), sizeof(n2n_sock_t)); |
|
|
memcpy(&(payload->sock), &(peer->sock), sizeof(n2n_sock_t)); |
|
|
memcpy(&(payload->mac), &(peer->mac_addr), sizeof(n2n_mac_t)); |
|
|
memcpy(&(payload->mac), &(peer->mac_addr), sizeof(n2n_mac_t)); |
|
@ -1261,7 +1277,6 @@ static int process_udp(n2n_sn_t * sss, |
|
|
} |
|
|
} |
|
|
ack.num_sn = num; |
|
|
ack.num_sn = num; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
traceEvent(TRACE_DEBUG, "Rx REGISTER_SUPER for %s [%s]", |
|
|
traceEvent(TRACE_DEBUG, "Rx REGISTER_SUPER for %s [%s]", |
|
|
macaddr_str(mac_buf, reg.edgeMac), |
|
|
macaddr_str(mac_buf, reg.edgeMac), |
|
|
sock_to_cstr(sockbuf, &(ack.sock))); |
|
|
sock_to_cstr(sockbuf, &(ack.sock))); |
|
@ -1276,17 +1291,16 @@ static int process_udp(n2n_sn_t * sss, |
|
|
|
|
|
|
|
|
if(ret_value == update_edge_auth_fail) { |
|
|
if(ret_value == update_edge_auth_fail) { |
|
|
cmn2.pc = n2n_register_super_nak; |
|
|
cmn2.pc = n2n_register_super_nak; |
|
|
|
|
|
|
|
|
memcpy(&(nak.cookie), &(reg.cookie), sizeof(n2n_cookie_t)); |
|
|
memcpy(&(nak.cookie), &(reg.cookie), sizeof(n2n_cookie_t)); |
|
|
memcpy(&(nak.srcMac), &(reg.edgeMac), sizeof(n2n_mac_t)); |
|
|
memcpy(&(nak.srcMac), &(reg.edgeMac), sizeof(n2n_mac_t)); |
|
|
|
|
|
|
|
|
encode_REGISTER_SUPER_NAK(ackbuf, &encx, &cmn2, &nak); |
|
|
encode_REGISTER_SUPER_NAK(ackbuf, &encx, &cmn2, &nak); |
|
|
|
|
|
|
|
|
if (comm->header_encryption == HEADER_ENCRYPTION_ENABLED) |
|
|
if(comm->header_encryption == HEADER_ENCRYPTION_ENABLED) { |
|
|
packet_header_encrypt(ackbuf, encx, comm->header_encryption_ctx, |
|
|
packet_header_encrypt(ackbuf, encx, comm->header_encryption_ctx, |
|
|
comm->header_iv_ctx, |
|
|
comm->header_iv_ctx, |
|
|
time_stamp(), pearson_hash_16(ackbuf, encx)); |
|
|
time_stamp(), pearson_hash_16(ackbuf, encx)); |
|
|
|
|
|
} |
|
|
sendto(sss->sock, ackbuf, encx, 0, |
|
|
sendto(sss->sock, ackbuf, encx, 0, |
|
|
(struct sockaddr *)sender_sock, sizeof(struct sockaddr_in)); |
|
|
(struct sockaddr *)sender_sock, sizeof(struct sockaddr_in)); |
|
|
|
|
|
|
|
@ -1305,10 +1319,11 @@ static int process_udp(n2n_sn_t * sss, |
|
|
cmn2.pc = n2n_register_super; |
|
|
cmn2.pc = n2n_register_super; |
|
|
encode_REGISTER_SUPER(ackbuf, &encx, &cmn2, ®); |
|
|
encode_REGISTER_SUPER(ackbuf, &encx, &cmn2, ®); |
|
|
|
|
|
|
|
|
if (comm->header_encryption == HEADER_ENCRYPTION_ENABLED) |
|
|
if(comm->header_encryption == HEADER_ENCRYPTION_ENABLED) { |
|
|
packet_header_encrypt(ackbuf, encx, comm->header_encryption_ctx, |
|
|
packet_header_encrypt(ackbuf, encx, comm->header_encryption_ctx, |
|
|
comm->header_iv_ctx, |
|
|
comm->header_iv_ctx, |
|
|
time_stamp(), pearson_hash_16(ackbuf, encx)); |
|
|
time_stamp(), pearson_hash_16(ackbuf, encx)); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
try_broadcast(sss, NULL, &cmn, reg.edgeMac, from_supernode, ackbuf, encx); |
|
|
try_broadcast(sss, NULL, &cmn, reg.edgeMac, from_supernode, ackbuf, encx); |
|
|
|
|
|
|
|
@ -1317,10 +1332,11 @@ static int process_udp(n2n_sn_t * sss, |
|
|
|
|
|
|
|
|
encode_REGISTER_SUPER_ACK(ackbuf, &encx, &cmn2, &ack, tmpbuf); |
|
|
encode_REGISTER_SUPER_ACK(ackbuf, &encx, &cmn2, &ack, tmpbuf); |
|
|
|
|
|
|
|
|
if (comm->header_encryption == HEADER_ENCRYPTION_ENABLED) |
|
|
if(comm->header_encryption == HEADER_ENCRYPTION_ENABLED) { |
|
|
packet_header_encrypt(ackbuf, encx, comm->header_encryption_ctx, |
|
|
packet_header_encrypt(ackbuf, encx, comm->header_encryption_ctx, |
|
|
comm->header_iv_ctx, |
|
|
comm->header_iv_ctx, |
|
|
time_stamp(), pearson_hash_16(ackbuf, encx)); |
|
|
time_stamp(), pearson_hash_16(ackbuf, encx)); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
sendto(sss->sock, ackbuf, encx, 0, |
|
|
sendto(sss->sock, ackbuf, encx, 0, |
|
|
(struct sockaddr *)sender_sock, sizeof(struct sockaddr_in)); |
|
|
(struct sockaddr *)sender_sock, sizeof(struct sockaddr_in)); |
|
@ -1337,6 +1353,7 @@ static int process_udp(n2n_sn_t * sss, |
|
|
} |
|
|
} |
|
|
break; |
|
|
break; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
case MSG_TYPE_UNREGISTER_SUPER: { |
|
|
case MSG_TYPE_UNREGISTER_SUPER: { |
|
|
n2n_UNREGISTER_SUPER_t unreg; |
|
|
n2n_UNREGISTER_SUPER_t unreg; |
|
|
struct peer_info *peer; |
|
|
struct peer_info *peer; |
|
@ -1376,6 +1393,7 @@ static int process_udp(n2n_sn_t * sss, |
|
|
|
|
|
|
|
|
break; |
|
|
break; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
case MSG_TYPE_REGISTER_SUPER_ACK: { |
|
|
case MSG_TYPE_REGISTER_SUPER_ACK: { |
|
|
n2n_REGISTER_SUPER_ACK_t ack; |
|
|
n2n_REGISTER_SUPER_ACK_t ack; |
|
|
size_t encx = 0; |
|
|
size_t encx = 0; |
|
@ -1455,6 +1473,7 @@ static int process_udp(n2n_sn_t * sss, |
|
|
|
|
|
|
|
|
break; |
|
|
break; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
case MSG_TYPE_REGISTER_SUPER_NAK: { |
|
|
case MSG_TYPE_REGISTER_SUPER_NAK: { |
|
|
n2n_REGISTER_SUPER_NAK_t nak; |
|
|
n2n_REGISTER_SUPER_NAK_t nak; |
|
|
size_t encx = 0; |
|
|
size_t encx = 0; |
|
@ -1499,6 +1518,7 @@ static int process_udp(n2n_sn_t * sss, |
|
|
|
|
|
|
|
|
break; |
|
|
break; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
case MSG_TYPE_QUERY_PEER: { |
|
|
case MSG_TYPE_QUERY_PEER: { |
|
|
n2n_QUERY_PEER_t query; |
|
|
n2n_QUERY_PEER_t query; |
|
|
uint8_t encbuf[N2N_SN_PKTBUF_SIZE]; |
|
|
uint8_t encbuf[N2N_SN_PKTBUF_SIZE]; |
|
@ -1566,11 +1586,12 @@ static int process_udp(n2n_sn_t * sss, |
|
|
encode_PEER_INFO(encbuf, &encx, &cmn2, &pi); |
|
|
encode_PEER_INFO(encbuf, &encx, &cmn2, &pi); |
|
|
|
|
|
|
|
|
if(comm) { |
|
|
if(comm) { |
|
|
if(comm->header_encryption == HEADER_ENCRYPTION_ENABLED) |
|
|
if(comm->header_encryption == HEADER_ENCRYPTION_ENABLED) { |
|
|
packet_header_encrypt(encbuf, encx, comm->header_encryption_ctx, |
|
|
packet_header_encrypt(encbuf, encx, comm->header_encryption_ctx, |
|
|
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, |
|
|
sendto(sss->sock, encbuf, encx, 0, |
|
|
(struct sockaddr *)sender_sock, sizeof(struct sockaddr_in)); |
|
|
(struct sockaddr *)sender_sock, sizeof(struct sockaddr_in)); |
|
@ -1597,10 +1618,11 @@ static int process_udp(n2n_sn_t * sss, |
|
|
|
|
|
|
|
|
encode_PEER_INFO(encbuf, &encx, &cmn2, &pi); |
|
|
encode_PEER_INFO(encbuf, &encx, &cmn2, &pi); |
|
|
|
|
|
|
|
|
if(comm->header_encryption == HEADER_ENCRYPTION_ENABLED) |
|
|
if(comm->header_encryption == HEADER_ENCRYPTION_ENABLED) { |
|
|
packet_header_encrypt(encbuf, encx, comm->header_encryption_ctx, |
|
|
packet_header_encrypt(encbuf, encx, comm->header_encryption_ctx, |
|
|
comm->header_iv_ctx, |
|
|
comm->header_iv_ctx, |
|
|
time_stamp(), pearson_hash_16(encbuf, encx)); |
|
|
time_stamp(), pearson_hash_16(encbuf, encx)); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
if(cmn.flags & N2N_FLAGS_SOCKET) { |
|
|
if(cmn.flags & N2N_FLAGS_SOCKET) { |
|
|
sendto_sock(sss, &query.sock, encbuf, encx); |
|
|
sendto_sock(sss, &query.sock, encbuf, encx); |
|
@ -1630,10 +1652,11 @@ static int process_udp(n2n_sn_t * sss, |
|
|
|
|
|
|
|
|
encode_QUERY_PEER(encbuf, &encx, &cmn2, &query); |
|
|
encode_QUERY_PEER(encbuf, &encx, &cmn2, &query); |
|
|
|
|
|
|
|
|
if (comm->header_encryption == HEADER_ENCRYPTION_ENABLED) |
|
|
if(comm->header_encryption == HEADER_ENCRYPTION_ENABLED) { |
|
|
packet_header_encrypt(encbuf, encx, comm->header_encryption_ctx, |
|
|
packet_header_encrypt(encbuf, encx, comm->header_encryption_ctx, |
|
|
comm->header_iv_ctx, |
|
|
comm->header_iv_ctx, |
|
|
time_stamp(), pearson_hash_16(encbuf, encx)); |
|
|
time_stamp(), pearson_hash_16(encbuf, encx)); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
try_broadcast(sss, NULL, &cmn, query.srcMac, from_supernode, encbuf, encx); |
|
|
try_broadcast(sss, NULL, &cmn, query.srcMac, from_supernode, encbuf, encx); |
|
|
} |
|
|
} |
|
@ -1642,6 +1665,7 @@ static int process_udp(n2n_sn_t * sss, |
|
|
|
|
|
|
|
|
break; |
|
|
break; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
default: |
|
|
default: |
|
|
/* Not a known message type */ |
|
|
/* Not a known message type */ |
|
|
traceEvent(TRACE_WARNING, "Unable to handle packet type %d: ignored", (signed int)msg_type); |
|
|
traceEvent(TRACE_WARNING, "Unable to handle packet type %d: ignored", (signed int)msg_type); |
|
@ -1652,8 +1676,8 @@ static int process_udp(n2n_sn_t * sss, |
|
|
|
|
|
|
|
|
/** Long lived processing entry point. Split out from main to simply
|
|
|
/** Long lived processing entry point. Split out from main to simply
|
|
|
* daemonisation on some platforms. */ |
|
|
* daemonisation on some platforms. */ |
|
|
int run_sn_loop(n2n_sn_t *sss, int *keep_running) |
|
|
int run_sn_loop (n2n_sn_t *sss, int *keep_running) { |
|
|
{ |
|
|
|
|
|
uint8_t pktbuf[N2N_SN_PKTBUF_SIZE]; |
|
|
uint8_t pktbuf[N2N_SN_PKTBUF_SIZE]; |
|
|
time_t last_purge_edges = 0; |
|
|
time_t last_purge_edges = 0; |
|
|
time_t last_sort_communities = 0; |
|
|
time_t last_sort_communities = 0; |
|
@ -1661,8 +1685,7 @@ int run_sn_loop(n2n_sn_t *sss, int *keep_running) |
|
|
|
|
|
|
|
|
sss->start_time = time(NULL); |
|
|
sss->start_time = time(NULL); |
|
|
|
|
|
|
|
|
while (*keep_running) |
|
|
while(*keep_running) { |
|
|
{ |
|
|
|
|
|
int rc; |
|
|
int rc; |
|
|
ssize_t bread; |
|
|
ssize_t bread; |
|
|
int max_sock; |
|
|
int max_sock; |
|
@ -1682,10 +1705,8 @@ int run_sn_loop(n2n_sn_t *sss, int *keep_running) |
|
|
|
|
|
|
|
|
now = time(NULL); |
|
|
now = time(NULL); |
|
|
|
|
|
|
|
|
if (rc > 0) |
|
|
if(rc > 0) { |
|
|
{ |
|
|
if(FD_ISSET(sss->sock, &socket_mask)) { |
|
|
if (FD_ISSET(sss->sock, &socket_mask)) |
|
|
|
|
|
{ |
|
|
|
|
|
struct sockaddr_in sender_sock; |
|
|
struct sockaddr_in sender_sock; |
|
|
socklen_t i; |
|
|
socklen_t i; |
|
|
|
|
|
|
|
@ -1697,8 +1718,7 @@ int run_sn_loop(n2n_sn_t *sss, int *keep_running) |
|
|
#ifdef WIN32 |
|
|
#ifdef WIN32 |
|
|
&& (WSAGetLastError() != WSAECONNRESET) |
|
|
&& (WSAGetLastError() != WSAECONNRESET) |
|
|
#endif |
|
|
#endif |
|
|
) |
|
|
) { |
|
|
{ |
|
|
|
|
|
/* For UDP bread of zero just means no data (unlike TCP). */ |
|
|
/* For UDP bread of zero just means no data (unlike TCP). */ |
|
|
/* The fd is no good now. Maybe we lost our interface. */ |
|
|
/* The fd is no good now. Maybe we lost our interface. */ |
|
|
traceEvent(TRACE_ERROR, "recvfrom() failed %d errno %d (%s)", bread, errno, strerror(errno)); |
|
|
traceEvent(TRACE_ERROR, "recvfrom() failed %d errno %d (%s)", bread, errno, strerror(errno)); |
|
@ -1710,15 +1730,13 @@ int run_sn_loop(n2n_sn_t *sss, int *keep_running) |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
/* We have a datagram to process */ |
|
|
/* We have a datagram to process */ |
|
|
if (bread > 0) |
|
|
if(bread > 0) { |
|
|
{ |
|
|
|
|
|
/* And the datagram has data (not just a header) */ |
|
|
/* And the datagram has data (not just a header) */ |
|
|
process_udp(sss, &sender_sock, pktbuf, bread, now); |
|
|
process_udp(sss, &sender_sock, pktbuf, bread, now); |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
if (FD_ISSET(sss->mgmt_sock, &socket_mask)) |
|
|
if(FD_ISSET(sss->mgmt_sock, &socket_mask)) { |
|
|
{ |
|
|
|
|
|
struct sockaddr_in sender_sock; |
|
|
struct sockaddr_in sender_sock; |
|
|
size_t i; |
|
|
size_t i; |
|
|
|
|
|
|
|
@ -1726,8 +1744,7 @@ int run_sn_loop(n2n_sn_t *sss, int *keep_running) |
|
|
bread = recvfrom(sss->mgmt_sock, pktbuf, N2N_SN_PKTBUF_SIZE, 0 /*flags*/, |
|
|
bread = recvfrom(sss->mgmt_sock, pktbuf, N2N_SN_PKTBUF_SIZE, 0 /*flags*/, |
|
|
(struct sockaddr *)&sender_sock, (socklen_t *)&i); |
|
|
(struct sockaddr *)&sender_sock, (socklen_t *)&i); |
|
|
|
|
|
|
|
|
if (bread <= 0) |
|
|
if(bread <= 0) { |
|
|
{ |
|
|
|
|
|
traceEvent(TRACE_ERROR, "recvfrom() failed %d errno %d (%s)", bread, errno, strerror(errno)); |
|
|
traceEvent(TRACE_ERROR, "recvfrom() failed %d errno %d (%s)", bread, errno, strerror(errno)); |
|
|
*keep_running = 0; |
|
|
*keep_running = 0; |
|
|
break; |
|
|
break; |
|
@ -1736,9 +1753,7 @@ int run_sn_loop(n2n_sn_t *sss, int *keep_running) |
|
|
/* We have a datagram to process */ |
|
|
/* We have a datagram to process */ |
|
|
process_mgmt(sss, &sender_sock, pktbuf, bread, now); |
|
|
process_mgmt(sss, &sender_sock, pktbuf, bread, now); |
|
|
} |
|
|
} |
|
|
} |
|
|
} else { |
|
|
else |
|
|
|
|
|
{ |
|
|
|
|
|
traceEvent(TRACE_DEBUG, "timeout"); |
|
|
traceEvent(TRACE_DEBUG, "timeout"); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|