2021-10-23 07:20:05 +02:00
|
|
|
/**
|
2022-03-12 10:22:42 +01:00
|
|
|
* (C) 2007-22 - ntop.org and contributors
|
2021-10-23 07:20:05 +02:00
|
|
|
*
|
|
|
|
* 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
|
|
|
|
* the Free Software Foundation; either version 3 of the License, or
|
|
|
|
* (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program; if not see see <http://www.gnu.org/licenses/>
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "n2n.h"
|
|
|
|
#include "edge_utils_win32.h"
|
|
|
|
|
2022-02-13 13:52:10 +01:00
|
|
|
#include "strbuf.h"
|
2022-04-17 01:19:08 +02:00
|
|
|
#include "management.h"
|
2021-11-28 14:30:10 +01:00
|
|
|
|
2022-02-05 21:03:09 +01:00
|
|
|
size_t event_debug (strbuf_t *buf, char *tag, int data0, void *data1) {
|
2022-02-05 19:39:26 +01:00
|
|
|
traceEvent(TRACE_DEBUG, "Unexpected call to event_debug");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2022-02-05 21:03:09 +01:00
|
|
|
size_t event_test (strbuf_t *buf, char *tag, int data0, void *data1) {
|
|
|
|
size_t msg_len = gen_json_1str(buf, tag, "event", "test", (char *)data1);
|
2022-02-05 19:39:26 +01:00
|
|
|
return msg_len;
|
2021-11-07 17:00:36 +01:00
|
|
|
}
|
|
|
|
|
2022-02-05 21:03:09 +01:00
|
|
|
size_t event_peer (strbuf_t *buf, char *tag, int data0, void *data1) {
|
|
|
|
int action = data0;
|
|
|
|
struct peer_info *peer = (struct peer_info *)data1;
|
|
|
|
|
|
|
|
macstr_t mac_buf;
|
|
|
|
n2n_sock_str_t sockbuf;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Just the peer_info bits that are needed for lookup (maccaddr) or
|
|
|
|
* firewall and routing (sockaddr)
|
|
|
|
* If needed, other details can be fetched via the edges method call.
|
|
|
|
*/
|
|
|
|
return snprintf(buf->str, buf->size,
|
|
|
|
"{"
|
|
|
|
"\"_tag\":\"%s\","
|
|
|
|
"\"_type\":\"event\","
|
|
|
|
"\"action\":%i,"
|
|
|
|
"\"macaddr\":\"%s\","
|
|
|
|
"\"sockaddr\":\"%s\"}\n",
|
|
|
|
tag,
|
|
|
|
action,
|
|
|
|
(is_null_mac(peer->mac_addr)) ? "" : macaddr_str(mac_buf, peer->mac_addr),
|
|
|
|
sock_to_cstr(sockbuf, &(peer->sock)));
|
|
|
|
}
|
|
|
|
|
2021-10-23 07:20:05 +02:00
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2022-04-17 01:19:08 +02:00
|
|
|
static void mgmt_communities (mgmt_req_t *req, strbuf_t *buf) {
|
2021-10-23 07:20:05 +02:00
|
|
|
|
2021-11-06 21:56:19 +01:00
|
|
|
if(req->eee->conf.header_encryption != HEADER_ENCRYPTION_NONE) {
|
2021-11-30 13:38:22 +01:00
|
|
|
mgmt_error(req, buf, "noaccess");
|
2021-10-23 07:20:05 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2021-11-30 13:38:22 +01:00
|
|
|
send_json_1str(req, buf, "row", "community", (char *)req->eee->conf.community_name);
|
2021-10-23 07:20:05 +02:00
|
|
|
}
|
|
|
|
|
2022-04-17 01:19:08 +02:00
|
|
|
static void mgmt_supernodes (mgmt_req_t *req, strbuf_t *buf) {
|
2021-10-23 07:20:05 +02:00
|
|
|
size_t msg_len;
|
|
|
|
struct peer_info *peer, *tmpPeer;
|
|
|
|
macstr_t mac_buf;
|
|
|
|
n2n_sock_str_t sockbuf;
|
|
|
|
selection_criterion_str_t sel_buf;
|
|
|
|
|
2021-11-06 21:56:19 +01:00
|
|
|
HASH_ITER(hh, req->eee->conf.supernodes, peer, tmpPeer) {
|
2021-10-23 07:20:05 +02:00
|
|
|
|
|
|
|
/*
|
|
|
|
* TODO:
|
|
|
|
* The version string provided by the remote supernode could contain
|
|
|
|
* chars that make our JSON invalid.
|
|
|
|
* - do we care?
|
|
|
|
*/
|
|
|
|
|
2021-11-30 13:38:22 +01:00
|
|
|
msg_len = snprintf(buf->str, buf->size,
|
2021-10-23 07:20:05 +02:00
|
|
|
"{"
|
|
|
|
"\"_tag\":\"%s\","
|
|
|
|
"\"_type\":\"row\","
|
|
|
|
"\"version\":\"%s\","
|
|
|
|
"\"purgeable\":%i,"
|
|
|
|
"\"current\":%i,"
|
|
|
|
"\"macaddr\":\"%s\","
|
|
|
|
"\"sockaddr\":\"%s\","
|
|
|
|
"\"selection\":\"%s\","
|
2021-10-24 00:20:36 +02:00
|
|
|
"\"last_seen\":%li,"
|
2021-10-23 07:20:05 +02:00
|
|
|
"\"uptime\":%li}\n",
|
2021-11-06 21:56:19 +01:00
|
|
|
req->tag,
|
2021-10-23 07:20:05 +02:00
|
|
|
peer->version,
|
|
|
|
peer->purgeable,
|
2021-11-06 21:56:19 +01:00
|
|
|
(peer == req->eee->curr_sn) ? (req->eee->sn_wait ? 2 : 1 ) : 0,
|
2021-10-23 07:20:05 +02:00
|
|
|
is_null_mac(peer->mac_addr) ? "" : macaddr_str(mac_buf, peer->mac_addr),
|
|
|
|
sock_to_cstr(sockbuf, &(peer->sock)),
|
2021-11-06 21:56:19 +01:00
|
|
|
sn_selection_criterion_str(req->eee, sel_buf, peer),
|
2021-10-23 07:20:05 +02:00
|
|
|
peer->last_seen,
|
|
|
|
peer->uptime);
|
|
|
|
|
2021-11-30 13:38:22 +01:00
|
|
|
send_reply(req, buf, msg_len);
|
2021-10-23 07:20:05 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-11-30 13:38:22 +01:00
|
|
|
static void mgmt_edges_row (mgmt_req_t *req, strbuf_t *buf, struct peer_info *peer, char *mode) {
|
2021-10-23 07:20:05 +02:00
|
|
|
size_t msg_len;
|
|
|
|
macstr_t mac_buf;
|
|
|
|
n2n_sock_str_t sockbuf;
|
|
|
|
dec_ip_bit_str_t ip_bit_str = {'\0'};
|
|
|
|
|
2021-11-30 13:38:22 +01:00
|
|
|
msg_len = snprintf(buf->str, buf->size,
|
2021-10-23 07:20:05 +02:00
|
|
|
"{"
|
|
|
|
"\"_tag\":\"%s\","
|
|
|
|
"\"_type\":\"row\","
|
|
|
|
"\"mode\":\"%s\","
|
|
|
|
"\"ip4addr\":\"%s\","
|
|
|
|
"\"purgeable\":%i,"
|
2021-10-24 00:20:36 +02:00
|
|
|
"\"local\":%i,"
|
2021-10-23 07:20:05 +02:00
|
|
|
"\"macaddr\":\"%s\","
|
|
|
|
"\"sockaddr\":\"%s\","
|
|
|
|
"\"desc\":\"%s\","
|
2021-10-24 00:20:36 +02:00
|
|
|
"\"last_p2p\":%li,\n"
|
|
|
|
"\"last_sent_query\":%li,\n"
|
2021-10-23 07:20:05 +02:00
|
|
|
"\"last_seen\":%li}\n",
|
2021-11-06 21:56:19 +01:00
|
|
|
req->tag,
|
2021-10-23 07:20:05 +02:00
|
|
|
mode,
|
|
|
|
(peer->dev_addr.net_addr == 0) ? "" : ip_subnet_to_str(ip_bit_str, &peer->dev_addr),
|
|
|
|
peer->purgeable,
|
2021-10-24 00:20:36 +02:00
|
|
|
peer->local,
|
2021-10-23 07:20:05 +02:00
|
|
|
(is_null_mac(peer->mac_addr)) ? "" : macaddr_str(mac_buf, peer->mac_addr),
|
|
|
|
sock_to_cstr(sockbuf, &(peer->sock)),
|
|
|
|
peer->dev_desc,
|
2021-10-24 00:20:36 +02:00
|
|
|
peer->last_p2p,
|
|
|
|
peer->last_sent_query,
|
2021-10-23 07:20:05 +02:00
|
|
|
peer->last_seen);
|
|
|
|
|
2021-11-30 13:38:22 +01:00
|
|
|
send_reply(req, buf, msg_len);
|
2021-10-23 07:20:05 +02:00
|
|
|
}
|
|
|
|
|
2022-04-17 01:19:08 +02:00
|
|
|
static void mgmt_edges (mgmt_req_t *req, strbuf_t *buf) {
|
2021-10-23 07:20:05 +02:00
|
|
|
struct peer_info *peer, *tmpPeer;
|
|
|
|
|
|
|
|
// dump nodes with forwarding through supernodes
|
2021-11-06 21:56:19 +01:00
|
|
|
HASH_ITER(hh, req->eee->pending_peers, peer, tmpPeer) {
|
2021-11-30 13:38:22 +01:00
|
|
|
mgmt_edges_row(req, buf, peer, "pSp");
|
2021-10-23 07:20:05 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// dump peer-to-peer nodes
|
2021-11-06 21:56:19 +01:00
|
|
|
HASH_ITER(hh, req->eee->known_peers, peer, tmpPeer) {
|
2021-11-30 13:38:22 +01:00
|
|
|
mgmt_edges_row(req, buf, peer, "p2p");
|
2021-10-23 07:20:05 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-04-17 01:19:08 +02:00
|
|
|
static void mgmt_timestamps (mgmt_req_t *req, strbuf_t *buf) {
|
2021-10-23 07:20:05 +02:00
|
|
|
size_t msg_len;
|
|
|
|
|
2021-11-30 13:38:22 +01:00
|
|
|
msg_len = snprintf(buf->str, buf->size,
|
2021-10-23 07:20:05 +02:00
|
|
|
"{"
|
|
|
|
"\"_tag\":\"%s\","
|
|
|
|
"\"_type\":\"row\","
|
|
|
|
"\"start_time\":%lu,"
|
|
|
|
"\"last_super\":%ld,"
|
|
|
|
"\"last_p2p\":%ld}\n",
|
2021-11-06 21:56:19 +01:00
|
|
|
req->tag,
|
|
|
|
req->eee->start_time,
|
|
|
|
req->eee->last_sup,
|
|
|
|
req->eee->last_p2p);
|
2021-10-23 07:20:05 +02:00
|
|
|
|
2021-11-30 13:38:22 +01:00
|
|
|
send_reply(req, buf, msg_len);
|
2021-10-23 07:20:05 +02:00
|
|
|
}
|
|
|
|
|
2022-04-17 01:19:08 +02:00
|
|
|
static void mgmt_packetstats (mgmt_req_t *req, strbuf_t *buf) {
|
2021-10-23 07:20:05 +02:00
|
|
|
size_t msg_len;
|
|
|
|
|
2021-11-30 13:38:22 +01:00
|
|
|
msg_len = snprintf(buf->str, buf->size,
|
2021-10-23 07:20:05 +02:00
|
|
|
"{"
|
|
|
|
"\"_tag\":\"%s\","
|
|
|
|
"\"_type\":\"row\","
|
|
|
|
"\"type\":\"transop\","
|
|
|
|
"\"tx_pkt\":%lu,"
|
|
|
|
"\"rx_pkt\":%lu}\n",
|
2021-11-06 21:56:19 +01:00
|
|
|
req->tag,
|
|
|
|
req->eee->transop.tx_cnt,
|
|
|
|
req->eee->transop.rx_cnt);
|
2021-10-23 07:20:05 +02:00
|
|
|
|
2021-11-30 13:38:22 +01:00
|
|
|
send_reply(req, buf, msg_len);
|
2021-10-23 07:20:05 +02:00
|
|
|
|
2021-11-30 13:38:22 +01:00
|
|
|
msg_len = snprintf(buf->str, buf->size,
|
2021-10-23 07:20:05 +02:00
|
|
|
"{"
|
|
|
|
"\"_tag\":\"%s\","
|
|
|
|
"\"_type\":\"row\","
|
|
|
|
"\"type\":\"p2p\","
|
|
|
|
"\"tx_pkt\":%u,"
|
|
|
|
"\"rx_pkt\":%u}\n",
|
2021-11-06 21:56:19 +01:00
|
|
|
req->tag,
|
|
|
|
req->eee->stats.tx_p2p,
|
|
|
|
req->eee->stats.rx_p2p);
|
2021-10-23 07:20:05 +02:00
|
|
|
|
2021-11-30 13:38:22 +01:00
|
|
|
send_reply(req, buf, msg_len);
|
2021-10-23 07:20:05 +02:00
|
|
|
|
2021-11-30 13:38:22 +01:00
|
|
|
msg_len = snprintf(buf->str, buf->size,
|
2021-10-23 07:20:05 +02:00
|
|
|
"{"
|
|
|
|
"\"_tag\":\"%s\","
|
|
|
|
"\"_type\":\"row\","
|
|
|
|
"\"type\":\"super\","
|
|
|
|
"\"tx_pkt\":%u,"
|
|
|
|
"\"rx_pkt\":%u}\n",
|
2021-11-06 21:56:19 +01:00
|
|
|
req->tag,
|
|
|
|
req->eee->stats.tx_sup,
|
|
|
|
req->eee->stats.rx_sup);
|
2021-10-23 07:20:05 +02:00
|
|
|
|
2021-11-30 13:38:22 +01:00
|
|
|
send_reply(req, buf, msg_len);
|
2021-10-23 07:20:05 +02:00
|
|
|
|
2021-11-30 13:38:22 +01:00
|
|
|
msg_len = snprintf(buf->str, buf->size,
|
2021-10-23 07:20:05 +02:00
|
|
|
"{"
|
|
|
|
"\"_tag\":\"%s\","
|
|
|
|
"\"_type\":\"row\","
|
|
|
|
"\"type\":\"super_broadcast\","
|
|
|
|
"\"tx_pkt\":%u,"
|
|
|
|
"\"rx_pkt\":%u}\n",
|
2021-11-06 21:56:19 +01:00
|
|
|
req->tag,
|
|
|
|
req->eee->stats.tx_sup_broadcast,
|
|
|
|
req->eee->stats.rx_sup_broadcast);
|
2021-10-23 07:20:05 +02:00
|
|
|
|
2021-11-30 13:38:22 +01:00
|
|
|
send_reply(req, buf, msg_len);
|
2021-10-23 07:20:05 +02:00
|
|
|
}
|
|
|
|
|
2022-04-17 01:19:08 +02:00
|
|
|
static void mgmt_post_test (mgmt_req_t *req, strbuf_t *buf) {
|
2022-02-05 19:39:26 +01:00
|
|
|
|
|
|
|
send_json_1str(req, buf, "row", "sending", "test");
|
2022-04-17 01:19:08 +02:00
|
|
|
mgmt_event_post(N2N_EVENT_TEST, -1, req->argv);
|
2021-10-23 07:20:05 +02:00
|
|
|
}
|
|
|
|
|
2021-11-07 17:00:36 +01:00
|
|
|
// Forward define so we can include this in the mgmt_handlers[] table
|
2022-04-17 01:19:08 +02:00
|
|
|
static void mgmt_help (mgmt_req_t *req, strbuf_t *buf);
|
|
|
|
static void mgmt_help_events (mgmt_req_t *req, strbuf_t *buf);
|
2021-10-23 07:20:05 +02:00
|
|
|
|
2021-11-07 20:19:36 +01:00
|
|
|
static const mgmt_handler_t mgmt_handlers[] = {
|
2021-10-23 07:20:05 +02:00
|
|
|
{ .cmd = "reload_communities", .flags = FLAG_WROK, .help = "Reserved for supernode", .func = mgmt_unimplemented},
|
|
|
|
|
|
|
|
{ .cmd = "stop", .flags = FLAG_WROK, .help = "Gracefully exit edge", .func = mgmt_stop},
|
|
|
|
{ .cmd = "verbose", .flags = FLAG_WROK, .help = "Manage verbosity level", .func = mgmt_verbose},
|
|
|
|
{ .cmd = "communities", .help = "Show current community", .func = mgmt_communities},
|
|
|
|
{ .cmd = "edges", .help = "List current edges/peers", .func = mgmt_edges},
|
|
|
|
{ .cmd = "supernodes", .help = "List current supernodes", .func = mgmt_supernodes},
|
|
|
|
{ .cmd = "timestamps", .help = "Event timestamps", .func = mgmt_timestamps},
|
|
|
|
{ .cmd = "packetstats", .help = "traffic counters", .func = mgmt_packetstats},
|
2022-02-05 19:39:26 +01:00
|
|
|
{ .cmd = "post.test", .help = "send a test event", .func = mgmt_post_test},
|
2021-10-23 07:20:05 +02:00
|
|
|
{ .cmd = "help", .flags = FLAG_WROK, .help = "Show JSON commands", .func = mgmt_help},
|
2021-11-28 13:10:17 +01:00
|
|
|
{ .cmd = "help.events", .help = "Show available Subscribe topics", .func = mgmt_help_events},
|
2021-11-07 17:00:36 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
/* Current subscriber for each event topic */
|
2021-11-28 13:10:17 +01:00
|
|
|
static mgmt_req_t mgmt_event_subscribers[] = {
|
2022-02-05 19:39:26 +01:00
|
|
|
[N2N_EVENT_DEBUG] = { .eee = NULL, .type = N2N_MGMT_UNKNOWN, .tag = "\0" },
|
|
|
|
[N2N_EVENT_TEST] = { .eee = NULL, .type = N2N_MGMT_UNKNOWN, .tag = "\0" },
|
2022-02-05 21:03:09 +01:00
|
|
|
[N2N_EVENT_PEER] = { .eee = NULL, .type = N2N_MGMT_UNKNOWN, .tag = "\0" },
|
2021-11-28 13:10:17 +01:00
|
|
|
};
|
2021-11-07 17:00:36 +01:00
|
|
|
|
|
|
|
/* Map topic number to function */
|
2022-04-17 01:19:08 +02:00
|
|
|
// TODO: want this to be const
|
|
|
|
static mgmt_event_handler_t *mgmt_events[] = {
|
2022-02-05 19:39:26 +01:00
|
|
|
[N2N_EVENT_DEBUG] = event_debug,
|
|
|
|
[N2N_EVENT_TEST] = event_test,
|
2022-02-05 21:03:09 +01:00
|
|
|
[N2N_EVENT_PEER] = event_peer,
|
2021-11-07 17:00:36 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
/* Allow help and subscriptions to use topic name */
|
2021-11-28 13:10:17 +01:00
|
|
|
static const mgmt_events_t mgmt_event_names[] = {
|
2022-02-05 19:39:26 +01:00
|
|
|
{ .cmd = "debug", .topic = N2N_EVENT_DEBUG, .help = "All events - for event debugging"},
|
|
|
|
{ .cmd = "test", .topic = N2N_EVENT_TEST, .help = "Used only by post.test"},
|
2022-02-05 21:03:09 +01:00
|
|
|
{ .cmd = "peer", .topic = N2N_EVENT_PEER, .help = "Changes to peer list"},
|
2021-10-23 07:20:05 +02:00
|
|
|
};
|
|
|
|
|
2022-02-05 21:03:09 +01:00
|
|
|
void mgmt_event_post (enum n2n_event_topic topic, int data0, void *data1) {
|
2022-02-05 19:39:26 +01:00
|
|
|
mgmt_req_t *debug = &mgmt_event_subscribers[N2N_EVENT_DEBUG];
|
|
|
|
mgmt_req_t *sub = &mgmt_event_subscribers[topic];
|
2022-04-17 01:19:08 +02:00
|
|
|
mgmt_event_handler_t *fn = mgmt_events[topic];
|
2022-02-05 19:39:26 +01:00
|
|
|
|
2022-04-17 01:19:08 +02:00
|
|
|
mgmt_event_post2 (topic, data0, data1, debug, sub, fn);
|
2022-02-05 19:39:26 +01:00
|
|
|
}
|
|
|
|
|
2022-04-17 01:19:08 +02:00
|
|
|
static void mgmt_help_events (mgmt_req_t *req, strbuf_t *buf) {
|
2021-11-28 13:10:17 +01:00
|
|
|
int i;
|
|
|
|
int nr_handlers = sizeof(mgmt_event_names) / sizeof(mgmt_events_t);
|
|
|
|
for( i=0; i < nr_handlers; i++ ) {
|
|
|
|
int topic = mgmt_event_names[i].topic;
|
|
|
|
mgmt_req_t *sub = &mgmt_event_subscribers[topic];
|
|
|
|
|
2022-04-17 01:19:08 +02:00
|
|
|
mgmt_help_events_row(req, buf, sub, mgmt_event_names[i].cmd, mgmt_event_names[i].help);
|
2021-11-28 13:10:17 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-04-17 01:19:08 +02:00
|
|
|
// TODO: want to keep the mgmt_handlers defintion const static, otherwise
|
|
|
|
// this whole function could be shared
|
|
|
|
static void mgmt_help (mgmt_req_t *req, strbuf_t *buf) {
|
2021-10-23 07:20:05 +02:00
|
|
|
/*
|
|
|
|
* Even though this command is readonly, we deliberately do not check
|
|
|
|
* the type - allowing help replies to both read and write requests
|
|
|
|
*/
|
|
|
|
|
2021-11-07 20:19:36 +01:00
|
|
|
int i;
|
|
|
|
int nr_handlers = sizeof(mgmt_handlers) / sizeof(mgmt_handler_t);
|
|
|
|
for( i=0; i < nr_handlers; i++ ) {
|
2022-04-17 01:19:08 +02:00
|
|
|
mgmt_help_row(req, buf, mgmt_handlers[i].cmd, mgmt_handlers[i].help);
|
2021-10-23 07:20:05 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-11-06 21:56:19 +01:00
|
|
|
static void handleMgmtJson (mgmt_req_t *req, char *udp_buf, const int recvlen) {
|
2021-10-23 07:20:05 +02:00
|
|
|
|
2021-11-30 13:38:22 +01:00
|
|
|
strbuf_t *buf;
|
2021-10-23 07:20:05 +02:00
|
|
|
char cmdlinebuf[80];
|
2021-11-07 16:16:10 +01:00
|
|
|
|
2021-10-23 07:20:05 +02:00
|
|
|
/* save a copy of the commandline before we reuse the udp_buf */
|
|
|
|
strncpy(cmdlinebuf, udp_buf, sizeof(cmdlinebuf)-1);
|
|
|
|
cmdlinebuf[sizeof(cmdlinebuf)-1] = 0;
|
|
|
|
|
|
|
|
traceEvent(TRACE_DEBUG, "mgmt json %s", cmdlinebuf);
|
|
|
|
|
2021-11-30 13:38:22 +01:00
|
|
|
/* we reuse the buffer already on the stack for all our strings */
|
|
|
|
STRBUF_INIT(buf, udp_buf);
|
|
|
|
|
2022-04-17 01:19:08 +02:00
|
|
|
mgmt_req_init2(req, buf, (char *)&cmdlinebuf);
|
2021-10-23 07:20:05 +02:00
|
|
|
|
2021-11-28 13:10:17 +01:00
|
|
|
if(req->type == N2N_MGMT_SUB) {
|
2022-02-05 19:39:26 +01:00
|
|
|
int handler;
|
2022-04-17 01:19:08 +02:00
|
|
|
lookup_handler(handler, mgmt_event_names, req->argv0);
|
2022-02-05 19:39:26 +01:00
|
|
|
if(handler == -1) {
|
|
|
|
mgmt_error(req, buf, "unknowntopic");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
int topic = mgmt_event_names[handler].topic;
|
|
|
|
if(mgmt_event_subscribers[topic].type == N2N_MGMT_SUB) {
|
|
|
|
send_json_1str(&mgmt_event_subscribers[topic], buf,
|
2022-04-17 01:19:08 +02:00
|
|
|
"unsubscribed", "topic", req->argv0);
|
|
|
|
send_json_1str(req, buf, "replacing", "topic", req->argv0);
|
2022-02-05 19:39:26 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
memcpy(&mgmt_event_subscribers[topic], req, sizeof(*req));
|
|
|
|
|
2022-04-17 01:19:08 +02:00
|
|
|
send_json_1str(req, buf, "subscribe", "topic", req->argv0);
|
2021-11-28 13:10:17 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2021-11-07 20:19:36 +01:00
|
|
|
int handler;
|
2022-04-17 01:19:08 +02:00
|
|
|
lookup_handler(handler, mgmt_handlers, req->argv0);
|
2021-11-28 13:47:13 +01:00
|
|
|
if(handler == -1) {
|
2021-11-30 13:38:22 +01:00
|
|
|
mgmt_error(req, buf, "unknowncmd");
|
2021-10-23 07:20:05 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2021-11-07 20:19:36 +01:00
|
|
|
if((req->type==N2N_MGMT_WRITE) && !(mgmt_handlers[handler].flags & FLAG_WROK)) {
|
2021-11-30 13:38:22 +01:00
|
|
|
mgmt_error(req, buf, "readonly");
|
2021-10-23 07:20:05 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* TODO:
|
|
|
|
* The tag provided by the requester could contain chars
|
|
|
|
* that make our JSON invalid.
|
|
|
|
* - do we care?
|
|
|
|
*/
|
2022-04-17 01:19:08 +02:00
|
|
|
send_json_1str(req, buf, "begin", "cmd", req->argv0);
|
2021-10-23 07:20:05 +02:00
|
|
|
|
2022-04-17 01:19:08 +02:00
|
|
|
mgmt_handlers[handler].func(req, buf);
|
2021-10-23 07:20:05 +02:00
|
|
|
|
2022-04-17 01:19:08 +02:00
|
|
|
send_json_1str(req, buf, "end", "cmd", req->argv0);
|
2021-10-23 07:20:05 +02:00
|
|
|
return;
|
|
|
|
}
|
2021-11-06 20:46:41 +01:00
|
|
|
|
|
|
|
/** Read a datagram from the management UDP socket and take appropriate
|
|
|
|
* action. */
|
|
|
|
void readFromMgmtSocket (n2n_edge_t *eee) {
|
|
|
|
|
|
|
|
char udp_buf[N2N_PKT_BUF_SIZE]; /* Compete UDP packet */
|
|
|
|
ssize_t recvlen;
|
|
|
|
/* ssize_t sendlen; */
|
2021-11-06 21:56:19 +01:00
|
|
|
mgmt_req_t req;
|
2021-11-06 20:46:41 +01:00
|
|
|
socklen_t i;
|
|
|
|
size_t msg_len;
|
|
|
|
time_t now;
|
|
|
|
struct peer_info *peer, *tmpPeer;
|
|
|
|
macstr_t mac_buf;
|
|
|
|
char time_buf[10]; /* 9 digits + 1 terminating zero */
|
|
|
|
char uptime_buf[11]; /* 10 digits + 1 terminating zero */
|
|
|
|
/* dec_ip_bit_str_t ip_bit_str = {'\0'}; */
|
|
|
|
/* dec_ip_str_t ip_str = {'\0'}; */
|
|
|
|
in_addr_t net;
|
|
|
|
n2n_sock_str_t sockbuf;
|
|
|
|
uint32_t num_pending_peers = 0;
|
|
|
|
uint32_t num_known_peers = 0;
|
|
|
|
uint32_t num = 0;
|
|
|
|
selection_criterion_str_t sel_buf;
|
|
|
|
|
2022-04-17 01:19:08 +02:00
|
|
|
req.sss = NULL;
|
2021-11-06 21:56:19 +01:00
|
|
|
req.eee = eee;
|
2022-04-17 01:19:08 +02:00
|
|
|
req.mgmt_sock = eee->udp_mgmt_sock;
|
|
|
|
req.keep_running = eee->keep_running;
|
|
|
|
req.mgmt_password_hash = eee->conf.mgmt_password_hash;
|
2021-11-06 20:46:41 +01:00
|
|
|
|
|
|
|
now = time(NULL);
|
2021-11-06 21:56:19 +01:00
|
|
|
i = sizeof(req.sender_sock);
|
2021-11-06 20:46:41 +01:00
|
|
|
recvlen = recvfrom(eee->udp_mgmt_sock, udp_buf, N2N_PKT_BUF_SIZE, 0 /*flags*/,
|
2021-11-06 21:56:19 +01:00
|
|
|
(struct sockaddr *) &req.sender_sock, (socklen_t *) &i);
|
2021-11-06 20:46:41 +01:00
|
|
|
|
|
|
|
if(recvlen < 0) {
|
|
|
|
traceEvent(TRACE_WARNING, "mgmt recvfrom failed: %d - %s", errno, strerror(errno));
|
|
|
|
return; /* failed to receive data from UDP */
|
|
|
|
}
|
|
|
|
|
|
|
|
/* avoid parsing any uninitialized junk from the stack */
|
|
|
|
udp_buf[recvlen] = 0;
|
|
|
|
|
|
|
|
if((0 == memcmp(udp_buf, "help", 4)) || (0 == memcmp(udp_buf, "?", 1))) {
|
2021-11-30 13:38:22 +01:00
|
|
|
strbuf_t *buf;
|
|
|
|
STRBUF_INIT(buf, &udp_buf);
|
|
|
|
msg_len = snprintf(buf->str, buf->size,
|
|
|
|
"Help for edge management console:\n"
|
|
|
|
"\tstop | Gracefully exit edge\n"
|
|
|
|
"\thelp | This help message\n"
|
|
|
|
"\t+verb | Increase verbosity of logging\n"
|
|
|
|
"\t-verb | Decrease verbosity of logging\n"
|
|
|
|
"\tr ... | start query with JSON reply\n"
|
|
|
|
"\tw ... | start update with JSON reply\n"
|
|
|
|
"\ts ... | subscribe to event channel JSON reply\n"
|
|
|
|
"\t<enter> | Display statistics\n\n");
|
|
|
|
|
|
|
|
send_reply(&req, buf, msg_len);
|
2021-11-06 20:46:41 +01:00
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(0 == memcmp(udp_buf, "stop", 4)) {
|
|
|
|
traceEvent(TRACE_NORMAL, "stop command received");
|
|
|
|
*eee->keep_running = 0;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(0 == memcmp(udp_buf, "+verb", 5)) {
|
|
|
|
setTraceLevel(getTraceLevel() + 1);
|
|
|
|
|
|
|
|
traceEvent(TRACE_NORMAL, "+verb traceLevel=%u", (unsigned int) getTraceLevel());
|
|
|
|
|
2021-11-30 13:38:22 +01:00
|
|
|
strbuf_t *buf;
|
|
|
|
STRBUF_INIT(buf, &udp_buf);
|
|
|
|
msg_len = snprintf(buf->str, buf->size,
|
|
|
|
"> +OK traceLevel=%u\n", (unsigned int) getTraceLevel());
|
|
|
|
|
|
|
|
send_reply(&req, buf, msg_len);
|
2021-11-06 20:46:41 +01:00
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(0 == memcmp(udp_buf, "-verb", 5)) {
|
2021-11-30 13:38:22 +01:00
|
|
|
strbuf_t *buf;
|
|
|
|
STRBUF_INIT(buf, &udp_buf);
|
2021-11-06 20:46:41 +01:00
|
|
|
|
|
|
|
if(getTraceLevel() > 0) {
|
|
|
|
setTraceLevel(getTraceLevel() - 1);
|
2021-11-30 13:38:22 +01:00
|
|
|
msg_len = snprintf(buf->str, buf->size,
|
|
|
|
"> -OK traceLevel=%u\n", getTraceLevel());
|
2021-11-06 20:46:41 +01:00
|
|
|
} else {
|
2021-11-30 13:38:22 +01:00
|
|
|
msg_len = snprintf(buf->str, buf->size,
|
|
|
|
"> -NOK traceLevel=%u\n", getTraceLevel());
|
2021-11-06 20:46:41 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
traceEvent(TRACE_NORMAL, "-verb traceLevel=%u", (unsigned int) getTraceLevel());
|
|
|
|
|
2021-11-30 13:38:22 +01:00
|
|
|
send_reply(&req, buf, msg_len);
|
2021-11-06 20:46:41 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2021-11-07 17:00:36 +01:00
|
|
|
if((udp_buf[0] >= 'a' && udp_buf[0] <= 'z') && (udp_buf[1] == ' ')) {
|
2021-11-06 20:46:41 +01:00
|
|
|
/* this is a JSON request */
|
2021-11-06 21:56:19 +01:00
|
|
|
handleMgmtJson(&req, udp_buf, recvlen);
|
2021-11-06 20:46:41 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
traceEvent(TRACE_DEBUG, "mgmt status requested");
|
|
|
|
|
|
|
|
msg_len = 0;
|
|
|
|
msg_len += snprintf((char *) (udp_buf + msg_len), (N2N_PKT_BUF_SIZE - msg_len),
|
|
|
|
"COMMUNITY '%s'\n\n",
|
|
|
|
(eee->conf.header_encryption == HEADER_ENCRYPTION_NONE) ? (char*)eee->conf.community_name : "-- header encrypted --");
|
|
|
|
msg_len += snprintf((char *) (udp_buf + msg_len), (N2N_PKT_BUF_SIZE - msg_len),
|
|
|
|
" ### | TAP | MAC | EDGE | HINT | LAST SEEN | UPTIME\n");
|
|
|
|
msg_len += snprintf((char *) (udp_buf + msg_len), (N2N_PKT_BUF_SIZE - msg_len),
|
|
|
|
"=============================================================================================================\n");
|
|
|
|
|
|
|
|
// dump nodes with forwarding through supernodes
|
|
|
|
msg_len += snprintf((char *) (udp_buf + msg_len), (N2N_PKT_BUF_SIZE - msg_len),
|
|
|
|
"SUPERNODE FORWARD\n");
|
|
|
|
num = 0;
|
|
|
|
HASH_ITER(hh, eee->pending_peers, peer, tmpPeer) {
|
|
|
|
++num_pending_peers;
|
|
|
|
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",
|
|
|
|
++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),
|
|
|
|
sock_to_cstr(sockbuf, &(peer->sock)),
|
|
|
|
peer->dev_desc,
|
|
|
|
(peer->last_seen) ? time_buf : "");
|
|
|
|
|
2021-11-30 13:38:22 +01:00
|
|
|
sendto(eee->udp_mgmt_sock, udp_buf, msg_len, 0,
|
|
|
|
(struct sockaddr *) &req.sender_sock, sizeof(struct sockaddr_in));
|
2021-11-06 20:46:41 +01:00
|
|
|
msg_len = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
// dump peer-to-peer nodes
|
|
|
|
msg_len += snprintf((char *) (udp_buf + msg_len), (N2N_PKT_BUF_SIZE - msg_len),
|
|
|
|
"-------------------------------------------------------------------------------------------------------------\n");
|
|
|
|
msg_len += snprintf((char *) (udp_buf + msg_len), (N2N_PKT_BUF_SIZE - msg_len),
|
|
|
|
"PEER TO PEER\n");
|
|
|
|
num = 0;
|
|
|
|
HASH_ITER(hh, eee->known_peers, peer, tmpPeer) {
|
|
|
|
++num_known_peers;
|
|
|
|
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",
|
|
|
|
++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),
|
|
|
|
sock_to_cstr(sockbuf, &(peer->sock)),
|
|
|
|
peer->dev_desc,
|
|
|
|
(peer->last_seen) ? time_buf : "");
|
|
|
|
|
2021-11-30 13:38:22 +01:00
|
|
|
sendto(eee->udp_mgmt_sock, udp_buf, msg_len, 0,
|
|
|
|
(struct sockaddr *) &req.sender_sock, sizeof(struct sockaddr_in));
|
2021-11-06 20:46:41 +01:00
|
|
|
msg_len = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
// dump supernodes
|
|
|
|
msg_len += snprintf((char *) (udp_buf + msg_len), (N2N_PKT_BUF_SIZE - msg_len),
|
|
|
|
"-------------------------------------------------------------------------------------------------------------\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));
|
|
|
|
snprintf(uptime_buf, sizeof(uptime_buf), "%10u", (unsigned int)(peer->uptime));
|
|
|
|
msg_len += snprintf((char *) (udp_buf + msg_len), (N2N_PKT_BUF_SIZE - msg_len),
|
|
|
|
"%-19s %1s%1s | %-17s | %-21s | %-15s | %9s | %10s\n",
|
|
|
|
peer->version,
|
|
|
|
(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(eee, sel_buf, peer),
|
|
|
|
(peer->last_seen) ? time_buf : "",
|
|
|
|
(peer->uptime) ? uptime_buf : "");
|
|
|
|
|
2021-11-30 13:38:22 +01:00
|
|
|
sendto(eee->udp_mgmt_sock, udp_buf, msg_len, 0,
|
|
|
|
(struct sockaddr *) &req.sender_sock, sizeof(struct sockaddr_in));
|
2021-11-06 20:46:41 +01:00
|
|
|
msg_len = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
// further stats
|
|
|
|
msg_len += snprintf((char *) (udp_buf + msg_len), (N2N_PKT_BUF_SIZE - msg_len),
|
|
|
|
"=============================================================================================================\n");
|
|
|
|
|
|
|
|
msg_len += snprintf((char *) (udp_buf + msg_len), (N2N_PKT_BUF_SIZE - msg_len),
|
|
|
|
"uptime %lu | ",
|
|
|
|
time(NULL) - eee->start_time);
|
|
|
|
|
|
|
|
msg_len += snprintf((char *) (udp_buf + msg_len), (N2N_PKT_BUF_SIZE - msg_len),
|
|
|
|
"pend_peers %u | ",
|
|
|
|
num_pending_peers);
|
|
|
|
|
|
|
|
msg_len += snprintf((char *) (udp_buf + msg_len), (N2N_PKT_BUF_SIZE - msg_len),
|
|
|
|
"known_peers %u | ",
|
|
|
|
num_known_peers);
|
|
|
|
|
|
|
|
msg_len += snprintf((char *) (udp_buf + msg_len), (N2N_PKT_BUF_SIZE - msg_len),
|
|
|
|
"transop %u,%u\n",
|
|
|
|
(unsigned int) eee->transop.tx_cnt,
|
|
|
|
(unsigned int) eee->transop.rx_cnt);
|
|
|
|
|
|
|
|
msg_len += snprintf((char *) (udp_buf + msg_len), (N2N_PKT_BUF_SIZE - msg_len),
|
|
|
|
"super %u,%u | ",
|
|
|
|
(unsigned int) eee->stats.tx_sup,
|
|
|
|
(unsigned int) eee->stats.rx_sup);
|
|
|
|
|
|
|
|
msg_len += snprintf((char *) (udp_buf + msg_len), (N2N_PKT_BUF_SIZE - msg_len),
|
|
|
|
"p2p %u,%u\n",
|
|
|
|
(unsigned int) eee->stats.tx_p2p,
|
|
|
|
(unsigned int) eee->stats.rx_p2p);
|
|
|
|
|
|
|
|
msg_len += snprintf((char *) (udp_buf + msg_len), (N2N_PKT_BUF_SIZE - msg_len),
|
|
|
|
"last_super %ld sec ago | ",
|
|
|
|
(now - eee->last_sup));
|
|
|
|
|
|
|
|
msg_len += snprintf((char *) (udp_buf + msg_len), (N2N_PKT_BUF_SIZE - msg_len),
|
|
|
|
"last_p2p %ld sec ago\n",
|
|
|
|
(now - eee->last_p2p));
|
|
|
|
|
|
|
|
msg_len += snprintf((char *) (udp_buf + msg_len), (N2N_PKT_BUF_SIZE - msg_len),
|
|
|
|
"\nType \"help\" to see more commands.\n\n");
|
|
|
|
|
2021-11-30 13:38:22 +01:00
|
|
|
sendto(eee->udp_mgmt_sock, udp_buf, msg_len, 0,
|
|
|
|
(struct sockaddr *) &req.sender_sock, sizeof(struct sockaddr_in));
|
2021-11-06 20:46:41 +01:00
|
|
|
}
|