Add new mdp trace command

This commit is contained in:
Jeremy Lakeman 2013-02-18 14:31:01 +10:30
parent 9e9f93b079
commit bb8b3d6376
6 changed files with 159 additions and 20 deletions

View File

@ -43,6 +43,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#include "mdp_client.h"
#include "cli.h"
#include "overlay_address.h"
#include "overlay_buffer.h"
extern struct cli_schema command_line_options[];
@ -1070,6 +1071,68 @@ int app_mdp_ping(const struct cli_parsed *parsed, void *context)
return ret;
}
int app_trace(const struct cli_parsed *parsed, void *context){
const char *sidhex;
if (cli_arg(parsed, "SID", &sidhex, str_is_subscriber_id, NULL) == -1)
return -1;
sid_t srcsid;
sid_t dstsid;
if (str_to_sid_t(&dstsid, sidhex) == -1)
return WHY("str_to_sid_t() failed");
overlay_mdp_frame mdp;
bzero(&mdp, sizeof(mdp));
int port=32768+(random()&32767);
if (overlay_mdp_getmyaddr(0, &srcsid)) return WHY("Could not get local address");
if (overlay_mdp_bind(&srcsid, port)) return WHY("Could not bind to MDP socket");
bcopy(srcsid.binary, mdp.out.src.sid, SID_SIZE);
bcopy(srcsid.binary, mdp.out.dst.sid, SID_SIZE);
mdp.out.src.port=port;
mdp.out.dst.port=MDP_PORT_TRACE;
mdp.packetTypeAndFlags=MDP_TX;
struct overlay_buffer *b = ob_static(mdp.out.payload, sizeof(mdp.out.payload));
ob_append_byte(b, SID_SIZE);
ob_append_bytes(b, srcsid.binary, SID_SIZE);
ob_append_byte(b, SID_SIZE);
ob_append_bytes(b, dstsid.binary, SID_SIZE);
mdp.out.payload_length = ob_position(b);
cli_printf("Tracing the network path from %s to %s",
alloca_tohex_sid(srcsid.binary), alloca_tohex_sid(dstsid.binary));
cli_delim("\n");
int ret=overlay_mdp_send(&mdp,MDP_AWAITREPLY,5000);
ob_free(b);
if (ret)
DEBUGF("overlay_mdp_send returned %d", ret);
else{
int offset=0;
{
// skip the first two sid's
int len = mdp.out.payload[offset++];
offset+=len;
len = mdp.out.payload[offset++];
offset+=len;
}
int i=0;
while(offset<mdp.out.payload_length){
int len = mdp.out.payload[offset++];
cli_printf("%d: ",i);
cli_puts(alloca_tohex(&mdp.out.payload[offset], len));
cli_delim("\n");
offset+=len;
i++;
}
}
overlay_mdp_client_done();
return ret;
}
int app_config_schema(const struct cli_parsed *parsed, void *context)
{
if (config.debug.verbose)
@ -2216,8 +2279,10 @@ struct cli_schema command_line_options[]={
"Stop a running Serval Mesh node process with given instance path."},
{app_server_status,{"status",NULL},CLIFLAG_PERMISSIVE_CONFIG,
"Display information about any running Serval Mesh node."},
{app_mdp_ping,{"mdp","ping","<SID|broadcast>","[<count>]",NULL},CLIFLAG_STANDALONE,
{app_mdp_ping,{"mdp","ping","<SID|broadcast>","[<count>]",NULL},0,
"Attempts to ping specified node via Mesh Datagram Protocol (MDP)."},
{app_trace,{"mdp","trace","<SID>",NULL},0,
"Trace through the network to the specified node via MDP."},
{app_config_schema,{"config","schema",NULL},CLIFLAG_STANDALONE|CLIFLAG_PERMISSIVE_CONFIG,
"Dump configuration schema."},
{app_config_set,{"config","set","<variable>","<value>","...",NULL},CLIFLAG_STANDALONE|CLIFLAG_PERMISSIVE_CONFIG,

View File

@ -132,6 +132,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#define MDP_PORT_STUN 5
#define MDP_PORT_PROBE 6
#define MDP_PORT_ECHO 7
#define MDP_PORT_TRACE 8
#define MDP_PORT_DNALOOKUP 10
#define MDP_PORT_VOMP 12
#define MDP_PORT_RHIZOME_REQUEST 13

View File

@ -63,7 +63,7 @@ int overlay_mdp_send(overlay_mdp_frame *mdp,int flags,int timeout_ms)
int port=0;
if ((mdp->packetTypeAndFlags&MDP_TYPE_MASK) == MDP_TX)
port = mdp->out.dst.port;
port = mdp->out.src.port;
time_ms_t started = gettime_ms();
while(timeout_ms>=0 && overlay_mdp_client_poll(timeout_ms)>0){

View File

@ -502,6 +502,9 @@ int overlay_mdp_dnalookup_reply(const sockaddr_mdp *dstaddr, const unsigned char
int overlay_mdp_check_binding(struct subscriber *subscriber, int port, int userGeneratedFrameP,
struct sockaddr_un *recvaddr, int recvaddrlen)
{
/* System generated frames can send anything they want */
if (!userGeneratedFrameP)
return 0;
/* Check if the address is in the list of bound addresses,
and that the recvaddr matches. */
@ -521,24 +524,6 @@ int overlay_mdp_check_binding(struct subscriber *subscriber, int port, int userG
}
}
/* Check for build-in port listeners */
if (!userGeneratedFrameP){
switch(port) {
case MDP_PORT_NOREPLY:
case MDP_PORT_ECHO:
case MDP_PORT_KEYMAPREQUEST:
case MDP_PORT_VOMP:
case MDP_PORT_DNALOOKUP:
case MDP_PORT_RHIZOME_RESPONSE:
case MDP_PORT_RHIZOME_REQUEST:
case MDP_PORT_RHIZOME_MANIFEST_REQUEST:
case MDP_PORT_PROBE:
case MDP_PORT_STUNREQ:
case MDP_PORT_STUN:
return 0;
}
}
return WHYF("No such binding: recvaddr=%p %s addr=%s port=%u (0x%x) -- possible spoofing attack",
recvaddr,
recvaddr ? alloca_toprint(-1, recvaddr->sun_path, recvaddrlen - sizeof(short)) : "",

View File

@ -281,6 +281,91 @@ int overlay_mdp_service_echo(overlay_mdp_frame *mdp)
RETURN(0);
}
static int overlay_mdp_service_trace(overlay_mdp_frame *mdp){
IN();
int ret=0;
struct overlay_buffer *b = ob_static(mdp->out.payload, sizeof(mdp->out.payload));
ob_limitsize(b, mdp->out.payload_length);
struct subscriber *src=NULL, *dst=NULL, *last=NULL, *next=NULL;
struct decode_context context;
bzero(&context, sizeof context);
if (overlay_address_parse(&context, b, &src)){
ret=WHYF("Invalid trace packet");
goto end;
}
if (overlay_address_parse(&context, b, &dst)){
ret=WHYF("Invalid trace packet");
goto end;
}
if (context.invalid_addresses){
ret=WHYF("Invalid address in trace packet");
goto end;
}
INFOF("Trace from %s to %s", alloca_tohex_sid(src->sid), alloca_tohex_sid(dst->sid));
while(ob_remaining(b)>0){
struct subscriber *trace=NULL;
if (overlay_address_parse(&context, b, &trace)){
ret=WHYF("Invalid trace packet");
goto end;
}
if (context.invalid_addresses){
ret=WHYF("Invalid address in trace packet");
goto end;
}
INFOF("Via %s", alloca_tohex_sid(trace->sid));
if (trace->reachable==REACHABLE_SELF && !next)
// We're already in this trace, send the next packet to the node before us in the list
next = last;
last = trace;
}
if (src->reachable==REACHABLE_SELF && last){
// it came back to us, we can send the reply to our mdp client...
next=src;
mdp->out.dst.port=mdp->out.src.port;
mdp->out.src.port=MDP_PORT_TRACE;
}
if (!next){
// destination is our neighbour?
if (dst->reachable & REACHABLE_DIRECT)
next = dst;
// destination is indirect?
else if (dst->reachable & REACHABLE_INDIRECT)
next = dst->next_hop;
// destination is not reachable or is ourselves? bounce back to the previous node or the sender.
else if (last)
next = last;
else
next = src;
}
INFOF("Next node is %s", alloca_tohex_sid(next->sid));
ob_unlimitsize(b);
// always write a full sid into the payload
my_subscriber->send_full=1;
if (overlay_address_append(&context, b, my_subscriber)){
ret = WHYF("Unable to append my address to the trace");
goto end;
}
mdp->out.payload_length = ob_position(b);
bcopy(my_subscriber->sid, mdp->out.src.sid, SID_SIZE);
bcopy(next->sid, mdp->out.dst.sid, SID_SIZE);
ret = overlay_mdp_dispatch(mdp, 0, NULL, 0);
end:
ob_free(b);
RETURN(ret);
}
static int overlay_mdp_service_manifest_response(overlay_mdp_frame *mdp){
int offset=0;
char id_hex[RHIZOME_MANIFEST_ID_STRLEN];
@ -310,6 +395,7 @@ int overlay_mdp_try_interal_services(overlay_mdp_frame *mdp)
case MDP_PORT_KEYMAPREQUEST: RETURN(keyring_mapping_request(keyring,mdp));
case MDP_PORT_DNALOOKUP: RETURN(overlay_mdp_service_dnalookup(mdp));
case MDP_PORT_ECHO: RETURN(overlay_mdp_service_echo(mdp));
case MDP_PORT_TRACE: RETURN(overlay_mdp_service_trace(mdp));
case MDP_PORT_PROBE: RETURN(overlay_mdp_service_probe(mdp));
case MDP_PORT_STUNREQ: RETURN(overlay_mdp_service_stun_req(mdp));
case MDP_PORT_STUN: RETURN(overlay_mdp_service_stun(mdp));

View File

@ -229,6 +229,8 @@ test_multihop_linear() {
set_instance +A
executeOk_servald mdp ping $SIDD 1
tfw_cat --stdout --stderr
executeOk_servald mdp trace $SIDD
tfw_cat --stdout --stderr
executeOk_servald route print
assertStdoutGrep --matches=1 "^$SIDB:BROADCAST UNICAST :"
assertStdoutGrep --matches=1 "^$SIDC:INDIRECT :"