Browse Source

Added the ability with kill -HUP to let the supernode display registered peers

Improvd supernode help
master
Luca Deri 6 years ago
parent
commit
dffdb6c6f5
  1. 6
      n2n.c
  2. 3
      packages/etc/n2n/supernode.conf
  3. 499
      sn.c

6
n2n.c

@ -265,10 +265,8 @@ void print_n2n_version() {
struct peer_info * find_peer_by_mac(struct peer_info * list, const n2n_mac_t mac)
{
/* TODO - replace a list with a hashtable */
while(list != NULL)
{
if(0 == memcmp(mac, list->mac_addr, 6))
{
while(list != NULL) {
if(0 == memcmp(mac, list->mac_addr, 6)) {
return list;
}
list = list->next;

3
packages/etc/n2n/supernode.conf

@ -9,3 +9,6 @@
#
# -l=7777
#
# Specify in supernodes.list the list of allowed communities
#
# -c=supernodes.list

499
sn.c

@ -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( &reg, &cmn, udp_buf, &rem, &idx );
decode_REGISTER(&reg, &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, &reg );
encode_REGISTER(encbuf, &encx, &cmn2, &reg);
/* 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( &reg, &cmn, udp_buf, &rem, &idx );
decode_REGISTER_SUPER(&reg, &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;
}

Loading…
Cancel
Save