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) struct peer_info * find_peer_by_mac(struct peer_info * list, const n2n_mac_t mac)
{ {
/* TODO - replace a list with a hashtable */ /* TODO - replace a list with a hashtable */
while(list != NULL) while(list != NULL) {
{ if(0 == memcmp(mac, list->mac_addr, 6)) {
if(0 == memcmp(mac, list->mac_addr, 6))
{
return list; return list;
} }
list = list->next; list = list->next;

3
packages/etc/n2n/supernode.conf

@ -9,3 +9,6 @@
# #
# -l=7777 # -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 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_common_t * cmn,
const n2n_mac_t dstMac, const n2n_mac_t dstMac,
const uint8_t * pktbuf, const uint8_t * pktbuf,
size_t pktsize ); size_t pktsize);
static int try_broadcast( n2n_sn_t * sss, static int try_broadcast(n2n_sn_t * sss,
const n2n_common_t * cmn, const n2n_common_t * cmn,
const n2n_mac_t srcMac, const n2n_mac_t srcMac,
const uint8_t * pktbuf, const uint8_t * pktbuf,
size_t pktsize ); size_t pktsize);
static n2n_sn_t sss_node;
/** Initialise the supernode structure */ /** Initialise the supernode structure */
static int init_sn( n2n_sn_t * sss ) static int init_sn(n2n_sn_t * sss) {
{
#ifdef WIN32 #ifdef WIN32
initWin32(); initWin32();
#endif #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->daemon = 1; /* By defult run as a daemon. */
sss->lport = N2N_SN_LPORT_DEFAULT; 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 /** Deinitialise the supernode structure and deallocate any memory owned by
* it. */ * 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); 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;
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 * 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) {
return 120; return 120;
} }
/** Update the edge table with the details of the edge which contacted the /** Update the edge table with the details of the edge which contacted the
* supernode. */ * supernode. */
static int update_edge( n2n_sn_t * sss, static int update_edge(n2n_sn_t * sss,
const n2n_mac_t edgeMac, const n2n_mac_t edgeMac,
const n2n_community_t community, const n2n_community_t community,
const n2n_sock_t * sender_sock, const n2n_sock_t * sender_sock,
@ -128,19 +127,18 @@ static int update_edge( n2n_sn_t * sss,
n2n_sock_str_t sockbuf; n2n_sock_str_t sockbuf;
struct peer_info * scan; struct peer_info * scan;
traceEvent( TRACE_DEBUG, "update_edge for %s [%s]", traceEvent(TRACE_DEBUG, "update_edge for %s [%s]",
macaddr_str( mac_buf, edgeMac ), macaddr_str(mac_buf, edgeMac),
sock_to_cstr( sockbuf, sender_sock ) ); 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 */ /* Not known */
scan = (struct peer_info*)calloc(1, sizeof(struct peer_info)); /* deallocated in purge_expired_registrations */ 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->mac_addr), edgeMac, sizeof(n2n_mac_t));
memcpy(&(scan->sock), sender_sock, sizeof(n2n_sock_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 */ scan->next = sss->edges; /* first in list */
sss->edges = scan; /* head of list points to new scan */ sss->edges = scan; /* head of list points to new scan */
traceEvent( TRACE_INFO, "update_edge created %s ==> %s", traceEvent(TRACE_INFO, "update_edge created %s ==> %s",
macaddr_str( mac_buf, edgeMac ), macaddr_str(mac_buf, edgeMac),
sock_to_cstr( sockbuf, sender_sock ) ); sock_to_cstr(sockbuf, sender_sock));
} } else {
else
{
/* Known */ /* Known */
if ( (0 != memcmp(community, scan->community_name, sizeof(n2n_community_t))) || if((0 != memcmp(community, scan->community_name, sizeof(n2n_community_t))) ||
(0 != sock_equal(sender_sock, &(scan->sock) )) ) (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)); memcpy(&(scan->sock), sender_sock, sizeof(n2n_sock_t));
traceEvent( TRACE_INFO, "update_edge updated %s ==> %s", traceEvent(TRACE_INFO, "update_edge updated %s ==> %s",
macaddr_str( mac_buf, edgeMac ), macaddr_str(mac_buf, edgeMac),
sock_to_cstr( sockbuf, sender_sock ) ); sock_to_cstr(sockbuf, sender_sock));
} }
else else
{ {
traceEvent( TRACE_DEBUG, "update_edge unchanged %s ==> %s", traceEvent(TRACE_DEBUG, "update_edge unchanged %s ==> %s",
macaddr_str( mac_buf, edgeMac ), macaddr_str(mac_buf, edgeMac),
sock_to_cstr( sockbuf, sender_sock ) ); sock_to_cstr(sockbuf, sender_sock));
} }
} }
@ -190,20 +186,20 @@ static ssize_t sendto_sock(n2n_sn_t * sss,
{ {
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;
udpsock.sin_port = htons( sock->port ); udpsock.sin_port = htons(sock->port);
memcpy( &(udpsock.sin_addr.s_addr), &(sock->addr.v4), IPV4_SIZE ); 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, pktsize,
sock_to_cstr( sockbuf, sock ) ); sock_to_cstr(sockbuf, sock));
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
{ {
@ -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 /** Try to forward a message to a unicast MAC. If the MAC is unknown then
* broadcast to all edges in the destination community. * 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_common_t * cmn,
const n2n_mac_t dstMac, const n2n_mac_t dstMac,
const uint8_t * pktbuf, const uint8_t * pktbuf,
size_t pktsize ) size_t pktsize)
{ {
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;
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; 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
@ -248,14 +244,14 @@ static int try_forward( n2n_sn_t * sss,
++(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,
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),
errno, strerror(errno) ); errno, strerror(errno));
} }
} }
else else
{ {
traceEvent( TRACE_DEBUG, "try_forward unknown MAC" ); traceEvent(TRACE_DEBUG, "try_forward unknown MAC");
/* Not a known MAC so drop. */ /* 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 * This will send the exact same datagram to zero or more edges registered to
* the supernode. * 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_common_t * cmn,
const n2n_mac_t srcMac, const n2n_mac_t srcMac,
const uint8_t * pktbuf, const uint8_t * pktbuf,
size_t pktsize ) size_t pktsize)
{ {
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;
traceEvent( TRACE_DEBUG, "try_broadcast" ); traceEvent(TRACE_DEBUG, "try_broadcast");
scan = sss->edges; scan = sss->edges;
while(scan != NULL) while(scan != NULL)
{ {
if( 0 == (memcmp(scan->community_name, cmn->community, sizeof(n2n_community_t)) ) if(0 == (memcmp(scan->community_name, cmn->community, sizeof(n2n_community_t)))
&& (0 != memcmp(srcMac, scan->mac_addr, sizeof(n2n_mac_t)) ) ) && (0 != memcmp(srcMac, scan->mac_addr, sizeof(n2n_mac_t))))
/* REVISIT: exclude if the destination socket is where the packet came from. */ /* REVISIT: exclude if the destination socket is where the packet came from. */
{ {
int data_sent_len; int data_sent_len;
@ -297,7 +293,7 @@ static int try_broadcast( n2n_sn_t * sss,
++(sss->stats.errors); ++(sss->stats.errors);
traceEvent(TRACE_WARNING, "multicast %lu to [%s] %s failed %s", traceEvent(TRACE_WARNING, "multicast %lu to [%s] %s failed %s",
pktsize, pktsize,
sock_to_cstr( sockbuf, &(scan->sock) ), sock_to_cstr(sockbuf, &(scan->sock)),
macaddr_str(mac_buf, scan->mac_addr), macaddr_str(mac_buf, scan->mac_addr),
strerror(errno)); strerror(errno));
} }
@ -306,7 +302,7 @@ static int try_broadcast( n2n_sn_t * sss,
++(sss->stats.broadcast); ++(sss->stats.broadcast);
traceEvent(TRACE_DEBUG, "multicast %lu to [%s] %s", traceEvent(TRACE_DEBUG, "multicast %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));
} }
} }
@ -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 struct sockaddr_in * sender_sock,
const uint8_t * mgmt_buf, const uint8_t * mgmt_buf,
size_t mgmt_size, size_t mgmt_size,
@ -328,54 +324,54 @@ static int process_mgmt( n2n_sn_t * sss,
size_t ressize=0; size_t ressize=0;
ssize_t r; ssize_t r;
traceEvent( TRACE_DEBUG, "process_mgmt" ); traceEvent(TRACE_DEBUG, "process_mgmt");
ressize += snprintf( resbuf+ressize, N2N_SN_PKTBUF_SIZE-ressize, ressize += snprintf(resbuf+ressize, N2N_SN_PKTBUF_SIZE-ressize,
"----------------\n" ); "----------------\n");
ressize += snprintf( resbuf+ressize, N2N_SN_PKTBUF_SIZE-ressize, ressize += snprintf(resbuf+ressize, N2N_SN_PKTBUF_SIZE-ressize,
"uptime %lu\n", (now - sss->start_time) ); "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", "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", "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", "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", "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", "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", "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", "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", "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*/, r = sendto(sss->mgmt_sock, resbuf, ressize, 0/*flags*/,
(struct sockaddr *)sender_sock, sizeof(struct sockaddr_in) ); (struct sockaddr *)sender_sock, sizeof(struct sockaddr_in));
if ( r <= 0 ) if(r <= 0)
{ {
++(sss->stats.errors); ++(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; return 0;
@ -417,15 +413,28 @@ static int load_allowed_n2n_communities(char *path) {
free(s); free(s);
while((line = fgets(buffer, sizeof(buffer), fd)) != NULL) { while((line = fgets(buffer, sizeof(buffer), fd)) != NULL) {
if((strlen(line) < 2) || line[0] == '#') int len = strlen(line);
if((len < 2) || line[0] == '#')
continue; 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)); s = (struct n2n_allowed_communities*)malloc(sizeof(struct n2n_allowed_communities));
if(s != NULL) { if(s != NULL) {
strncpy((char*)s->community, line, N2N_COMMUNITY_SIZE); strncpy((char*)s->community, line, N2N_COMMUNITY_SIZE);
HASH_ADD_STR(allowed_communities, community, s); HASH_ADD_STR(allowed_communities, community, s);
num_communities++; 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. /** 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 struct sockaddr_in * sender_sock,
const uint8_t * udp_buf, const uint8_t * udp_buf,
size_t udp_size, size_t udp_size,
@ -454,9 +463,11 @@ static int process_udp( n2n_sn_t * sss,
macstr_t mac_buf; macstr_t mac_buf;
macstr_t mac_buf2; macstr_t mac_buf2;
n2n_sock_str_t sockbuf; n2n_sock_str_t sockbuf;
char buf[32];
traceEvent(TRACE_DEBUG, "Processing incoming UDP packet [len: %lu][sender: %s:%u]",
traceEvent( TRACE_DEBUG, "process_udp(%lu)", udp_size ); 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: /* 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. */ rem = udp_size; /* Counts down bytes of packet to protect against buffer overruns. */
idx = 0; /* marches through packet header as parts are decoded. */ idx = 0; /* marches through packet header as parts are decoded. */
if ( decode_common(&cmn, udp_buf, &rem, &idx) < 0 ) if(decode_common(&cmn, udp_buf, &rem, &idx) < 0) {
{ traceEvent(TRACE_ERROR, "Failed to decode common section");
traceEvent( TRACE_ERROR, "Failed to decode common section" );
return -1; /* failed to decode packet */ return -1; /* failed to decode packet */
} }
msg_type = cmn.pc; /* packet code */ msg_type = cmn.pc; /* packet code */
from_supernode= cmn.flags & N2N_FLAGS_FROM_SUPERNODE; from_supernode= cmn.flags & N2N_FLAGS_FROM_SUPERNODE;
if ( cmn.ttl < 1 ) if(cmn.ttl < 1) {
{ traceEvent(TRACE_WARNING, "Expired TTL");
traceEvent( TRACE_WARNING, "Expired TTL" );
return 0; /* Don't process further */ return 0; /* Don't process further */
} }
--(cmn.ttl); /* The value copied into all forwarded packets. */ --(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. */ /* 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
@ -501,58 +509,50 @@ static int process_udp( n2n_sn_t * sss,
sss->stats.last_fwd=now; 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"), (unicast?"unicast":"multicast"),
macaddr_str( mac_buf, pkt.srcMac ), macaddr_str(mac_buf, pkt.srcMac),
macaddr_str( mac_buf2, pkt.dstMac ), macaddr_str(mac_buf2, pkt.dstMac),
(from_supernode?"from sn":"local") ); (from_supernode?"from sn":"local"));
if ( !from_supernode ) if(!from_supernode) {
{ memcpy(&cmn2, &cmn, sizeof(n2n_common_t));
memcpy( &cmn2, &cmn, sizeof( n2n_common_t ) );
/* We are going to add socket even if it was not there before */ /* We are going to add socket even if it was not there before */
cmn2.flags |= N2N_FLAGS_SOCKET | N2N_FLAGS_FROM_SUPERNODE; cmn2.flags |= N2N_FLAGS_SOCKET | N2N_FLAGS_FROM_SUPERNODE;
pkt.sock.family = AF_INET; pkt.sock.family = AF_INET;
pkt.sock.port = ntohs(sender_sock->sin_port); 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; rec_buf = encbuf;
/* Re-encode the header. */ /* Re-encode the header. */
encode_PACKET( encbuf, &encx, &cmn2, &pkt ); encode_PACKET(encbuf, &encx, &cmn2, &pkt);
/* 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));
} } else {
else
{
/* Already from a supernode. Nothing to modify, just pass to /* Already from a supernode. Nothing to modify, just pass to
* destination. */ * destination. */
traceEvent( TRACE_DEBUG, "Rx PACKET fwd unmodified" ); traceEvent(TRACE_DEBUG, "Rx PACKET fwd unmodified");
rec_buf = udp_buf; rec_buf = udp_buf;
encx = udp_size; encx = udp_size;
} }
/* Common section to forward the final product. */ /* Common section to forward the final product. */
if ( unicast ) if(unicast)
{ try_forward(sss, &cmn, pkt.dstMac, rec_buf, encx);
try_forward( sss, &cmn, pkt.dstMac, rec_buf, encx );
}
else else
{ try_broadcast(sss, &cmn, pkt.srcMac, rec_buf, encx);
try_broadcast( sss, &cmn, pkt.srcMac, rec_buf, encx );
}
}/* MSG_TYPE_PACKET */ }/* 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 */ /* Forwarding a REGISTER from one edge to the next */
n2n_REGISTER_t reg; 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 */ const uint8_t * rec_buf; /* either udp_buf or encbuf */
sss->stats.last_fwd=now; 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 ) if(unicast) {
{ traceEvent(TRACE_DEBUG, "Rx REGISTER %s -> %s %s",
traceEvent( TRACE_DEBUG, "Rx REGISTER %s -> %s %s", macaddr_str(mac_buf, reg.srcMac),
macaddr_str( mac_buf, reg.srcMac ), macaddr_str(mac_buf2, reg.dstMac),
macaddr_str( mac_buf2, reg.dstMac ), ((cmn.flags & N2N_FLAGS_FROM_SUPERNODE)?"from sn":"local"));
((cmn.flags & N2N_FLAGS_FROM_SUPERNODE)?"from sn":"local") );
if ( 0 != (cmn.flags & N2N_FLAGS_FROM_SUPERNODE) ) if(0 != (cmn.flags & N2N_FLAGS_FROM_SUPERNODE)) {
{ memcpy(&cmn2, &cmn, sizeof(n2n_common_t));
memcpy( &cmn2, &cmn, sizeof( n2n_common_t ) );
/* We are going to add socket even if it was not there before */ /* We are going to add socket even if it was not there before */
cmn2.flags |= N2N_FLAGS_SOCKET | N2N_FLAGS_FROM_SUPERNODE; cmn2.flags |= N2N_FLAGS_SOCKET | N2N_FLAGS_FROM_SUPERNODE;
reg.sock.family = AF_INET; reg.sock.family = AF_INET;
reg.sock.port = ntohs(sender_sock->sin_port); 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; rec_buf = encbuf;
/* Re-encode the header. */ /* Re-encode the header. */
encode_REGISTER( encbuf, &encx, &cmn2, &reg ); encode_REGISTER(encbuf, &encx, &cmn2, &reg);
/* 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));
} } else {
else
{
/* Already from a supernode. Nothing to modify, just pass to /* Already from a supernode. Nothing to modify, just pass to
* destination. */ * destination. */
@ -602,20 +598,12 @@ static int process_udp( n2n_sn_t * sss,
encx = udp_size; encx = udp_size;
} }
try_forward( sss, &cmn, reg.dstMac, rec_buf, encx ); /* unicast only */ try_forward(sss, &cmn, reg.dstMac, rec_buf, encx); /* unicast only */
} } else
else traceEvent(TRACE_ERROR, "Rx REGISTER with multicast destination");
{ } else if(msg_type == MSG_TYPE_REGISTER_ACK)
traceEvent( TRACE_ERROR, "Rx REGISTER with multicast destination" ); traceEvent(TRACE_DEBUG, "Rx REGISTER_ACK (NOT IMPLEMENTED) SHould not be via supernode");
} else if(msg_type == MSG_TYPE_REGISTER_SUPER) {
}
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_t reg;
n2n_REGISTER_SUPER_ACK_t ack; n2n_REGISTER_SUPER_ACK_t ack;
n2n_common_t cmn2; n2n_common_t cmn2;
@ -625,7 +613,7 @@ static int process_udp( n2n_sn_t * sss,
/* Edge requesting registration with us. */ /* Edge requesting registration with us. */
sss->stats.last_reg_super=now; sss->stats.last_reg_super=now;
++(sss->stats.reg_super); ++(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 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.ttl = N2N_DEFAULT_TTL;
cmn2.pc = n2n_register_super_ack; cmn2.pc = n2n_register_super_ack;
cmn2.flags = N2N_FLAGS_SOCKET | N2N_FLAGS_FROM_SUPERNODE; 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.cookie), &(reg.cookie), sizeof(n2n_cookie_t));
memcpy( ack.edgeMac, reg.edgeMac, sizeof(n2n_mac_t) ); memcpy(ack.edgeMac, reg.edgeMac, sizeof(n2n_mac_t));
ack.lifetime = reg_lifetime( sss ); ack.lifetime = reg_lifetime(sss);
ack.sock.family = AF_INET; ack.sock.family = AF_INET;
ack.sock.port = ntohs(sender_sock->sin_port); 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 */ 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]", 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)));
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, sendto(sss->sock, ackbuf, encx, 0,
(struct sockaddr *)sender_sock, sizeof(struct sockaddr_in) ); (struct sockaddr *)sender_sock, sizeof(struct sockaddr_in));
traceEvent( TRACE_DEBUG, "Tx REGISTER_SUPER_ACK for %s [%s]", traceEvent(TRACE_DEBUG, "Tx REGISTER_SUPER_ACK 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)));
} 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. */ /** Help message to print if the command line arguments are not valid. */
static void help() static void help() {
{
print_n2n_version(); print_n2n_version();
printf("supernode <config file> (see supernode.conf)\n" printf("supernode <config file> (see supernode.conf)\n"
@ -682,12 +672,13 @@ static void help()
); );
printf("supernode "); printf("supernode ");
printf("-l <lport> "); printf("-l <lport> ");
printf("-c <community file path> "); printf("-c <path> ");
printf("[-f] "); printf("[-f] ");
printf("[-v] "); printf("[-v] ");
printf("\n\n"); printf("\n\n");
printf("-l <lport>\tSet UDP main listen port to <lport>\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) #if defined(N2N_HAVE_DAEMON)
printf("-f \tRun in foreground.\n"); printf("-f \tRun in foreground.\n");
#endif /* #if defined(N2N_HAVE_DAEMON) */ #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) { static int setOption(int optkey, char *_optarg, n2n_sn_t *sss) {
//traceEvent(TRACE_NORMAL, "Option %c = %s", optkey, _optarg ? _optarg : ""); //traceEvent(TRACE_NORMAL, "Option %c = %s", optkey, _optarg ? _optarg : "");
switch(optkey) { switch(optkey) {
case 'l': /* local-port */ case 'l': /* local-port */
{
sss->lport = atoi(_optarg); sss->lport = atoi(_optarg);
break; break;
}
case 'c': /* community file */ case 'c': /* community file */
load_allowed_n2n_communities(optarg); load_allowed_n2n_communities(optarg);
break; break;
case 'f': /* foreground */ case 'f': /* foreground */
{
sss->daemon = 0; sss->daemon = 0;
break; break;
}
case 'h': /* help */ case 'h': /* help */
{
help(); help();
break; break;
}
case 'v': /* verbose */ case 'v': /* verbose */
{ traceLevel = 4; /* DEBUG */
++traceLevel;
break; break;
}
default: default:
{
traceEvent(TRACE_WARNING, "Unknown option -%c: Ignored.", (char)optkey); traceEvent(TRACE_WARNING, "Unknown option -%c: Ignored.", (char)optkey);
return(-1); return(-1);
} }
}
return(0); return(0);
} }
@ -763,8 +743,7 @@ static const struct option long_options[] = {
static int loadFromCLI(int argc, char * const argv[], n2n_sn_t *sss) { static int loadFromCLI(int argc, char * const argv[], n2n_sn_t *sss) {
u_char c; u_char c;
while((c = getopt_long(argc, argv, while((c = getopt_long(argc, argv, "fl:c:vh",
"fl:c:vh",
long_options, NULL)) != '?') { long_options, NULL)) != '?') {
if(c == 255) break; if(c == 255) break;
setOption(c, optarg, sss); 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) { static char *trim(char *s) {
char *end; 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; if(s[0] == 0) return s;
end = &s[strlen(s) - 1]; 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. */ /** Main program entry point from kernel. */
int main( int argc, char * const argv[] ) int main(int argc, char * const argv[]) {
{
int rc; int rc;
n2n_sn_t sss;
if(argc == 1) if(argc == 1)
help(); help();
init_sn(&sss); init_sn(&sss_node);
#ifndef WIN32 #ifndef WIN32
if((argc >= 2) && (argv[1][0] != '-')) if((argc >= 2) && (argv[1][0] != '-')) {
{ rc = loadFromFile(argv[1], &sss_node);
rc = loadFromFile(argv[1], &sss); if(argc > 2)
if (argc > 2) rc = loadFromCLI(argc, argv, &sss_node);
rc = loadFromCLI(argc, argv, &sss);
} else } else
#endif #endif
rc = loadFromCLI(argc, argv, &sss); rc = loadFromCLI(argc, argv, &sss_node);
if (rc < 0) if(rc < 0)
return(-1); return(-1);
#if defined(N2N_HAVE_DAEMON) #if defined(N2N_HAVE_DAEMON)
if (sss.daemon) if(sss_node.daemon) {
{
useSyslog=1; /* traceEvent output now goes to syslog. */ useSyslog=1; /* traceEvent output now goes to syslog. */
if ( -1 == daemon( 0, 0 ) )
{ if(-1 == daemon(0, 0)) {
traceEvent( TRACE_ERROR, "Failed to become daemon." ); traceEvent(TRACE_ERROR, "Failed to become daemon.");
exit(-5); exit(-5);
} }
} }
#endif /* #if defined(N2N_HAVE_DAEMON) */ #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*/ ); sss_node.sock = open_socket(sss_node.lport, 1 /*bind ANY*/);
if ( -1 == sss.sock ) if(-1 == sss_node.sock) {
{ traceEvent(TRACE_ERROR, "Failed to open main socket. %s", strerror(errno));
traceEvent( TRACE_ERROR, "Failed to open main socket. %s", strerror(errno) );
exit(-2); exit(-2);
} } else {
else traceEvent(TRACE_NORMAL, "supernode is listening on UDP %u (main)", sss_node.lport);
{
traceEvent( TRACE_NORMAL, "supernode is listening on UDP %u (main)", sss.lport );
} }
sss.mgmt_sock = open_socket(N2N_SN_MGMT_PORT, 0 /* bind LOOPBACK */ ); sss_node.mgmt_sock = open_socket(N2N_SN_MGMT_PORT, 0 /* bind LOOPBACK */);
if ( -1 == sss.mgmt_sock ) if(-1 == sss_node.mgmt_sock) {
{ traceEvent(TRACE_ERROR, "Failed to open management socket. %s", strerror(errno));
traceEvent( TRACE_ERROR, "Failed to open management socket. %s", strerror(errno) );
exit(-2); exit(-2);
} } else
else traceEvent(TRACE_NORMAL, "supernode is listening on UDP %u (management)", N2N_SN_MGMT_PORT);
{
traceEvent( TRACE_NORMAL, "supernode is listening on UDP %u (management)", N2N_SN_MGMT_PORT );
}
traceEvent(TRACE_NORMAL, "supernode started"); 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 /** Long lived processing entry point. Split out from main to simply
* daemonisation on some platforms. */ * 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]; uint8_t pktbuf[N2N_SN_PKTBUF_SIZE];
int keep_running=1; int keep_running=1;
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;
@ -951,63 +951,56 @@ static int run_loop( n2n_sn_t * sss )
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;
i = sizeof(sender_sock); 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); (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. */ /* 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; keep_running=0;
break; break;
} }
/* 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;
i = sizeof(sender_sock); 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); (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;
} }
/* 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" );
} }
purge_expired_registrations( &(sss->edges) ); purge_expired_registrations(&(sss->edges));
} /* while */ } /* while */
deinit_sn( sss ); deinit_sn(sss);
return 0; return 0;
} }

Loading…
Cancel
Save