From dffdb6c6f57fe386bf68362ed146caea2a61cd38 Mon Sep 17 00:00:00 2001 From: Luca Deri Date: Fri, 28 Sep 2018 22:08:18 +0200 Subject: [PATCH] Added the ability with kill -HUP to let the supernode display registered peers Improvd supernode help --- n2n.c | 6 +- packages/etc/n2n/supernode.conf | 3 + sn.c | 687 ++++++++++++++++---------------- 3 files changed, 345 insertions(+), 351 deletions(-) diff --git a/n2n.c b/n2n.c index 7eea7d0..cb92275 100644 --- a/n2n.c +++ b/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; diff --git a/packages/etc/n2n/supernode.conf b/packages/etc/n2n/supernode.conf index dc968c0..373c872 100644 --- a/packages/etc/n2n/supernode.conf +++ b/packages/etc/n2n/supernode.conf @@ -9,3 +9,6 @@ # # -l=7777 # +# Specify in supernodes.list the list of allowed communities +# +# -c=supernodes.list \ No newline at end of file diff --git a/sn.c b/sn.c index 096af76..80b4240 100644 --- a/sn.c +++ b/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, - const n2n_common_t * cmn, - const n2n_mac_t dstMac, - const uint8_t * pktbuf, - size_t pktsize ); - -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 ); +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); +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); +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,35 +111,34 @@ 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, - const n2n_mac_t edgeMac, - const n2n_community_t community, - const n2n_sock_t * sender_sock, - time_t now) { +static int update_edge(n2n_sn_t * sss, + const n2n_mac_t edgeMac, + const n2n_community_t community, + const n2n_sock_t * sender_sock, + time_t now) { macstr_t mac_buf; 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]", - pktsize, - sock_to_cstr( sockbuf, sock ) ); + traceEvent(TRACE_DEBUG, "sendto_sock %lu to [%s]", + pktsize, + 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, - const n2n_common_t * cmn, - const n2n_mac_t dstMac, - const uint8_t * pktbuf, - size_t pktsize ) +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) { 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, - const n2n_common_t * cmn, - const n2n_mac_t srcMac, - const uint8_t * pktbuf, - size_t pktsize ) +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) { 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,64 +314,64 @@ static int try_broadcast( 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, - time_t now) +static int process_mgmt(n2n_sn_t * sss, + const struct sockaddr_in * sender_sock, + const uint8_t * mgmt_buf, + size_t mgmt_size, + time_t now) { char resbuf[N2N_SN_PKTBUF_SIZE]; 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, - "edges %u\n", - (unsigned int)peer_list_size( sss->edges ) ); + ressize += snprintf(resbuf+ressize, N2N_SN_PKTBUF_SIZE-ressize, + "edges %u\n", + (unsigned int)peer_list_size(sss->edges)); - ressize += snprintf( resbuf+ressize, N2N_SN_PKTBUF_SIZE-ressize, - "errors %u\n", - (unsigned int)sss->stats.errors ); + ressize += snprintf(resbuf+ressize, N2N_SN_PKTBUF_SIZE-ressize, + "errors %u\n", + (unsigned int)sss->stats.errors); - ressize += snprintf( resbuf+ressize, N2N_SN_PKTBUF_SIZE-ressize, - "reg_sup %u\n", - (unsigned int)sss->stats.reg_super ); + ressize += snprintf(resbuf+ressize, N2N_SN_PKTBUF_SIZE-ressize, + "reg_sup %u\n", + (unsigned int)sss->stats.reg_super); - ressize += snprintf( resbuf+ressize, N2N_SN_PKTBUF_SIZE-ressize, - "reg_nak %u\n", - (unsigned int)sss->stats.reg_super_nak ); + ressize += snprintf(resbuf+ressize, N2N_SN_PKTBUF_SIZE-ressize, + "reg_nak %u\n", + (unsigned int)sss->stats.reg_super_nak); - ressize += snprintf( resbuf+ressize, N2N_SN_PKTBUF_SIZE-ressize, - "fwd %u\n", - (unsigned int) sss->stats.fwd ); + ressize += snprintf(resbuf+ressize, N2N_SN_PKTBUF_SIZE-ressize, + "fwd %u\n", + (unsigned int) sss->stats.fwd); - ressize += snprintf( resbuf+ressize, N2N_SN_PKTBUF_SIZE-ressize, - "broadcast %u\n", - (unsigned int) sss->stats.broadcast ); + ressize += snprintf(resbuf+ressize, N2N_SN_PKTBUF_SIZE-ressize, + "broadcast %u\n", + (unsigned int) sss->stats.broadcast); - ressize += snprintf( resbuf+ressize, N2N_SN_PKTBUF_SIZE-ressize, - "last fwd %lu sec ago\n", - (long unsigned int)(now - sss->stats.last_fwd) ); + ressize += snprintf(resbuf+ressize, N2N_SN_PKTBUF_SIZE-ressize, + "last fwd %lu sec ago\n", + (long unsigned int)(now - sss->stats.last_fwd)); - ressize += snprintf( resbuf+ressize, N2N_SN_PKTBUF_SIZE-ressize, - "last reg %lu sec ago\n", - (long unsigned int) (now - sss->stats.last_reg_super) ); + ressize += snprintf(resbuf+ressize, N2N_SN_PKTBUF_SIZE-ressize, + "last reg %lu sec ago\n", + (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,11 +449,11 @@ 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, - const struct sockaddr_in * sender_sock, - const uint8_t * udp_buf, - size_t udp_size, - time_t now) +static int process_udp(n2n_sn_t * sss, + const struct sockaddr_in * sender_sock, + const uint8_t * udp_buf, + size_t udp_size, + time_t now) { n2n_common_t cmn; /* common fields in the packet header */ size_t rem; @@ -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", - (unicast?"unicast":"multicast"), - macaddr_str( mac_buf, pkt.srcMac ), - macaddr_str( mac_buf2, pkt.dstMac ), - (from_supernode?"from sn":"local") ); + 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")); - 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,34 +625,37 @@ 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); + } } return 0; @@ -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 (see supernode.conf)\n" @@ -682,12 +672,13 @@ static void help() ); printf("supernode "); printf("-l "); - printf("-c "); + printf("-c "); printf("[-f] "); printf("[-v] "); printf("\n\n"); printf("-l \tSet UDP main listen port to \n"); + printf("-c \tFile containing the allowed communities.\n"); #if defined(N2N_HAVE_DAEMON) printf("-f \tRun in foreground.\n"); #endif /* #if defined(N2N_HAVE_DAEMON) */ @@ -700,48 +691,37 @@ 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; - } - + sss->lport = atoi(_optarg); + break; + case 'c': /* community file */ load_allowed_n2n_communities(optarg); break; case 'f': /* foreground */ - { - sss->daemon = 0; - break; - } + sss->daemon = 0; + break; case 'h': /* help */ - { - help(); - break; - } + help(); + break; case 'v': /* verbose */ - { - ++traceLevel; - break; - } + traceLevel = 4; /* DEBUG */ + break; default: - { - traceEvent(TRACE_WARNING, "Unknown option -%c: Ignored.", (char)optkey); - return(-1); - } + 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,158 +837,170 @@ 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); - } else + 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) - { - useSyslog=1; /* traceEvent output now goes to syslog. */ - if ( -1 == daemon( 0, 0 ) ) - { - traceEvent( TRACE_ERROR, "Failed to become daemon." ); - exit(-5); - } + if(sss_node.daemon) { + useSyslog=1; /* traceEvent output now goes to syslog. */ + + 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) ); - exit(-2); - } - else - { - traceEvent( TRACE_NORMAL, "supernode is listening on UDP %u (main)", sss.lport ); - } + 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_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) ); - exit(-2); - } - else - { - traceEvent( TRACE_NORMAL, "supernode is listening on UDP %u (management)", N2N_SN_MGMT_PORT ); - } + 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); 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) - { - int rc; - ssize_t bread; - int max_sock; - fd_set socket_mask; - struct timeval wait_time; - time_t now=0; + while(keep_running) { + int rc; + ssize_t bread; + int max_sock; + fd_set socket_mask; + struct timeval wait_time; + time_t now=0; - FD_ZERO(&socket_mask); - max_sock = MAX(sss->sock, sss->mgmt_sock); + FD_ZERO(&socket_mask); + max_sock = MAX(sss->sock, sss->mgmt_sock); - FD_SET(sss->sock, &socket_mask); - FD_SET(sss->mgmt_sock, &socket_mask); + FD_SET(sss->sock, &socket_mask); + FD_SET(sss->mgmt_sock, &socket_mask); - wait_time.tv_sec = 10; wait_time.tv_usec = 0; - rc = select(max_sock+1, &socket_mask, NULL, NULL, &wait_time); + wait_time.tv_sec = 10; wait_time.tv_usec = 0; + rc = select(max_sock+1, &socket_mask, NULL, NULL, &wait_time); - now = time(NULL); + now = time(NULL); - 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*/, - (struct sockaddr *)&sender_sock, (socklen_t*)&i); - - 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) ); - keep_running=0; - break; - } - - /* We have a datagram to process */ - if ( bread > 0 ) - { - /* And the datagram has data (not just a header) */ - process_udp( sss, &sender_sock, pktbuf, bread, now ); - } - } + if(rc > 0) { + if(FD_ISSET(sss->sock, &socket_mask)) { + struct sockaddr_in sender_sock; + socklen_t i; - 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*/, - (struct sockaddr *)&sender_sock, (socklen_t*)&i); - - 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 ); - } - } - else - { - traceEvent( TRACE_DEBUG, "timeout" ); - } + i = sizeof(sender_sock); + bread = recvfrom(sss->sock, pktbuf, N2N_SN_PKTBUF_SIZE, 0/*flags*/, + (struct sockaddr *)&sender_sock, (socklen_t*)&i); - purge_expired_registrations( &(sss->edges) ); + 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)); + keep_running=0; + break; + } - } /* while */ + /* We have a datagram to process */ + if(bread > 0) { + /* And the datagram has data (not just a header) */ + process_udp(sss, &sender_sock, pktbuf, bread, now); + } + } + + 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*/, + (struct sockaddr *)&sender_sock, (socklen_t*)&i); + + 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); + } + } else { + traceEvent(TRACE_DEBUG, "timeout"); + } + + purge_expired_registrations(&(sss->edges)); + + } /* while */ - deinit_sn( sss ); + deinit_sn(sss); return 0; }