diff --git a/include/n2n_typedefs.h b/include/n2n_typedefs.h index 752cf3b..31d5d9d 100644 --- a/include/n2n_typedefs.h +++ b/include/n2n_typedefs.h @@ -282,6 +282,10 @@ typedef enum n2n_pc { #define N2N_ENOSPACE -4 +#define N2N_VERSION_STRING_SIZE 20 +typedef char n2n_version_t[N2N_VERSION_STRING_SIZE]; + + typedef struct n2n_ip_subnet { uint32_t net_addr; /* Host order IP address. */ uint8_t net_bitlen; /* Subnet prefix. */ @@ -411,6 +415,8 @@ typedef struct n2n_PEER_INFO { n2n_sock_t sock; n2n_sock_t preferred_sock; SN_SELECTION_CRITERION_DATA_TYPE data; + n2n_version_t version; + time_t uptime; } n2n_PEER_INFO_t; @@ -418,6 +424,7 @@ typedef struct n2n_QUERY_PEER { n2n_mac_t srcMac; n2n_sock_t sock; n2n_mac_t targetMac; + } n2n_QUERY_PEER_t; typedef struct n2n_buf n2n_buf_t; @@ -441,6 +448,8 @@ struct peer_info { uint64_t last_valid_time_stamp; char *ip_addr; uint8_t local; + time_t uptime; + n2n_version_t version; UT_hash_handle hh; /* makes this structure hashable */ }; @@ -793,6 +802,7 @@ typedef struct n2n_tcp_connection { typedef struct n2n_sn { time_t start_time; /* Used to measure uptime. */ + n2n_version_t version; /* version string sent to edges along with PEER_INFO a.k.a. PONG */ sn_stats_t stats; int daemon; /* If non-zero then daemonise. */ n2n_mac_t mac_addr; diff --git a/src/edge_utils.c b/src/edge_utils.c index 9f8c135..43c2dfe 100644 --- a/src/edge_utils.c +++ b/src/edge_utils.c @@ -1905,9 +1905,9 @@ static void readFromMgmtSocket (n2n_edge_t *eee, int *keep_running) { "COMMUNITY '%s'\n\n", eee->conf.community_name); msg_len += snprintf((char *) (udp_buf + msg_len), (N2N_PKT_BUF_SIZE - msg_len), - " ### | TAP | MAC | EDGE | HINT | LAST SEEN\n"); + " ### | TAP | MAC | EDGE | HINT | LAST SEEN | VERSION | UPTIME \n\n"); msg_len += snprintf((char *) (udp_buf + msg_len), (N2N_PKT_BUF_SIZE - msg_len), - "================================================================================================\n"); + "===================================================================================================================================\n"); // dump nodes with forwarding through supernodes msg_len += snprintf((char *) (udp_buf + msg_len), (N2N_PKT_BUF_SIZE - msg_len), @@ -1918,7 +1918,7 @@ static void readFromMgmtSocket (n2n_edge_t *eee, int *keep_running) { net = htonl(peer->dev_addr.net_addr); snprintf (time_buf, sizeof(time_buf), "%9u", (unsigned int)(now - peer->last_seen)); msg_len += snprintf((char *) (udp_buf + msg_len), (N2N_PKT_BUF_SIZE - msg_len), - "%4u | %-15s | %-17s | %-21s | %-15s | %9s\n", + "%4u | %-15s | %-17s | %-21s | %-15s | %9s | |\n", ++num, (peer->dev_addr.net_addr == 0) ? "" : inet_ntoa(*(struct in_addr *) &net), (is_null_mac(peer->mac_addr)) ? "" : macaddr_str(mac_buf, peer->mac_addr), @@ -1933,7 +1933,7 @@ static void readFromMgmtSocket (n2n_edge_t *eee, int *keep_running) { // dump peer-to-peer nodes msg_len += snprintf((char *) (udp_buf + msg_len), (N2N_PKT_BUF_SIZE - msg_len), - "------------------------------------------------------------------------------------------------\n"); + "-----------------------------------------------------------------------------------------------------------------------------------\n"); msg_len += snprintf((char *) (udp_buf + msg_len), (N2N_PKT_BUF_SIZE - msg_len), "PEER TO PEER\n"); num = 0; @@ -1942,7 +1942,7 @@ static void readFromMgmtSocket (n2n_edge_t *eee, int *keep_running) { net = htonl(peer->dev_addr.net_addr); snprintf (time_buf, sizeof(time_buf), "%9u", (unsigned int)(now - peer->last_seen)); msg_len += snprintf((char *) (udp_buf + msg_len), (N2N_PKT_BUF_SIZE - msg_len), - "%4u | %-15s | %-17s | %-21s | %-15s | %9s\n", + "%4u | %-15s | %-17s | %-21s | %-15s | %9s | |\n", ++num, (peer->dev_addr.net_addr == 0) ? "" : inet_ntoa(*(struct in_addr *) &net), (is_null_mac(peer->mac_addr)) ? "" : macaddr_str(mac_buf, peer->mac_addr), @@ -1957,23 +1957,24 @@ static void readFromMgmtSocket (n2n_edge_t *eee, int *keep_running) { // dump supernodes msg_len += snprintf((char *) (udp_buf + msg_len), (N2N_PKT_BUF_SIZE - msg_len), - "------------------------------------------------------------------------------------------------\n"); + "-----------------------------------------------------------------------------------------------------------------------------------\n"); msg_len += snprintf((char *) (udp_buf + msg_len), (N2N_PKT_BUF_SIZE - msg_len), "SUPERNODES\n"); - HASH_ITER(hh, eee->conf.supernodes, peer, tmpPeer) { net = htonl(peer->dev_addr.net_addr); snprintf (time_buf, sizeof(time_buf), "%9u", (unsigned int)(now - peer->last_seen)); msg_len += snprintf((char *) (udp_buf + msg_len), (N2N_PKT_BUF_SIZE - msg_len), - "%4u | %-3s %-11s | %-17s | %-21s | %-15s | %9s\n", + "%4u | %-3s %-11s | %-17s | %-21s | %-15s | %9s | %-19s | %10lu\n", ++num, (peer->purgeable == SN_UNPURGEABLE) ? "-l" : "", (peer == eee->curr_sn) ? (eee->sn_wait ? ">>..." : ">>>>>" ) : "", is_null_mac(peer->mac_addr) ? "" : macaddr_str(mac_buf, peer->mac_addr), sock_to_cstr(sockbuf, &(peer->sock)), sn_selection_criterion_str(sel_buf, peer), - (peer->last_seen) ? time_buf : ""); + (peer->last_seen) ? time_buf : "", + peer->version, + peer->uptime); sendto(eee->udp_mgmt_sock, udp_buf, msg_len, 0, (struct sockaddr *) &sender_sock, sizeof(struct sockaddr_in)); @@ -1982,7 +1983,7 @@ static void readFromMgmtSocket (n2n_edge_t *eee, int *keep_running) { // further stats msg_len += snprintf((char *) (udp_buf + msg_len), (N2N_PKT_BUF_SIZE - msg_len), - "================================================================================================\n"); + "===================================================================================================================================\n"); msg_len += snprintf((char *) (udp_buf + msg_len), (N2N_PKT_BUF_SIZE - msg_len), "uptime %lu | ", @@ -2797,7 +2798,7 @@ void process_udp (n2n_edge_t *eee, const struct sockaddr_in *sender_sock, const } } - if(!is_valid_peer_sock(&pi.sock)) { + if((cmn.flags & N2N_FLAGS_SOCKET) && !is_valid_peer_sock(&pi.sock)) { traceEvent(TRACE_DEBUG, "skip invalid PEER_INFO from %s [%s]", macaddr_str(mac_buf1, pi.mac), sock_to_cstr(sockbuf1, &pi.sock)); @@ -2811,8 +2812,11 @@ void process_udp (n2n_edge_t *eee, const struct sockaddr_in *sender_sock, const if(scan != NULL) { eee->sn_pong = 1; scan->last_seen = now; + scan->uptime = pi.uptime; + memcpy(scan->version, pi.version, sizeof(n2n_version_t)); /* The data type depends on the actual selection strategy that has been chosen. */ sn_selection_criterion_calculate(eee, scan, &pi.data); + traceEvent(TRACE_INFO, "Rx PONG from supernode %s", macaddr_str(mac_buf1, pi.srcMac)); diff --git a/src/sn_utils.c b/src/sn_utils.c index 3a8a836..448050e 100644 --- a/src/sn_utils.c +++ b/src/sn_utils.c @@ -738,6 +738,7 @@ int sn_init_defaults (n2n_sn_t *sss) { memset(sss, 0, sizeof(n2n_sn_t)); + strncpy(sss->version, GIT_RELEASE, sizeof(n2n_version_t) - 1); sss->daemon = 1; /* By defult run as a daemon. */ sss->lport = N2N_SN_LPORT_DEFAULT; sss->mport = N2N_SN_MGMT_PORT; @@ -2537,6 +2538,9 @@ static int process_udp (n2n_sn_t * sss, memcpy(pi.sock.addr.v4, &(sender_sock->sin_addr.s_addr), IPV4_SIZE); pi.data = sn_selection_criterion_gather_data(sss); + snprintf(pi.version, sizeof(pi.version), "%s", sss->version); + pi.uptime = now - sss->start_time; + encode_PEER_INFO(encbuf, &encx, &cmn2, &pi); if(comm) { diff --git a/src/supernode.c b/src/supernode.c index d60c002..f7450b2 100644 --- a/src/supernode.c +++ b/src/supernode.c @@ -70,6 +70,7 @@ static void help (int level) { "[-m ] " #endif "[-M] " + "[-V ] " "\n\n overlay network " "[-c ] " "\n configuration " @@ -120,6 +121,8 @@ static void help (int level) { #endif printf(" -M | disable MAC and IP address spoofing protection for all\n" " | non-username-password-authenticating communities\n"); + printf(" -V | sends a custom supernode version string of max 19 letters \n" + " | length to edges, visible in their management port output\n"); printf ("\n"); printf (" TAP DEVICE AND OVERLAY NETWORK CONFIGURATION\n"); printf (" --------------------------------------------\n\n"); @@ -290,6 +293,10 @@ static int setOption (int optkey, char *_optarg, n2n_sn_t *sss) { case 'M': /* override spoofing protection */ sss->override_spoofing_protection = 1; break; + + case 'V': /* community file */ + strncpy(sss->version, _optarg, sizeof(n2n_version_t) - 1); /* mind the \0 terminator */ + case 'c': /* community file */ sss->community_file = calloc(1, strlen(_optarg) + 1); if(sss->community_file) @@ -342,7 +349,7 @@ static int loadFromCLI (int argc, char * const argv[], n2n_sn_t *sss) { u_char c; while((c = getopt_long(argc, argv, - "p:l:t:a:c:F:vhM" + "p:l:t:a:c:F:vhMV:" #ifdef SN_MANUAL_MAC "m:" #endif diff --git a/src/wire.c b/src/wire.c index 1579f39..f061952 100644 --- a/src/wire.c +++ b/src/wire.c @@ -664,6 +664,8 @@ int encode_PEER_INFO (uint8_t *base, retval += encode_sock(base, idx, &pkt->preferred_sock); } retval += encode_buf(base, idx, &pkt->data, sizeof(SN_SELECTION_CRITERION_DATA_TYPE)); + retval += encode_uint32(base, idx, (uint32_t)pkt->uptime); + retval += encode_buf(base, idx, pkt->version, sizeof(n2n_version_t)); return retval; } @@ -686,6 +688,8 @@ int decode_PEER_INFO (n2n_PEER_INFO_t *pkt, retval += decode_sock(&pkt->preferred_sock, base, rem, idx); } retval += decode_buf((uint8_t*)&pkt->data, sizeof(SN_SELECTION_CRITERION_DATA_TYPE), base, rem, idx); + retval += decode_uint32((uint32_t*)&pkt->uptime, base, rem, idx); + retval += decode_buf((uint8_t*)pkt->version, sizeof(n2n_version_t), base, rem, idx); return retval; } diff --git a/supernode.1 b/supernode.1 index 013bdc2..5a16c72 100644 --- a/supernode.1 +++ b/supernode.1 @@ -26,22 +26,27 @@ Lines starting with a "#" are ignored. An equal sign ('=') should be used between key and value. Example: -p=7777 .SH OPTIONS FOR THE UNDERLYING NETWORK CONNECTION .TP -\fB\-p \fR<\fIlocal port\fR>, \fB\-\-local-port\fR=<\fIlocal port\fR> +\fB\-p \fR<\fIlocal_port\fR>, \fB\-\-local-port\fR=<\fIlocal_port\fR> listen on this fixed local UDP port, defaults to 7654 .TP -\fB\-F \fR<\fIfed name\fR> +\fB\-F \fR<\fIfed_name\fR> name of the supernode's federation, defaults to '*Federation' .TP \fB\-l \fR<\fIhost:port\fR> ip address or name, and port of known supernode .TP -\fB\-m \fR<\fImac address\fR> +\fB\-m \fR<\fImac_address\fR> fixed MAC address for the supernode, e.g. '-m 10:20:30:40:50:60', random otherwise .TP \fB\-M\fR disable MAC and IP address spoofing protection for all non-username-password-authenticating communities +.TP +\fB\-V \fR<\fIversion_string\fR> +modify the supernode version string which is distributed to the +edges and shown at their management port output, up to 19 characters +.TP .SH TAP DEVICE AND OVERLAY NETWORK CONFIGURATION .TP \fB\-c \fR<\fIpath\fR>, \fB\-\-communities\fR=<\fIpath\fR>