|
|
@ -56,27 +56,26 @@ struct n2n_allowed_communities { |
|
|
|
|
|
|
|
static struct n2n_allowed_communities *allowed_communities = NULL; |
|
|
|
|
|
|
|
static int try_forward( n2n_sn_t * sss, |
|
|
|
static int try_forward(n2n_sn_t * sss, |
|
|
|
const n2n_common_t * cmn, |
|
|
|
const n2n_mac_t dstMac, |
|
|
|
const uint8_t * pktbuf, |
|
|
|
size_t pktsize ); |
|
|
|
size_t pktsize); |
|
|
|
|
|
|
|
static int try_broadcast( n2n_sn_t * sss, |
|
|
|
static int try_broadcast(n2n_sn_t * sss, |
|
|
|
const n2n_common_t * cmn, |
|
|
|
const n2n_mac_t srcMac, |
|
|
|
const uint8_t * pktbuf, |
|
|
|
size_t pktsize ); |
|
|
|
|
|
|
|
size_t pktsize); |
|
|
|
|
|
|
|
static n2n_sn_t sss_node; |
|
|
|
|
|
|
|
/** Initialise the supernode structure */ |
|
|
|
static int init_sn( n2n_sn_t * sss ) |
|
|
|
{ |
|
|
|
static int init_sn(n2n_sn_t * sss) { |
|
|
|
#ifdef WIN32 |
|
|
|
initWin32(); |
|
|
|
#endif |
|
|
|
memset( sss, 0, sizeof(n2n_sn_t) ); |
|
|
|
memset(sss, 0, sizeof(n2n_sn_t)); |
|
|
|
|
|
|
|
sss->daemon = 1; /* By defult run as a daemon. */ |
|
|
|
sss->lport = N2N_SN_LPORT_DEFAULT; |
|
|
@ -89,21 +88,21 @@ static int init_sn( n2n_sn_t * sss ) |
|
|
|
|
|
|
|
/** Deinitialise the supernode structure and deallocate any memory owned by
|
|
|
|
* it. */ |
|
|
|
static void deinit_sn( n2n_sn_t * sss ) |
|
|
|
static void deinit_sn(n2n_sn_t * sss) |
|
|
|
{ |
|
|
|
if (sss->sock >= 0) |
|
|
|
if(sss->sock >= 0) |
|
|
|
{ |
|
|
|
closesocket(sss->sock); |
|
|
|
} |
|
|
|
sss->sock=-1; |
|
|
|
|
|
|
|
if ( sss->mgmt_sock >= 0 ) |
|
|
|
if(sss->mgmt_sock >= 0) |
|
|
|
{ |
|
|
|
closesocket(sss->mgmt_sock); |
|
|
|
} |
|
|
|
sss->mgmt_sock=-1; |
|
|
|
|
|
|
|
purge_peer_list( &(sss->edges), 0xffffffff ); |
|
|
|
purge_peer_list(&(sss->edges), 0xffffffff); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
@ -112,14 +111,14 @@ static void deinit_sn( n2n_sn_t * sss ) |
|
|
|
* If the supernode has been put into a pre-shutdown phase then this lifetime |
|
|
|
* 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) { |
|
|
|
return 120; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** Update the edge table with the details of the edge which contacted the
|
|
|
|
* supernode. */ |
|
|
|
static int update_edge( n2n_sn_t * sss, |
|
|
|
static int update_edge(n2n_sn_t * sss, |
|
|
|
const n2n_mac_t edgeMac, |
|
|
|
const n2n_community_t community, |
|
|
|
const n2n_sock_t * sender_sock, |
|
|
@ -128,19 +127,18 @@ static int update_edge( n2n_sn_t * sss, |
|
|
|
n2n_sock_str_t sockbuf; |
|
|
|
struct peer_info * scan; |
|
|
|
|
|
|
|
traceEvent( TRACE_DEBUG, "update_edge for %s [%s]", |
|
|
|
macaddr_str( mac_buf, edgeMac ), |
|
|
|
sock_to_cstr( sockbuf, sender_sock ) ); |
|
|
|
traceEvent(TRACE_DEBUG, "update_edge for %s [%s]", |
|
|
|
macaddr_str(mac_buf, edgeMac), |
|
|
|
sock_to_cstr(sockbuf, sender_sock)); |
|
|
|
|
|
|
|
scan = find_peer_by_mac( sss->edges, edgeMac ); |
|
|
|
scan = find_peer_by_mac(sss->edges, edgeMac); |
|
|
|
|
|
|
|
if ( NULL == scan ) |
|
|
|
{ |
|
|
|
if(NULL == scan) { |
|
|
|
/* Not known */ |
|
|
|
|
|
|
|
scan = (struct peer_info*)calloc(1, sizeof(struct peer_info)); /* deallocated in purge_expired_registrations */ |
|
|
|
|
|
|
|
memcpy(scan->community_name, community, sizeof(n2n_community_t) ); |
|
|
|
memcpy(scan->community_name, community, sizeof(n2n_community_t)); |
|
|
|
memcpy(&(scan->mac_addr), edgeMac, sizeof(n2n_mac_t)); |
|
|
|
memcpy(&(scan->sock), sender_sock, sizeof(n2n_sock_t)); |
|
|
|
|
|
|
@ -148,28 +146,26 @@ static int update_edge( n2n_sn_t * sss, |
|
|
|
scan->next = sss->edges; /* first in list */ |
|
|
|
sss->edges = scan; /* head of list points to new scan */ |
|
|
|
|
|
|
|
traceEvent( TRACE_INFO, "update_edge created %s ==> %s", |
|
|
|
macaddr_str( mac_buf, edgeMac ), |
|
|
|
sock_to_cstr( sockbuf, sender_sock ) ); |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
traceEvent(TRACE_INFO, "update_edge created %s ==> %s", |
|
|
|
macaddr_str(mac_buf, edgeMac), |
|
|
|
sock_to_cstr(sockbuf, sender_sock)); |
|
|
|
} else { |
|
|
|
/* Known */ |
|
|
|
if ( (0 != memcmp(community, scan->community_name, sizeof(n2n_community_t))) || |
|
|
|
(0 != sock_equal(sender_sock, &(scan->sock) )) ) |
|
|
|
if((0 != memcmp(community, scan->community_name, sizeof(n2n_community_t))) || |
|
|
|
(0 != sock_equal(sender_sock, &(scan->sock)))) |
|
|
|
{ |
|
|
|
memcpy(scan->community_name, community, sizeof(n2n_community_t) ); |
|
|
|
memcpy(scan->community_name, community, sizeof(n2n_community_t)); |
|
|
|
memcpy(&(scan->sock), sender_sock, sizeof(n2n_sock_t)); |
|
|
|
|
|
|
|
traceEvent( TRACE_INFO, "update_edge updated %s ==> %s", |
|
|
|
macaddr_str( mac_buf, edgeMac ), |
|
|
|
sock_to_cstr( sockbuf, sender_sock ) ); |
|
|
|
traceEvent(TRACE_INFO, "update_edge updated %s ==> %s", |
|
|
|
macaddr_str(mac_buf, edgeMac), |
|
|
|
sock_to_cstr(sockbuf, sender_sock)); |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
traceEvent( TRACE_DEBUG, "update_edge unchanged %s ==> %s", |
|
|
|
macaddr_str( mac_buf, edgeMac ), |
|
|
|
sock_to_cstr( sockbuf, sender_sock ) ); |
|
|
|
traceEvent(TRACE_DEBUG, "update_edge unchanged %s ==> %s", |
|
|
|
macaddr_str(mac_buf, edgeMac), |
|
|
|
sock_to_cstr(sockbuf, sender_sock)); |
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
@ -190,20 +186,20 @@ static ssize_t sendto_sock(n2n_sn_t * sss, |
|
|
|
{ |
|
|
|
n2n_sock_str_t sockbuf; |
|
|
|
|
|
|
|
if ( AF_INET == sock->family ) |
|
|
|
if(AF_INET == sock->family) |
|
|
|
{ |
|
|
|
struct sockaddr_in udpsock; |
|
|
|
|
|
|
|
udpsock.sin_family = AF_INET; |
|
|
|
udpsock.sin_port = htons( sock->port ); |
|
|
|
memcpy( &(udpsock.sin_addr.s_addr), &(sock->addr.v4), IPV4_SIZE ); |
|
|
|
udpsock.sin_port = htons(sock->port); |
|
|
|
memcpy(&(udpsock.sin_addr.s_addr), &(sock->addr.v4), IPV4_SIZE); |
|
|
|
|
|
|
|
traceEvent( TRACE_DEBUG, "sendto_sock %lu to [%s]", |
|
|
|
traceEvent(TRACE_DEBUG, "sendto_sock %lu to [%s]", |
|
|
|
pktsize, |
|
|
|
sock_to_cstr( sockbuf, sock ) ); |
|
|
|
sock_to_cstr(sockbuf, sock)); |
|
|
|
|
|
|
|
return sendto( sss->sock, pktbuf, pktsize, 0, |
|
|
|
(const struct sockaddr *)&udpsock, sizeof(struct sockaddr_in) ); |
|
|
|
return sendto(sss->sock, pktbuf, pktsize, 0, |
|
|
|
(const struct sockaddr *)&udpsock, sizeof(struct sockaddr_in)); |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
@ -218,29 +214,29 @@ static ssize_t sendto_sock(n2n_sn_t * sss, |
|
|
|
/** Try to forward a message to a unicast MAC. If the MAC is unknown then
|
|
|
|
* broadcast to all edges in the destination community. |
|
|
|
*/ |
|
|
|
static int try_forward( n2n_sn_t * sss, |
|
|
|
static int try_forward(n2n_sn_t * sss, |
|
|
|
const n2n_common_t * cmn, |
|
|
|
const n2n_mac_t dstMac, |
|
|
|
const uint8_t * pktbuf, |
|
|
|
size_t pktsize ) |
|
|
|
size_t pktsize) |
|
|
|
{ |
|
|
|
struct peer_info * scan; |
|
|
|
macstr_t mac_buf; |
|
|
|
n2n_sock_str_t sockbuf; |
|
|
|
|
|
|
|
scan = find_peer_by_mac( sss->edges, dstMac ); |
|
|
|
scan = find_peer_by_mac(sss->edges, dstMac); |
|
|
|
|
|
|
|
if ( NULL != scan ) |
|
|
|
if(NULL != scan) |
|
|
|
{ |
|
|
|
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); |
|
|
|
traceEvent(TRACE_DEBUG, "unicast %lu to [%s] %s", |
|
|
|
pktsize, |
|
|
|
sock_to_cstr( sockbuf, &(scan->sock) ), |
|
|
|
sock_to_cstr(sockbuf, &(scan->sock)), |
|
|
|
macaddr_str(mac_buf, scan->mac_addr)); |
|
|
|
} |
|
|
|
else |
|
|
@ -248,14 +244,14 @@ static int try_forward( n2n_sn_t * sss, |
|
|
|
++(sss->stats.errors); |
|
|
|
traceEvent(TRACE_ERROR, "unicast %lu to [%s] %s FAILED (%d: %s)", |
|
|
|
pktsize, |
|
|
|
sock_to_cstr( sockbuf, &(scan->sock) ), |
|
|
|
sock_to_cstr(sockbuf, &(scan->sock)), |
|
|
|
macaddr_str(mac_buf, scan->mac_addr), |
|
|
|
errno, strerror(errno) ); |
|
|
|
errno, strerror(errno)); |
|
|
|
} |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
traceEvent( TRACE_DEBUG, "try_forward unknown MAC" ); |
|
|
|
traceEvent(TRACE_DEBUG, "try_forward unknown MAC"); |
|
|
|
|
|
|
|
/* Not a known MAC so drop. */ |
|
|
|
} |
|
|
@ -269,23 +265,23 @@ static int try_forward( n2n_sn_t * sss, |
|
|
|
* This will send the exact same datagram to zero or more edges registered to |
|
|
|
* the supernode. |
|
|
|
*/ |
|
|
|
static int try_broadcast( n2n_sn_t * sss, |
|
|
|
static int try_broadcast(n2n_sn_t * sss, |
|
|
|
const n2n_common_t * cmn, |
|
|
|
const n2n_mac_t srcMac, |
|
|
|
const uint8_t * pktbuf, |
|
|
|
size_t pktsize ) |
|
|
|
size_t pktsize) |
|
|
|
{ |
|
|
|
struct peer_info * scan; |
|
|
|
macstr_t mac_buf; |
|
|
|
n2n_sock_str_t sockbuf; |
|
|
|
|
|
|
|
traceEvent( TRACE_DEBUG, "try_broadcast" ); |
|
|
|
traceEvent(TRACE_DEBUG, "try_broadcast"); |
|
|
|
|
|
|
|
scan = sss->edges; |
|
|
|
while(scan != NULL) |
|
|
|
{ |
|
|
|
if( 0 == (memcmp(scan->community_name, cmn->community, sizeof(n2n_community_t)) ) |
|
|
|
&& (0 != memcmp(srcMac, scan->mac_addr, sizeof(n2n_mac_t)) ) ) |
|
|
|
if(0 == (memcmp(scan->community_name, cmn->community, sizeof(n2n_community_t))) |
|
|
|
&& (0 != memcmp(srcMac, scan->mac_addr, sizeof(n2n_mac_t)))) |
|
|
|
/* REVISIT: exclude if the destination socket is where the packet came from. */ |
|
|
|
{ |
|
|
|
int data_sent_len; |
|
|
@ -297,7 +293,7 @@ static int try_broadcast( n2n_sn_t * sss, |
|
|
|
++(sss->stats.errors); |
|
|
|
traceEvent(TRACE_WARNING, "multicast %lu to [%s] %s failed %s", |
|
|
|
pktsize, |
|
|
|
sock_to_cstr( sockbuf, &(scan->sock) ), |
|
|
|
sock_to_cstr(sockbuf, &(scan->sock)), |
|
|
|
macaddr_str(mac_buf, scan->mac_addr), |
|
|
|
strerror(errno)); |
|
|
|
} |
|
|
@ -306,7 +302,7 @@ static int try_broadcast( n2n_sn_t * sss, |
|
|
|
++(sss->stats.broadcast); |
|
|
|
traceEvent(TRACE_DEBUG, "multicast %lu to [%s] %s", |
|
|
|
pktsize, |
|
|
|
sock_to_cstr( sockbuf, &(scan->sock) ), |
|
|
|
sock_to_cstr(sockbuf, &(scan->sock)), |
|
|
|
macaddr_str(mac_buf, scan->mac_addr)); |
|
|
|
} |
|
|
|
} |
|
|
@ -318,7 +314,7 @@ static int try_broadcast( n2n_sn_t * sss, |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static int process_mgmt( n2n_sn_t * sss, |
|
|
|
static int process_mgmt(n2n_sn_t * sss, |
|
|
|
const struct sockaddr_in * sender_sock, |
|
|
|
const uint8_t * mgmt_buf, |
|
|
|
size_t mgmt_size, |
|
|
@ -328,54 +324,54 @@ static int process_mgmt( n2n_sn_t * sss, |
|
|
|
size_t ressize=0; |
|
|
|
ssize_t r; |
|
|
|
|
|
|
|
traceEvent( TRACE_DEBUG, "process_mgmt" ); |
|
|
|
traceEvent(TRACE_DEBUG, "process_mgmt"); |
|
|
|
|
|
|
|
ressize += snprintf( resbuf+ressize, N2N_SN_PKTBUF_SIZE-ressize, |
|
|
|
"----------------\n" ); |
|
|
|
ressize += snprintf(resbuf+ressize, N2N_SN_PKTBUF_SIZE-ressize, |
|
|
|
"----------------\n"); |
|
|
|
|
|
|
|
ressize += snprintf( resbuf+ressize, N2N_SN_PKTBUF_SIZE-ressize, |
|
|
|
"uptime %lu\n", (now - sss->start_time) ); |
|
|
|
ressize += snprintf(resbuf+ressize, N2N_SN_PKTBUF_SIZE-ressize, |
|
|
|
"uptime %lu\n", (now - sss->start_time)); |
|
|
|
|
|
|
|
ressize += snprintf( resbuf+ressize, N2N_SN_PKTBUF_SIZE-ressize, |
|
|
|
ressize += snprintf(resbuf+ressize, N2N_SN_PKTBUF_SIZE-ressize, |
|
|
|
"edges %u\n", |
|
|
|
(unsigned int)peer_list_size( sss->edges ) ); |
|
|
|
(unsigned int)peer_list_size(sss->edges)); |
|
|
|
|
|
|
|
ressize += snprintf( resbuf+ressize, N2N_SN_PKTBUF_SIZE-ressize, |
|
|
|
ressize += snprintf(resbuf+ressize, N2N_SN_PKTBUF_SIZE-ressize, |
|
|
|
"errors %u\n", |
|
|
|
(unsigned int)sss->stats.errors ); |
|
|
|
(unsigned int)sss->stats.errors); |
|
|
|
|
|
|
|
ressize += snprintf( resbuf+ressize, N2N_SN_PKTBUF_SIZE-ressize, |
|
|
|
ressize += snprintf(resbuf+ressize, N2N_SN_PKTBUF_SIZE-ressize, |
|
|
|
"reg_sup %u\n", |
|
|
|
(unsigned int)sss->stats.reg_super ); |
|
|
|
(unsigned int)sss->stats.reg_super); |
|
|
|
|
|
|
|
ressize += snprintf( resbuf+ressize, N2N_SN_PKTBUF_SIZE-ressize, |
|
|
|
ressize += snprintf(resbuf+ressize, N2N_SN_PKTBUF_SIZE-ressize, |
|
|
|
"reg_nak %u\n", |
|
|
|
(unsigned int)sss->stats.reg_super_nak ); |
|
|
|
(unsigned int)sss->stats.reg_super_nak); |
|
|
|
|
|
|
|
ressize += snprintf( resbuf+ressize, N2N_SN_PKTBUF_SIZE-ressize, |
|
|
|
ressize += snprintf(resbuf+ressize, N2N_SN_PKTBUF_SIZE-ressize, |
|
|
|
"fwd %u\n", |
|
|
|
(unsigned int) sss->stats.fwd ); |
|
|
|
(unsigned int) sss->stats.fwd); |
|
|
|
|
|
|
|
ressize += snprintf( resbuf+ressize, N2N_SN_PKTBUF_SIZE-ressize, |
|
|
|
ressize += snprintf(resbuf+ressize, N2N_SN_PKTBUF_SIZE-ressize, |
|
|
|
"broadcast %u\n", |
|
|
|
(unsigned int) sss->stats.broadcast ); |
|
|
|
(unsigned int) sss->stats.broadcast); |
|
|
|
|
|
|
|
ressize += snprintf( resbuf+ressize, N2N_SN_PKTBUF_SIZE-ressize, |
|
|
|
ressize += snprintf(resbuf+ressize, N2N_SN_PKTBUF_SIZE-ressize, |
|
|
|
"last fwd %lu sec ago\n", |
|
|
|
(long unsigned int)(now - sss->stats.last_fwd) ); |
|
|
|
(long unsigned int)(now - sss->stats.last_fwd)); |
|
|
|
|
|
|
|
ressize += snprintf( resbuf+ressize, N2N_SN_PKTBUF_SIZE-ressize, |
|
|
|
ressize += snprintf(resbuf+ressize, N2N_SN_PKTBUF_SIZE-ressize, |
|
|
|
"last reg %lu sec ago\n", |
|
|
|
(long unsigned int) (now - sss->stats.last_reg_super) ); |
|
|
|
(long unsigned int) (now - sss->stats.last_reg_super)); |
|
|
|
|
|
|
|
|
|
|
|
r = sendto( sss->mgmt_sock, resbuf, ressize, 0/*flags*/, |
|
|
|
(struct sockaddr *)sender_sock, sizeof(struct sockaddr_in) ); |
|
|
|
r = sendto(sss->mgmt_sock, resbuf, ressize, 0/*flags*/, |
|
|
|
(struct sockaddr *)sender_sock, sizeof(struct sockaddr_in)); |
|
|
|
|
|
|
|
if ( r <= 0 ) |
|
|
|
if(r <= 0) |
|
|
|
{ |
|
|
|
++(sss->stats.errors); |
|
|
|
traceEvent( TRACE_ERROR, "process_mgmt : sendto failed. %s", strerror(errno) ); |
|
|
|
traceEvent(TRACE_ERROR, "process_mgmt : sendto failed. %s", strerror(errno)); |
|
|
|
} |
|
|
|
|
|
|
|
return 0; |
|
|
@ -417,15 +413,28 @@ static int load_allowed_n2n_communities(char *path) { |
|
|
|
free(s); |
|
|
|
|
|
|
|
while((line = fgets(buffer, sizeof(buffer), fd)) != NULL) { |
|
|
|
if((strlen(line) < 2) || line[0] == '#') |
|
|
|
int len = strlen(line); |
|
|
|
|
|
|
|
if((len < 2) || line[0] == '#') |
|
|
|
continue; |
|
|
|
|
|
|
|
len--; |
|
|
|
while(len > 0) { |
|
|
|
if((line[len] == '\n') || (line[len] == '\r')) { |
|
|
|
line[len] = '\0'; |
|
|
|
len--; |
|
|
|
} else |
|
|
|
break; |
|
|
|
} |
|
|
|
|
|
|
|
s = (struct n2n_allowed_communities*)malloc(sizeof(struct n2n_allowed_communities)); |
|
|
|
|
|
|
|
if(s != NULL) { |
|
|
|
strncpy((char*)s->community, line, N2N_COMMUNITY_SIZE); |
|
|
|
HASH_ADD_STR(allowed_communities, community, s); |
|
|
|
num_communities++; |
|
|
|
traceEvent(TRACE_INFO, "Added allowed community '%s' [total: %u]", |
|
|
|
(char*)s->community, num_communities); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
@ -440,7 +449,7 @@ static int load_allowed_n2n_communities(char *path) { |
|
|
|
/** Examine a datagram and determine what to do with it.
|
|
|
|
* |
|
|
|
*/ |
|
|
|
static int process_udp( n2n_sn_t * sss, |
|
|
|
static int process_udp(n2n_sn_t * sss, |
|
|
|
const struct sockaddr_in * sender_sock, |
|
|
|
const uint8_t * udp_buf, |
|
|
|
size_t udp_size, |
|
|
@ -454,9 +463,11 @@ static int process_udp( n2n_sn_t * sss, |
|
|
|
macstr_t mac_buf; |
|
|
|
macstr_t mac_buf2; |
|
|
|
n2n_sock_str_t sockbuf; |
|
|
|
char buf[32]; |
|
|
|
|
|
|
|
|
|
|
|
traceEvent( TRACE_DEBUG, "process_udp(%lu)", udp_size ); |
|
|
|
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)), |
|
|
|
ntohs(sender_sock->sin_port)); |
|
|
|
|
|
|
|
/* Use decode_common() to determine the kind of packet then process it:
|
|
|
|
* |
|
|
@ -469,25 +480,22 @@ static int process_udp( n2n_sn_t * sss, |
|
|
|
|
|
|
|
rem = udp_size; /* Counts down bytes of packet to protect against buffer overruns. */ |
|
|
|
idx = 0; /* marches through packet header as parts are decoded. */ |
|
|
|
if ( decode_common(&cmn, udp_buf, &rem, &idx) < 0 ) |
|
|
|
{ |
|
|
|
traceEvent( TRACE_ERROR, "Failed to decode common section" ); |
|
|
|
if(decode_common(&cmn, udp_buf, &rem, &idx) < 0) { |
|
|
|
traceEvent(TRACE_ERROR, "Failed to decode common section"); |
|
|
|
return -1; /* failed to decode packet */ |
|
|
|
} |
|
|
|
|
|
|
|
msg_type = cmn.pc; /* packet code */ |
|
|
|
from_supernode= cmn.flags & N2N_FLAGS_FROM_SUPERNODE; |
|
|
|
|
|
|
|
if ( cmn.ttl < 1 ) |
|
|
|
{ |
|
|
|
traceEvent( TRACE_WARNING, "Expired TTL" ); |
|
|
|
if(cmn.ttl < 1) { |
|
|
|
traceEvent(TRACE_WARNING, "Expired TTL"); |
|
|
|
return 0; /* Don't process further */ |
|
|
|
} |
|
|
|
|
|
|
|
--(cmn.ttl); /* The value copied into all forwarded packets. */ |
|
|
|
|
|
|
|
if ( msg_type == MSG_TYPE_PACKET ) |
|
|
|
{ |
|
|
|
if(msg_type == MSG_TYPE_PACKET) { |
|
|
|
/* PACKET from one edge to another edge via supernode. */ |
|
|
|
|
|
|
|
/* pkt will be modified in place and recoded to an output of potentially
|
|
|
@ -501,58 +509,50 @@ static int process_udp( n2n_sn_t * sss, |
|
|
|
|
|
|
|
|
|
|
|
sss->stats.last_fwd=now; |
|
|
|
decode_PACKET( &pkt, &cmn, udp_buf, &rem, &idx ); |
|
|
|
decode_PACKET(&pkt, &cmn, udp_buf, &rem, &idx); |
|
|
|
|
|
|
|
unicast = (0 == is_multi_broadcast(pkt.dstMac) ); |
|
|
|
unicast = (0 == is_multi_broadcast(pkt.dstMac)); |
|
|
|
|
|
|
|
traceEvent( TRACE_DEBUG, "Rx PACKET (%s) %s -> %s %s", |
|
|
|
traceEvent(TRACE_DEBUG, "RX PACKET (%s) %s -> %s %s", |
|
|
|
(unicast?"unicast":"multicast"), |
|
|
|
macaddr_str( mac_buf, pkt.srcMac ), |
|
|
|
macaddr_str( mac_buf2, pkt.dstMac ), |
|
|
|
(from_supernode?"from sn":"local") ); |
|
|
|
macaddr_str(mac_buf, pkt.srcMac), |
|
|
|
macaddr_str(mac_buf2, pkt.dstMac), |
|
|
|
(from_supernode?"from sn":"local")); |
|
|
|
|
|
|
|
if ( !from_supernode ) |
|
|
|
{ |
|
|
|
memcpy( &cmn2, &cmn, sizeof( n2n_common_t ) ); |
|
|
|
if(!from_supernode) { |
|
|
|
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; |
|
|
|
|
|
|
|
pkt.sock.family = AF_INET; |
|
|
|
pkt.sock.port = ntohs(sender_sock->sin_port); |
|
|
|
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; |
|
|
|
|
|
|
|
/* Re-encode the header. */ |
|
|
|
encode_PACKET( encbuf, &encx, &cmn2, &pkt ); |
|
|
|
encode_PACKET(encbuf, &encx, &cmn2, &pkt); |
|
|
|
|
|
|
|
/* Copy the original payload unchanged */ |
|
|
|
encode_buf( encbuf, &encx, (udp_buf + idx), (udp_size - idx ) ); |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
encode_buf(encbuf, &encx, (udp_buf + idx), (udp_size - idx)); |
|
|
|
} else { |
|
|
|
/* Already from a supernode. Nothing to modify, just pass to
|
|
|
|
* destination. */ |
|
|
|
|
|
|
|
traceEvent( TRACE_DEBUG, "Rx PACKET fwd unmodified" ); |
|
|
|
traceEvent(TRACE_DEBUG, "Rx PACKET fwd unmodified"); |
|
|
|
|
|
|
|
rec_buf = udp_buf; |
|
|
|
encx = udp_size; |
|
|
|
} |
|
|
|
|
|
|
|
/* Common section to forward the final product. */ |
|
|
|
if ( unicast ) |
|
|
|
{ |
|
|
|
try_forward( sss, &cmn, pkt.dstMac, rec_buf, encx ); |
|
|
|
} |
|
|
|
if(unicast) |
|
|
|
try_forward(sss, &cmn, pkt.dstMac, rec_buf, encx); |
|
|
|
else |
|
|
|
{ |
|
|
|
try_broadcast( sss, &cmn, pkt.srcMac, rec_buf, encx ); |
|
|
|
} |
|
|
|
try_broadcast(sss, &cmn, pkt.srcMac, rec_buf, encx); |
|
|
|
}/* MSG_TYPE_PACKET */ |
|
|
|
else if ( msg_type == MSG_TYPE_REGISTER ) |
|
|
|
{ |
|
|
|
else if(msg_type == MSG_TYPE_REGISTER) { |
|
|
|
/* Forwarding a REGISTER from one edge to the next */ |
|
|
|
|
|
|
|
n2n_REGISTER_t reg; |
|
|
@ -563,38 +563,34 @@ static int process_udp( n2n_sn_t * sss, |
|
|
|
const uint8_t * rec_buf; /* either udp_buf or encbuf */ |
|
|
|
|
|
|
|
sss->stats.last_fwd=now; |
|
|
|
decode_REGISTER( ®, &cmn, udp_buf, &rem, &idx ); |
|
|
|
decode_REGISTER(®, &cmn, udp_buf, &rem, &idx); |
|
|
|
|
|
|
|
unicast = (0 == is_multi_broadcast(reg.dstMac) ); |
|
|
|
unicast = (0 == is_multi_broadcast(reg.dstMac)); |
|
|
|
|
|
|
|
if ( unicast ) |
|
|
|
{ |
|
|
|
traceEvent( TRACE_DEBUG, "Rx REGISTER %s -> %s %s", |
|
|
|
macaddr_str( mac_buf, reg.srcMac ), |
|
|
|
macaddr_str( mac_buf2, reg.dstMac ), |
|
|
|
((cmn.flags & N2N_FLAGS_FROM_SUPERNODE)?"from sn":"local") ); |
|
|
|
if(unicast) { |
|
|
|
traceEvent(TRACE_DEBUG, "Rx REGISTER %s -> %s %s", |
|
|
|
macaddr_str(mac_buf, reg.srcMac), |
|
|
|
macaddr_str(mac_buf2, reg.dstMac), |
|
|
|
((cmn.flags & N2N_FLAGS_FROM_SUPERNODE)?"from sn":"local")); |
|
|
|
|
|
|
|
if ( 0 != (cmn.flags & N2N_FLAGS_FROM_SUPERNODE) ) |
|
|
|
{ |
|
|
|
memcpy( &cmn2, &cmn, sizeof( n2n_common_t ) ); |
|
|
|
if(0 != (cmn.flags & N2N_FLAGS_FROM_SUPERNODE)) { |
|
|
|
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; |
|
|
|
|
|
|
|
reg.sock.family = AF_INET; |
|
|
|
reg.sock.port = ntohs(sender_sock->sin_port); |
|
|
|
memcpy( reg.sock.addr.v4, &(sender_sock->sin_addr.s_addr), IPV4_SIZE ); |
|
|
|
memcpy(reg.sock.addr.v4, &(sender_sock->sin_addr.s_addr), IPV4_SIZE); |
|
|
|
|
|
|
|
rec_buf = encbuf; |
|
|
|
|
|
|
|
/* Re-encode the header. */ |
|
|
|
encode_REGISTER( encbuf, &encx, &cmn2, ® ); |
|
|
|
encode_REGISTER(encbuf, &encx, &cmn2, ®); |
|
|
|
|
|
|
|
/* Copy the original payload unchanged */ |
|
|
|
encode_buf( encbuf, &encx, (udp_buf + idx), (udp_size - idx ) ); |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
encode_buf(encbuf, &encx, (udp_buf + idx), (udp_size - idx)); |
|
|
|
} else { |
|
|
|
/* Already from a supernode. Nothing to modify, just pass to
|
|
|
|
* destination. */ |
|
|
|
|
|
|
@ -602,20 +598,12 @@ static int process_udp( n2n_sn_t * sss, |
|
|
|
encx = udp_size; |
|
|
|
} |
|
|
|
|
|
|
|
try_forward( sss, &cmn, reg.dstMac, rec_buf, encx ); /* unicast only */ |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
traceEvent( TRACE_ERROR, "Rx REGISTER with multicast destination" ); |
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
else if ( msg_type == MSG_TYPE_REGISTER_ACK ) |
|
|
|
{ |
|
|
|
traceEvent( TRACE_DEBUG, "Rx REGISTER_ACK (NOT IMPLEMENTED) SHould not be via supernode" ); |
|
|
|
} |
|
|
|
else if ( msg_type == MSG_TYPE_REGISTER_SUPER ) |
|
|
|
{ |
|
|
|
try_forward(sss, &cmn, reg.dstMac, rec_buf, encx); /* unicast only */ |
|
|
|
} else |
|
|
|
traceEvent(TRACE_ERROR, "Rx REGISTER with multicast destination"); |
|
|
|
} else if(msg_type == MSG_TYPE_REGISTER_ACK) |
|
|
|
traceEvent(TRACE_DEBUG, "Rx REGISTER_ACK (NOT IMPLEMENTED) SHould not be via supernode"); |
|
|
|
else if(msg_type == MSG_TYPE_REGISTER_SUPER) { |
|
|
|
n2n_REGISTER_SUPER_t reg; |
|
|
|
n2n_REGISTER_SUPER_ACK_t ack; |
|
|
|
n2n_common_t cmn2; |
|
|
@ -625,7 +613,7 @@ static int process_udp( n2n_sn_t * sss, |
|
|
|
/* Edge requesting registration with us. */ |
|
|
|
sss->stats.last_reg_super=now; |
|
|
|
++(sss->stats.reg_super); |
|
|
|
decode_REGISTER_SUPER( ®, &cmn, udp_buf, &rem, &idx ); |
|
|
|
decode_REGISTER_SUPER(®, &cmn, udp_buf, &rem, &idx); |
|
|
|
|
|
|
|
/*
|
|
|
|
Before we move any further, we need to check if the requested |
|
|
@ -637,33 +625,36 @@ static int process_udp( n2n_sn_t * sss, |
|
|
|
cmn2.ttl = N2N_DEFAULT_TTL; |
|
|
|
cmn2.pc = n2n_register_super_ack; |
|
|
|
cmn2.flags = N2N_FLAGS_SOCKET | N2N_FLAGS_FROM_SUPERNODE; |
|
|
|
memcpy( cmn2.community, cmn.community, sizeof(n2n_community_t) ); |
|
|
|
memcpy(cmn2.community, cmn.community, sizeof(n2n_community_t)); |
|
|
|
|
|
|
|
memcpy( &(ack.cookie), &(reg.cookie), sizeof(n2n_cookie_t) ); |
|
|
|
memcpy( ack.edgeMac, reg.edgeMac, sizeof(n2n_mac_t) ); |
|
|
|
ack.lifetime = reg_lifetime( sss ); |
|
|
|
memcpy(&(ack.cookie), &(reg.cookie), sizeof(n2n_cookie_t)); |
|
|
|
memcpy(ack.edgeMac, reg.edgeMac, sizeof(n2n_mac_t)); |
|
|
|
ack.lifetime = reg_lifetime(sss); |
|
|
|
|
|
|
|
ack.sock.family = AF_INET; |
|
|
|
ack.sock.port = ntohs(sender_sock->sin_port); |
|
|
|
memcpy( ack.sock.addr.v4, &(sender_sock->sin_addr.s_addr), IPV4_SIZE ); |
|
|
|
memcpy(ack.sock.addr.v4, &(sender_sock->sin_addr.s_addr), IPV4_SIZE); |
|
|
|
|
|
|
|
ack.num_sn=0; /* No backup */ |
|
|
|
memset( &(ack.sn_bak), 0, sizeof(n2n_sock_t) ); |
|
|
|
memset(&(ack.sn_bak), 0, sizeof(n2n_sock_t)); |
|
|
|
|
|
|
|
traceEvent( TRACE_DEBUG, "Rx REGISTER_SUPER for %s [%s]", |
|
|
|
macaddr_str( mac_buf, reg.edgeMac ), |
|
|
|
sock_to_cstr( sockbuf, &(ack.sock) ) ); |
|
|
|
traceEvent(TRACE_DEBUG, "Rx REGISTER_SUPER for %s [%s]", |
|
|
|
macaddr_str(mac_buf, reg.edgeMac), |
|
|
|
sock_to_cstr(sockbuf, &(ack.sock))); |
|
|
|
|
|
|
|
update_edge( sss, reg.edgeMac, cmn.community, &(ack.sock), now ); |
|
|
|
update_edge(sss, reg.edgeMac, cmn.community, &(ack.sock), now); |
|
|
|
|
|
|
|
encode_REGISTER_SUPER_ACK( ackbuf, &encx, &cmn2, &ack ); |
|
|
|
encode_REGISTER_SUPER_ACK(ackbuf, &encx, &cmn2, &ack); |
|
|
|
|
|
|
|
sendto( sss->sock, ackbuf, encx, 0, |
|
|
|
(struct sockaddr *)sender_sock, sizeof(struct sockaddr_in) ); |
|
|
|
sendto(sss->sock, ackbuf, encx, 0, |
|
|
|
(struct sockaddr *)sender_sock, sizeof(struct sockaddr_in)); |
|
|
|
|
|
|
|
traceEvent( TRACE_DEBUG, "Tx REGISTER_SUPER_ACK for %s [%s]", |
|
|
|
macaddr_str( mac_buf, reg.edgeMac ), |
|
|
|
sock_to_cstr( sockbuf, &(ack.sock) ) ); |
|
|
|
traceEvent(TRACE_DEBUG, "Tx REGISTER_SUPER_ACK for %s [%s]", |
|
|
|
macaddr_str(mac_buf, reg.edgeMac), |
|
|
|
sock_to_cstr(sockbuf, &(ack.sock))); |
|
|
|
} else { |
|
|
|
traceEvent(TRACE_INFO, "Discarded registration: unallowed community '%s'", |
|
|
|
(char*)cmn.community); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
@ -673,8 +664,7 @@ static int process_udp( n2n_sn_t * sss, |
|
|
|
/* *************************************************** */ |
|
|
|
|
|
|
|
/** Help message to print if the command line arguments are not valid. */ |
|
|
|
static void help() |
|
|
|
{ |
|
|
|
static void help() { |
|
|
|
print_n2n_version(); |
|
|
|
|
|
|
|
printf("supernode <config file> (see supernode.conf)\n" |
|
|
@ -682,12 +672,13 @@ static void help() |
|
|
|
); |
|
|
|
printf("supernode "); |
|
|
|
printf("-l <lport> "); |
|
|
|
printf("-c <community file path> "); |
|
|
|
printf("-c <path> "); |
|
|
|
printf("[-f] "); |
|
|
|
printf("[-v] "); |
|
|
|
printf("\n\n"); |
|
|
|
|
|
|
|
printf("-l <lport>\tSet UDP main listen port to <lport>\n"); |
|
|
|
printf("-c <path>\tFile containing the allowed communities.\n"); |
|
|
|
#if defined(N2N_HAVE_DAEMON) |
|
|
|
printf("-f \tRun in foreground.\n"); |
|
|
|
#endif /* #if defined(N2N_HAVE_DAEMON) */ |
|
|
@ -700,49 +691,38 @@ static void help() |
|
|
|
|
|
|
|
/* *************************************************** */ |
|
|
|
|
|
|
|
static int run_loop( n2n_sn_t * sss ); |
|
|
|
static int run_loop(n2n_sn_t * sss); |
|
|
|
|
|
|
|
/* *************************************************** */ |
|
|
|
|
|
|
|
static int setOption(int optkey, char *_optarg, n2n_sn_t *sss) { |
|
|
|
|
|
|
|
//traceEvent(TRACE_NORMAL, "Option %c = %s", optkey, _optarg ? _optarg : "");
|
|
|
|
|
|
|
|
switch(optkey) { |
|
|
|
case 'l': /* local-port */ |
|
|
|
{ |
|
|
|
sss->lport = atoi(_optarg); |
|
|
|
break; |
|
|
|
} |
|
|
|
|
|
|
|
case 'c': /* community file */ |
|
|
|
load_allowed_n2n_communities(optarg); |
|
|
|
break; |
|
|
|
|
|
|
|
case 'f': /* foreground */ |
|
|
|
{ |
|
|
|
sss->daemon = 0; |
|
|
|
break; |
|
|
|
} |
|
|
|
|
|
|
|
case 'h': /* help */ |
|
|
|
{ |
|
|
|
help(); |
|
|
|
break; |
|
|
|
} |
|
|
|
|
|
|
|
case 'v': /* verbose */ |
|
|
|
{ |
|
|
|
++traceLevel; |
|
|
|
traceLevel = 4; /* DEBUG */ |
|
|
|
break; |
|
|
|
} |
|
|
|
|
|
|
|
default: |
|
|
|
{ |
|
|
|
traceEvent(TRACE_WARNING, "Unknown option -%c: Ignored.", (char)optkey); |
|
|
|
return(-1); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
return(0); |
|
|
|
} |
|
|
@ -763,8 +743,7 @@ static const struct option long_options[] = { |
|
|
|
static int loadFromCLI(int argc, char * const argv[], n2n_sn_t *sss) { |
|
|
|
u_char c; |
|
|
|
|
|
|
|
while((c = getopt_long(argc, argv, |
|
|
|
"fl:c:vh", |
|
|
|
while((c = getopt_long(argc, argv, "fl:c:vh", |
|
|
|
long_options, NULL)) != '?') { |
|
|
|
if(c == 255) break; |
|
|
|
setOption(c, optarg, sss); |
|
|
@ -778,7 +757,9 @@ static int loadFromCLI(int argc, char * const argv[], n2n_sn_t *sss) { |
|
|
|
static char *trim(char *s) { |
|
|
|
char *end; |
|
|
|
|
|
|
|
while(isspace(s[0]) || (s[0] == '"') || (s[0] == '\'')) s++; |
|
|
|
while(isspace(s[0]) || (s[0] == '"') || (s[0] == '\'')) |
|
|
|
s++; |
|
|
|
|
|
|
|
if(s[0] == 0) return s; |
|
|
|
|
|
|
|
end = &s[strlen(s) - 1]; |
|
|
@ -856,83 +837,102 @@ static int loadFromFile(const char *path, n2n_sn_t *sss) { |
|
|
|
|
|
|
|
/* *************************************************** */ |
|
|
|
|
|
|
|
static void dump_registrations(int signo) { |
|
|
|
struct peer_info * list = sss_node.edges; |
|
|
|
char buf[32]; |
|
|
|
time_t now = time(NULL); |
|
|
|
u_int num = 0; |
|
|
|
|
|
|
|
traceEvent(TRACE_NORMAL, "===================================="); |
|
|
|
|
|
|
|
while(list != NULL) { |
|
|
|
if(list->sock.family == AF_INET) |
|
|
|
traceEvent(TRACE_NORMAL, "[id: %u][MAC: %s][edge: %u.%u.%u.%u:%u][community: %s][last seen: %u sec ago]", |
|
|
|
++num, macaddr_str(buf, list->mac_addr), |
|
|
|
list->sock.addr.v4[0], list->sock.addr.v4[1], list->sock.addr.v4[2], list->sock.addr.v4[3], |
|
|
|
list->sock.port, |
|
|
|
(char*)list->community_name, |
|
|
|
now-list->last_seen); |
|
|
|
else |
|
|
|
traceEvent(TRACE_NORMAL, "[id: %u][MAC: %s][edge: IPv6:%u][community: %s][last seen: %u sec ago]", |
|
|
|
++num, macaddr_str(buf, list->mac_addr), list->sock.port, |
|
|
|
(char*)list->community_name, |
|
|
|
now-list->last_seen); |
|
|
|
|
|
|
|
list = list->next; |
|
|
|
} |
|
|
|
|
|
|
|
traceEvent(TRACE_NORMAL, "===================================="); |
|
|
|
} |
|
|
|
|
|
|
|
/* *************************************************** */ |
|
|
|
|
|
|
|
/** Main program entry point from kernel. */ |
|
|
|
int main( int argc, char * const argv[] ) |
|
|
|
{ |
|
|
|
int main(int argc, char * const argv[]) { |
|
|
|
int rc; |
|
|
|
n2n_sn_t sss; |
|
|
|
|
|
|
|
if(argc == 1) |
|
|
|
help(); |
|
|
|
|
|
|
|
init_sn(&sss); |
|
|
|
init_sn(&sss_node); |
|
|
|
|
|
|
|
#ifndef WIN32 |
|
|
|
if((argc >= 2) && (argv[1][0] != '-')) |
|
|
|
{ |
|
|
|
rc = loadFromFile(argv[1], &sss); |
|
|
|
if (argc > 2) |
|
|
|
rc = loadFromCLI(argc, argv, &sss); |
|
|
|
if((argc >= 2) && (argv[1][0] != '-')) { |
|
|
|
rc = loadFromFile(argv[1], &sss_node); |
|
|
|
if(argc > 2) |
|
|
|
rc = loadFromCLI(argc, argv, &sss_node); |
|
|
|
} else |
|
|
|
#endif |
|
|
|
rc = loadFromCLI(argc, argv, &sss); |
|
|
|
rc = loadFromCLI(argc, argv, &sss_node); |
|
|
|
|
|
|
|
if (rc < 0) |
|
|
|
if(rc < 0) |
|
|
|
return(-1); |
|
|
|
|
|
|
|
#if defined(N2N_HAVE_DAEMON) |
|
|
|
if (sss.daemon) |
|
|
|
{ |
|
|
|
if(sss_node.daemon) { |
|
|
|
useSyslog=1; /* traceEvent output now goes to syslog. */ |
|
|
|
if ( -1 == daemon( 0, 0 ) ) |
|
|
|
{ |
|
|
|
traceEvent( TRACE_ERROR, "Failed to become daemon." ); |
|
|
|
|
|
|
|
if(-1 == daemon(0, 0)) { |
|
|
|
traceEvent(TRACE_ERROR, "Failed to become daemon."); |
|
|
|
exit(-5); |
|
|
|
} |
|
|
|
} |
|
|
|
#endif /* #if defined(N2N_HAVE_DAEMON) */ |
|
|
|
|
|
|
|
traceEvent( TRACE_DEBUG, "traceLevel is %d", traceLevel); |
|
|
|
traceEvent(TRACE_DEBUG, "traceLevel is %d", traceLevel); |
|
|
|
|
|
|
|
sss.sock = open_socket(sss.lport, 1 /*bind ANY*/ ); |
|
|
|
if ( -1 == sss.sock ) |
|
|
|
{ |
|
|
|
traceEvent( TRACE_ERROR, "Failed to open main socket. %s", strerror(errno) ); |
|
|
|
sss_node.sock = open_socket(sss_node.lport, 1 /*bind ANY*/); |
|
|
|
if(-1 == sss_node.sock) { |
|
|
|
traceEvent(TRACE_ERROR, "Failed to open main socket. %s", strerror(errno)); |
|
|
|
exit(-2); |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
traceEvent( TRACE_NORMAL, "supernode is listening on UDP %u (main)", sss.lport ); |
|
|
|
} else { |
|
|
|
traceEvent(TRACE_NORMAL, "supernode is listening on UDP %u (main)", sss_node.lport); |
|
|
|
} |
|
|
|
|
|
|
|
sss.mgmt_sock = open_socket(N2N_SN_MGMT_PORT, 0 /* bind LOOPBACK */ ); |
|
|
|
if ( -1 == sss.mgmt_sock ) |
|
|
|
{ |
|
|
|
traceEvent( TRACE_ERROR, "Failed to open management socket. %s", strerror(errno) ); |
|
|
|
sss_node.mgmt_sock = open_socket(N2N_SN_MGMT_PORT, 0 /* bind LOOPBACK */); |
|
|
|
if(-1 == sss_node.mgmt_sock) { |
|
|
|
traceEvent(TRACE_ERROR, "Failed to open management socket. %s", strerror(errno)); |
|
|
|
exit(-2); |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
traceEvent( TRACE_NORMAL, "supernode is listening on UDP %u (management)", N2N_SN_MGMT_PORT ); |
|
|
|
} |
|
|
|
} else |
|
|
|
traceEvent(TRACE_NORMAL, "supernode is listening on UDP %u (management)", N2N_SN_MGMT_PORT); |
|
|
|
|
|
|
|
traceEvent(TRACE_NORMAL, "supernode started"); |
|
|
|
|
|
|
|
return run_loop(&sss); |
|
|
|
signal(SIGHUP, dump_registrations); |
|
|
|
|
|
|
|
return run_loop(&sss_node); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** Long lived processing entry point. Split out from main to simply
|
|
|
|
* daemonisation on some platforms. */ |
|
|
|
static int run_loop( n2n_sn_t * sss ) |
|
|
|
{ |
|
|
|
static int run_loop(n2n_sn_t * sss) { |
|
|
|
uint8_t pktbuf[N2N_SN_PKTBUF_SIZE]; |
|
|
|
int keep_running=1; |
|
|
|
|
|
|
|
sss->start_time = time(NULL); |
|
|
|
|
|
|
|
while(keep_running) |
|
|
|
{ |
|
|
|
while(keep_running) { |
|
|
|
int rc; |
|
|
|
ssize_t bread; |
|
|
|
int max_sock; |
|
|
@ -951,63 +951,56 @@ static int run_loop( n2n_sn_t * sss ) |
|
|
|
|
|
|
|
now = time(NULL); |
|
|
|
|
|
|
|
if(rc > 0) |
|
|
|
{ |
|
|
|
if (FD_ISSET(sss->sock, &socket_mask)) |
|
|
|
{ |
|
|
|
if(rc > 0) { |
|
|
|
if(FD_ISSET(sss->sock, &socket_mask)) { |
|
|
|
struct sockaddr_in sender_sock; |
|
|
|
socklen_t i; |
|
|
|
|
|
|
|
i = sizeof(sender_sock); |
|
|
|
bread = recvfrom( sss->sock, pktbuf, N2N_SN_PKTBUF_SIZE, 0/*flags*/, |
|
|
|
bread = recvfrom(sss->sock, pktbuf, N2N_SN_PKTBUF_SIZE, 0/*flags*/, |
|
|
|
(struct sockaddr *)&sender_sock, (socklen_t*)&i); |
|
|
|
|
|
|
|
if ( bread < 0 ) /* For UDP bread of zero just means no data (unlike TCP). */ |
|
|
|
{ |
|
|
|
if(bread < 0) { |
|
|
|
/* For UDP bread of zero just means no data (unlike TCP). */ |
|
|
|
/* 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)); |
|
|
|
keep_running=0; |
|
|
|
break; |
|
|
|
} |
|
|
|
|
|
|
|
/* We have a datagram to process */ |
|
|
|
if ( bread > 0 ) |
|
|
|
{ |
|
|
|
if(bread > 0) { |
|
|
|
/* 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; |
|
|
|
size_t i; |
|
|
|
|
|
|
|
i = sizeof(sender_sock); |
|
|
|
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); |
|
|
|
|
|
|
|
if ( bread <= 0 ) |
|
|
|
{ |
|
|
|
traceEvent( TRACE_ERROR, "recvfrom() failed %d errno %d (%s)", bread, errno, strerror(errno) ); |
|
|
|
if(bread <= 0) { |
|
|
|
traceEvent(TRACE_ERROR, "recvfrom() failed %d errno %d (%s)", bread, errno, strerror(errno)); |
|
|
|
keep_running=0; |
|
|
|
break; |
|
|
|
} |
|
|
|
|
|
|
|
/* We have a datagram to process */ |
|
|
|
process_mgmt( sss, &sender_sock, pktbuf, bread, now ); |
|
|
|
} |
|
|
|
process_mgmt(sss, &sender_sock, pktbuf, bread, now); |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
traceEvent( TRACE_DEBUG, "timeout" ); |
|
|
|
} else { |
|
|
|
traceEvent(TRACE_DEBUG, "timeout"); |
|
|
|
} |
|
|
|
|
|
|
|
purge_expired_registrations( &(sss->edges) ); |
|
|
|
purge_expired_registrations(&(sss->edges)); |
|
|
|
|
|
|
|
} /* while */ |
|
|
|
|
|
|
|
deinit_sn( sss ); |
|
|
|
deinit_sn(sss); |
|
|
|
|
|
|
|
return 0; |
|
|
|
} |
|
|
|