sn_management.c (n2n-3.0) | : | sn_management.c (n2n-3.1.1) | ||
---|---|---|---|---|
/** | /** | |||
* (C) 2007-21 - ntop.org and contributors | * (C) 2007-22 - ntop.org and contributors | |||
* | * | |||
* This program is free software; you can redistribute it and/or modify | * This program is free software; you can redistribute it and/or modify | |||
* it under the terms of the GNU General Public License as published by | * it under the terms of the GNU General Public License as published by | |||
* the Free Software Foundation; either version 3 of the License, or | * the Free Software Foundation; either version 3 of the License, or | |||
* (at your option) any later version. | * (at your option) any later version. | |||
* | * | |||
* This program is distributed in the hope that it will be useful, | * This program is distributed in the hope that it will be useful, | |||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
* GNU General Public License for more details. | * GNU General Public License for more details. | |||
skipping to change at line 29 | skipping to change at line 29 | |||
/* | /* | |||
* This file has a large amount of duplication with the edge_management.c | * This file has a large amount of duplication with the edge_management.c | |||
* code. In the fullness of time, they should both be merged | * code. In the fullness of time, they should both be merged | |||
*/ | */ | |||
#include "n2n.h" | #include "n2n.h" | |||
#include "edge_utils_win32.h" | #include "edge_utils_win32.h" | |||
int load_allowed_sn_community (n2n_sn_t *sss); /* defined in sn_utils.c */ | int load_allowed_sn_community (n2n_sn_t *sss); /* defined in sn_utils.c */ | |||
enum n2n_mgmt_type { | ||||
N2N_MGMT_READ = 0, | ||||
N2N_MGMT_WRITE = 1, | ||||
}; | ||||
#define FLAG_WROK 1 | #define FLAG_WROK 1 | |||
typedef struct n2n_mgmt_handler { | typedef struct mgmt_handler { | |||
int flags; | int flags; | |||
char *cmd; | char *cmd; | |||
char *help; | char *help; | |||
void (*func)(n2n_sn_t *sss, char *udp_buf, struct sockaddr_in sender_sock, e num n2n_mgmt_type type, char *tag, char *argv0, char *argv); | void (*func)(n2n_sn_t *sss, char *udp_buf, struct sockaddr_in sender_sock, e num n2n_mgmt_type type, char *tag, char *argv0, char *argv); | |||
} n2n_mgmt_handler_t; | } mgmt_handler_t; | |||
static void mgmt_error (n2n_sn_t *sss, char *udp_buf, const struct sockaddr_in s ender_sock, char *tag, char *msg) { | static void mgmt_error (n2n_sn_t *sss, char *udp_buf, const struct sockaddr_in s ender_sock, char *tag, char *msg) { | |||
size_t msg_len; | size_t msg_len; | |||
msg_len = snprintf(udp_buf, N2N_PKT_BUF_SIZE, | msg_len = snprintf(udp_buf, N2N_PKT_BUF_SIZE, | |||
"{" | "{" | |||
"\"_tag\":\"%s\"," | "\"_tag\":\"%s\"," | |||
"\"_type\":\"error\"," | "\"_type\":\"error\"," | |||
"\"error\":\"%s\"}\n", | "\"error\":\"%s\"}\n", | |||
tag, | tag, | |||
msg); | msg); | |||
skipping to change at line 265 | skipping to change at line 270 | |||
} | } | |||
} | } | |||
} | } | |||
static void mgmt_unimplemented (n2n_sn_t *sss, char *udp_buf, const struct socka ddr_in sender_sock, enum n2n_mgmt_type type, char *tag, char *argv0, char *argv) { | static void mgmt_unimplemented (n2n_sn_t *sss, char *udp_buf, const struct socka ddr_in sender_sock, enum n2n_mgmt_type type, char *tag, char *argv0, char *argv) { | |||
mgmt_error(sss, udp_buf, sender_sock, tag, "unimplemented"); | mgmt_error(sss, udp_buf, sender_sock, tag, "unimplemented"); | |||
} | } | |||
static void mgmt_help (n2n_sn_t *sss, char *udp_buf, const struct sockaddr_in se nder_sock, enum n2n_mgmt_type type, char *tag, char *argv0, char *argv); | static void mgmt_help (n2n_sn_t *sss, char *udp_buf, const struct sockaddr_in se nder_sock, enum n2n_mgmt_type type, char *tag, char *argv0, char *argv); | |||
n2n_mgmt_handler_t mgmt_handlers[] = { | mgmt_handler_t mgmt_handlers[] = { | |||
{ .cmd = "supernodes", .help = "Reserved for edge", .func = mgmt_unimplement ed}, | { .cmd = "supernodes", .help = "Reserved for edge", .func = mgmt_unimplement ed}, | |||
{ .cmd = "stop", .flags = FLAG_WROK, .help = "Gracefully exit edge", .func = mgmt_stop}, | { .cmd = "stop", .flags = FLAG_WROK, .help = "Gracefully exit edge", .func = mgmt_stop}, | |||
{ .cmd = "verbose", .flags = FLAG_WROK, .help = "Manage verbosity level", .f unc = mgmt_verbose}, | { .cmd = "verbose", .flags = FLAG_WROK, .help = "Manage verbosity level", .f unc = mgmt_verbose}, | |||
{ .cmd = "reload_communities", .flags = FLAG_WROK, .help = "Reloads communit ies and user's public keys", .func = mgmt_reload_communities}, | { .cmd = "reload_communities", .flags = FLAG_WROK, .help = "Reloads communit ies and user's public keys", .func = mgmt_reload_communities}, | |||
{ .cmd = "communities", .help = "List current communities", .func = mgmt_com munities}, | { .cmd = "communities", .help = "List current communities", .func = mgmt_com munities}, | |||
{ .cmd = "edges", .help = "List current edges/peers", .func = mgmt_edges}, | { .cmd = "edges", .help = "List current edges/peers", .func = mgmt_edges}, | |||
{ .cmd = "timestamps", .help = "Event timestamps", .func = mgmt_timestamps}, | { .cmd = "timestamps", .help = "Event timestamps", .func = mgmt_timestamps}, | |||
{ .cmd = "packetstats", .help = "Traffic statistics", .func = mgmt_packetsta ts}, | { .cmd = "packetstats", .help = "Traffic statistics", .func = mgmt_packetsta ts}, | |||
{ .cmd = "help", .flags = FLAG_WROK, .help = "Show JSON commands", .func = m gmt_help}, | { .cmd = "help", .flags = FLAG_WROK, .help = "Show JSON commands", .func = m gmt_help}, | |||
{ .cmd = NULL }, | { .cmd = NULL }, | |||
}; | }; | |||
static void mgmt_help (n2n_sn_t *sss, char *udp_buf, const struct sockaddr_in se nder_sock, enum n2n_mgmt_type type, char *tag, char *argv0, char *argv) { | static void mgmt_help (n2n_sn_t *sss, char *udp_buf, const struct sockaddr_in se nder_sock, enum n2n_mgmt_type type, char *tag, char *argv0, char *argv) { | |||
size_t msg_len; | size_t msg_len; | |||
n2n_mgmt_handler_t *handler; | mgmt_handler_t *handler; | |||
/* | /* | |||
* Even though this command is readonly, we deliberately do not check | * Even though this command is readonly, we deliberately do not check | |||
* the type - allowing help replies to both read and write requests | * the type - allowing help replies to both read and write requests | |||
*/ | */ | |||
for( handler=mgmt_handlers; handler->cmd; handler++ ) { | for( handler=mgmt_handlers; handler->cmd; handler++ ) { | |||
msg_len = snprintf(udp_buf, N2N_PKT_BUF_SIZE, | msg_len = snprintf(udp_buf, N2N_PKT_BUF_SIZE, | |||
"{" | "{" | |||
"\"_tag\":\"%s\"," | "\"_tag\":\"%s\"," | |||
skipping to change at line 328 | skipping to change at line 333 | |||
return 0; | return 0; | |||
} | } | |||
/* if we dont have an auth key, we can still read */ | /* if we dont have an auth key, we can still read */ | |||
if(type == N2N_MGMT_READ) { | if(type == N2N_MGMT_READ) { | |||
return 1; | return 1; | |||
} | } | |||
return 0; | return 0; | |||
} | } | |||
void handleMgmtJson_sn (n2n_sn_t *sss, char *udp_buf, const struct sockaddr_in s ender_sock) { | static void handleMgmtJson (n2n_sn_t *sss, char *udp_buf, const struct sockaddr_ in sender_sock) { | |||
char cmdlinebuf[80]; | char cmdlinebuf[80]; | |||
enum n2n_mgmt_type type; | enum n2n_mgmt_type type; | |||
char *typechar; | char *typechar; | |||
char *options; | char *options; | |||
char *argv0; | char *argv0; | |||
char *argv; | char *argv; | |||
char *tag; | char *tag; | |||
char *flagstr; | char *flagstr; | |||
int flags; | int flags; | |||
char *auth; | char *auth; | |||
n2n_mgmt_handler_t *handler; | mgmt_handler_t *handler; | |||
size_t msg_len; | size_t msg_len; | |||
/* save a copy of the commandline before we reuse the udp_buf */ | /* save a copy of the commandline before we reuse the udp_buf */ | |||
strncpy(cmdlinebuf, udp_buf, sizeof(cmdlinebuf)-1); | strncpy(cmdlinebuf, udp_buf, sizeof(cmdlinebuf)-1); | |||
cmdlinebuf[sizeof(cmdlinebuf)-1] = 0; | cmdlinebuf[sizeof(cmdlinebuf)-1] = 0; | |||
traceEvent(TRACE_DEBUG, "mgmt json %s", cmdlinebuf); | traceEvent(TRACE_DEBUG, "mgmt json %s", cmdlinebuf); | |||
typechar = strtok(cmdlinebuf, " \r\n"); | typechar = strtok(cmdlinebuf, " \r\n"); | |||
if(!typechar) { | if(!typechar) { | |||
skipping to change at line 441 | skipping to change at line 446 | |||
(struct sockaddr *) &sender_sock, sizeof(struct sockaddr_in)); | (struct sockaddr *) &sender_sock, sizeof(struct sockaddr_in)); | |||
handler->func(sss, udp_buf, sender_sock, type, tag, argv0, argv); | handler->func(sss, udp_buf, sender_sock, type, tag, argv0, argv); | |||
msg_len = snprintf(udp_buf, N2N_PKT_BUF_SIZE, | msg_len = snprintf(udp_buf, N2N_PKT_BUF_SIZE, | |||
"{\"_tag\":\"%s\",\"_type\":\"end\"}\n", tag); | "{\"_tag\":\"%s\",\"_type\":\"end\"}\n", tag); | |||
sendto(sss->mgmt_sock, udp_buf, msg_len, 0, | sendto(sss->mgmt_sock, udp_buf, msg_len, 0, | |||
(struct sockaddr *) &sender_sock, sizeof(struct sockaddr_in)); | (struct sockaddr *) &sender_sock, sizeof(struct sockaddr_in)); | |||
return; | return; | |||
} | } | |||
static int sendto_mgmt (n2n_sn_t *sss, | ||||
const struct sockaddr_in *sender_sock, | ||||
const uint8_t *mgmt_buf, | ||||
size_t mgmt_size) { | ||||
ssize_t r = sendto(sss->mgmt_sock, (void *)mgmt_buf, mgmt_size, 0 /*flags*/, | ||||
(struct sockaddr *)sender_sock, sizeof (struct sockaddr_i | ||||
n)); | ||||
if(r <= 0) { | ||||
++(sss->stats.errors); | ||||
traceEvent(TRACE_ERROR, "sendto_mgmt : sendto failed. %s", strerror(errn | ||||
o)); | ||||
return -1; | ||||
} | ||||
return 0; | ||||
} | ||||
int process_mgmt (n2n_sn_t *sss, | ||||
const struct sockaddr_in *sender_sock, | ||||
char *mgmt_buf, | ||||
size_t mgmt_size, | ||||
time_t now) { | ||||
char resbuf[N2N_SN_PKTBUF_SIZE]; | ||||
size_t ressize = 0; | ||||
uint32_t num_edges = 0; | ||||
uint32_t num_comm = 0; | ||||
uint32_t num = 0; | ||||
struct sn_community *community, *tmp; | ||||
struct peer_info *peer, *tmpPeer; | ||||
macstr_t mac_buf; | ||||
n2n_sock_str_t sockbuf; | ||||
char time_buf[10]; /* 9 digits + 1 terminating zero */ | ||||
dec_ip_bit_str_t ip_bit_str = {'\0'}; | ||||
traceEvent(TRACE_DEBUG, "process_mgmt"); | ||||
/* avoid parsing any uninitialized junk from the stack */ | ||||
mgmt_buf[mgmt_size] = 0; | ||||
// process input, if any | ||||
if((0 == memcmp(mgmt_buf, "help", 4)) || (0 == memcmp(mgmt_buf, "?", 1))) { | ||||
ressize += snprintf(resbuf + ressize, N2N_SN_PKTBUF_SIZE - ressize, | ||||
"Help for supernode management console:\n" | ||||
"\thelp | This help message\n" | ||||
"\treload_communities | Reloads communities and us | ||||
er's public keys\n" | ||||
"\t<enter> | Display status and statist | ||||
ics\n"); | ||||
sendto_mgmt(sss, sender_sock, (const uint8_t *) resbuf, ressize); | ||||
return 0; /* no status output afterwards */ | ||||
} | ||||
if(0 == memcmp(mgmt_buf, "reload_communities", 18)) { | ||||
if(!sss->community_file) { | ||||
ressize += snprintf(resbuf + ressize, N2N_SN_PKTBUF_SIZE - ressize, | ||||
"No community file provided (-c command line opt | ||||
ion)\n"); | ||||
sendto_mgmt(sss, sender_sock, (const uint8_t *) resbuf, ressize); | ||||
return 0; /* no status output afterwards */ | ||||
} | ||||
traceEvent(TRACE_NORMAL, "'reload_communities' command"); | ||||
if(load_allowed_sn_community(sss)) { | ||||
ressize += snprintf(resbuf + ressize, N2N_SN_PKTBUF_SIZE - ressize, | ||||
"Error while re-loading community file (not foun | ||||
d or no valid content)\n"); | ||||
sendto_mgmt(sss, sender_sock, (const uint8_t *) resbuf, ressize); | ||||
return 0; /* no status output afterwards */ | ||||
} | ||||
ressize += snprintf(resbuf + ressize, N2N_SN_PKTBUF_SIZE - ressize, | ||||
"OK.\n"); | ||||
sendto_mgmt(sss, sender_sock, (const uint8_t *) resbuf, ressize); | ||||
return 0; /* no status output afterwards */ | ||||
} | ||||
if((mgmt_buf[0] == 'r' || mgmt_buf[0] == 'w') && (mgmt_buf[1] == ' ')) { | ||||
/* this is a JSON request */ | ||||
handleMgmtJson(sss, mgmt_buf, *sender_sock); | ||||
return 0; | ||||
} | ||||
// output current status | ||||
ressize += snprintf(resbuf + ressize, N2N_SN_PKTBUF_SIZE - ressize, | ||||
" ### | TAP | MAC | EDGE | ||||
| HINT | LAST SEEN\n"); | ||||
ressize += snprintf(resbuf + ressize, N2N_SN_PKTBUF_SIZE - ressize, | ||||
"======================================================= | ||||
=================================================\n"); | ||||
HASH_ITER(hh, sss->communities, community, tmp) { | ||||
if(num_comm) | ||||
ressize += snprintf(resbuf + ressize, N2N_SN_PKTBUF_SIZE - ressize, | ||||
"----------------------------------------------- | ||||
---------------------------------------------------------\n"); | ||||
num_comm++; | ||||
num_edges += HASH_COUNT(community->edges); | ||||
ressize += snprintf(resbuf + ressize, N2N_SN_PKTBUF_SIZE - ressize, | ||||
"%s '%s'\n", | ||||
(community->is_federation) ? "FEDERATION" : ((commun | ||||
ity->purgeable == COMMUNITY_UNPURGEABLE) ? "FIXED NAME COMMUNITY" : "COMMUNITY") | ||||
, | ||||
(community->is_federation) ? "-/-" : community->comm | ||||
unity); | ||||
sendto_mgmt(sss, sender_sock, (const uint8_t *) resbuf, ressize); | ||||
ressize = 0; | ||||
num = 0; | ||||
HASH_ITER(hh, community->edges, peer, tmpPeer) { | ||||
sprintf(time_buf, "%9u", (unsigned int)(now - peer->last_seen)); | ||||
ressize += snprintf(resbuf + ressize, N2N_SN_PKTBUF_SIZE - ressize, | ||||
"%4u | %-19s | %-17s | %-21s %-3s | %-15s | %9s\ | ||||
n", | ||||
++num, | ||||
(peer->dev_addr.net_addr == 0) ? ((peer->purgeab | ||||
le == SN_UNPURGEABLE) ? "-l" : "") : ip_subnet_to_str(ip_bit_str, &peer->dev_add | ||||
r), | ||||
(is_null_mac(peer->mac_addr)) ? "" : macaddr_str | ||||
(mac_buf, peer->mac_addr), | ||||
sock_to_cstr(sockbuf, &(peer->sock)), | ||||
((peer->socket_fd >= 0) && (peer->socket_fd != s | ||||
ss->sock)) ? "TCP" : "", | ||||
peer->dev_desc, | ||||
(peer->last_seen) ? time_buf : ""); | ||||
sendto_mgmt(sss, sender_sock, (const uint8_t *) resbuf, ressize); | ||||
ressize = 0; | ||||
} | ||||
} | ||||
ressize += snprintf(resbuf + ressize, N2N_SN_PKTBUF_SIZE - ressize, | ||||
"======================================================= | ||||
=================================================\n"); | ||||
ressize += snprintf(resbuf + ressize, N2N_SN_PKTBUF_SIZE - ressize, | ||||
"uptime %lu | ", (now - sss->start_time)); | ||||
ressize += snprintf(resbuf + ressize, N2N_SN_PKTBUF_SIZE - ressize, | ||||
"edges %u | ", | ||||
num_edges); | ||||
ressize += snprintf(resbuf + ressize, N2N_SN_PKTBUF_SIZE - ressize, | ||||
"reg_sup %u | ", | ||||
(unsigned int) sss->stats.reg_super); | ||||
ressize += snprintf(resbuf + ressize, N2N_SN_PKTBUF_SIZE - ressize, | ||||
"reg_nak %u | ", | ||||
(unsigned int) sss->stats.reg_super_nak); | ||||
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, | ||||
"fwd %u | ", | ||||
(unsigned int) sss->stats.fwd); | ||||
ressize += snprintf(resbuf + ressize, N2N_SN_PKTBUF_SIZE - ressize, | ||||
"broadcast %u | ", | ||||
(unsigned int) sss->stats.broadcast); | ||||
ressize += snprintf(resbuf + ressize, N2N_SN_PKTBUF_SIZE - ressize, | ||||
"cur_cmnts %u\n", HASH_COUNT(sss->communities)); | ||||
ressize += snprintf(resbuf + ressize, N2N_SN_PKTBUF_SIZE - ressize, | ||||
"last_fwd %lu sec ago | ", | ||||
(long unsigned int) (now - sss->stats.last_fwd)); | ||||
ressize += snprintf(resbuf + ressize, N2N_SN_PKTBUF_SIZE - ressize, | ||||
"last reg %lu sec ago\n\n", | ||||
(long unsigned int) (now - sss->stats.last_reg_super)); | ||||
sendto_mgmt(sss, sender_sock, (const uint8_t *) resbuf, ressize); | ||||
return 0; | ||||
} | ||||
End of changes. 9 change blocks. | ||||
7 lines changed or deleted | 12 lines changed or added |