diff --git a/commandline.c b/commandline.c index a61a4bd3..27d01719 100644 --- a/commandline.c +++ b/commandline.c @@ -569,7 +569,7 @@ int cli_absolute_path(const char *arg) int app_server_start(int argc, const char *const *argv, struct command_line_option *o) { /* Process optional arguments */ - int foregroundP= (argc >= 3 && !strcasecmp(argv[2], "foreground")); + int foregroundP= (argc >= 2 && !strcasecmp(argv[1], "foreground")); if (cli_arg(argc, argv, o, "instance path", &thisinstancepath, cli_absolute_path, NULL) == -1) return -1; @@ -1165,6 +1165,50 @@ int app_id_self(int argc, const char *const *argv, struct command_line_option *o return 0; } +int app_node_info(int argc, const char *const *argv, struct command_line_option *o) +{ + const char *sid; + cli_arg(argc, argv, o, "sid", &sid, NULL, ""); + unsigned char packed_sid[SID_SIZE]; + + overlay_mdp_frame mdp; + bzero(&mdp,sizeof(mdp)); + + mdp.packetTypeAndFlags=MDP_NODEINFO; + if (argc>3) mdp.nodeinfo.resolve_did=1; + + /* get SID or SID prefix */ + int i; + mdp.nodeinfo.sid_prefix_length=0; + for(i = 0; i != SID_SIZE&&sid[i<<1]&&sid[(i<<1)+1]; ++i) { + packed_sid[mdp.nodeinfo.sid_prefix_length] = hexvalue(sid[i<<1]) << 4; + packed_sid[mdp.nodeinfo.sid_prefix_length++] |= hexvalue(sid[(i<<1)+1]); + } + + int result=overlay_mdp_send(&mdp,MDP_AWAITREPLY,5000); + if (result) { + if (mdp.packetTypeAndFlags==MDP_ERROR) + { + return WHYF(" MDP Server error #%d: '%s'",mdp.error.error,mdp.error.message); + } + else + return WHYF("Could not get information about node."); + } + + cli_printf("%d:%d:%s:%s:%s:%s:%s:%d:%d\n", + mdp.nodeinfo.index, + mdp.nodeinfo.count, + mdp.nodeinfo.foundP?"found":"noresult", + overlay_render_sid(mdp.nodeinfo.sid), + mdp.nodeinfo.resolve_did?mdp.nodeinfo.did:"did-not-resolved", + mdp.nodeinfo.localP?"self":"peer", + mdp.nodeinfo.neighbourP?"direct":"indirect", + mdp.nodeinfo.score, + mdp.nodeinfo.interface_number); + + return 0; +} + /* NULL marks ends of command structure. "" marks an arg that can take any value. "[]" marks an optional arg that can take any value. @@ -1189,19 +1233,19 @@ command_line_option command_line_options[]={ "Display command usage."}, {app_echo,{"echo","...",NULL},CLIFLAG_STANDALONE, "Output the supplied string."}, - {app_server_start,{"node","start",NULL},CLIFLAG_STANDALONE, + {app_server_start,{"start",NULL},CLIFLAG_STANDALONE, "Start Serval Mesh node process with instance path taken from SERVALINSTANCE_PATH environment variable."}, - {app_server_start,{"node","start","in","",NULL},CLIFLAG_STANDALONE, + {app_server_start,{"start","in","",NULL},CLIFLAG_STANDALONE, "Start Serval Mesh node process with given instance path."}, - {app_server_start,{"node","start","foreground",NULL},CLIFLAG_STANDALONE, + {app_server_start,{"start","foreground",NULL},CLIFLAG_STANDALONE, "Start Serval Mesh node process without detatching from foreground."}, - {app_server_start,{"node","start","foreground","in","",NULL},CLIFLAG_STANDALONE, + {app_server_start,{"start","foreground","in","",NULL},CLIFLAG_STANDALONE, "Start Serval Mesh node process with given instance path, without detatching from foreground."}, - {app_server_stop,{"node","stop",NULL},0, + {app_server_stop,{"stop",NULL},0, "Stop a running Serval Mesh node process with instance path taken from SERVALINSTANCE_PATH environment variable."}, - {app_server_stop,{"node","stop","in","",NULL},0, + {app_server_stop,{"stop","in","",NULL},0, "Stop a running Serval Mesh node process with given instance path."}, - {app_server_status,{"node","status",NULL},0, + {app_server_status,{"status",NULL},0, "Display information about any running Serval Mesh node."}, {app_mdp_ping,{"mdp","ping","",NULL},CLIFLAG_STANDALONE, "Attempts to ping specified node via Mesh Datagram Protocol (MDP)."}, @@ -1239,6 +1283,8 @@ command_line_option command_line_options[]={ "Return my own identity(s) as SIDs"}, {app_id_self,{"id","peers",NULL},0, "Return identity of known peers as SIDs"}, + {app_node_info,{"node","info","","[]",NULL},0, + "Return information about SID, and optionally ask for DID resolution via network"}, #ifdef HAVE_VOIPTEST {app_pa_phone,{"phone",NULL},0, "Run phone test application"}, diff --git a/overlay_mdp.c b/overlay_mdp.c index 50976061..71f57a06 100644 --- a/overlay_mdp.c +++ b/overlay_mdp.c @@ -902,6 +902,8 @@ int overlay_mdp_poll() switch(mdp->packetTypeAndFlags&MDP_TYPE_MASK) { case MDP_VOMPEVENT: return vomp_mdp_event(mdp,recvaddr_un,recvaddrlen); + case MDP_NODEINFO: + return overlay_route_node_info(mdp,recvaddr_un,recvaddrlen); case MDP_GETADDRS: { overlay_mdp_frame mdpreply; @@ -1019,6 +1021,10 @@ int overlay_mdp_relevant_bytes(overlay_mdp_frame *mdp) /* XXX too hard to work out precisely for now. */ len=sizeof(overlay_mdp_frame); break; + case MDP_NODEINFO: + len=&mdp->nodeinfo.count-(int *)mdp; + len+=sizeof(mdp->nodeinfo.count); + break; default: return WHY("Illegal MDP frame type."); } diff --git a/overlay_route.c b/overlay_route.c index ea13707f..4c35ecde 100644 --- a/overlay_route.c +++ b/overlay_route.c @@ -1264,3 +1264,131 @@ int overlay_route_tick_node(int bin,int slot,long long now) return overlay_route_recalc_node_metrics(&overlay_nodes[bin][slot],now); } +int overlay_route_node_info(overlay_mdp_frame *mdp, + struct sockaddr_un *addr,int addrlen) +{ + int bin,slot,n; + long long now=overlay_gettime_ms(); + + /* check if it is a local identity */ + int cn,in,kp; + for(cn=0;cncontext_count;cn++) + for(in=0;incontexts[cn]->identity_count;in++) + for(kp=0;kpcontexts[cn]->identities[in]->keypair_count;kp++) + if (keyring->contexts[cn]->identities[in]->keypairs[kp]->type + ==KEYTYPE_CRYPTOBOX) + { + if (!bcmp(&mdp->nodeinfo.sid[0], + &keyring->contexts[cn]->identities[in] + ->keypairs[kp]->public_key[0], + mdp->nodeinfo.sid_prefix_length)) + { + if (mdp->nodeinfo.count==mdp->nodeinfo.index) + { + mdp->nodeinfo.foundP=1; + mdp->nodeinfo.localP=1; + mdp->nodeinfo.neighbourP=0; + mdp->nodeinfo.time_since_last_observation=0; + mdp->nodeinfo.score=256; + mdp->nodeinfo.interface_number=-1; + bcopy(&keyring->contexts[cn]->identities[in] + ->keypairs[kp]->public_key[0], + &mdp->nodeinfo.sid[0],SID_SIZE); + + mdp->nodeinfo.did[0]=0; + if (mdp->nodeinfo.resolve_did) { + mdp->nodeinfo.resolve_did=0; + int k2; + for(k2=0;k2contexts[cn]->identities[in] + ->keypair_count;k2++) + if (keyring->contexts[cn]->identities[in]->keypairs[k2]->type + ==KEYTYPE_DID) + { + /* private key field has packed did */ + extractDid(keyring->contexts[cn]->identities[in] + ->keypairs[k2]->private_key,0, + &mdp->nodeinfo.did[0]); + mdp->nodeinfo.resolve_did=1; + } + } + } + mdp->nodeinfo.count++; + } + } + + /* check neighbour table, i.e., if directly connected */ + for(n=0;nnodeinfo.sid[0], + &overlay_neighbours[n].node->sid[0], + mdp->nodeinfo.sid_prefix_length)) + { + if (mdp->nodeinfo.count==mdp->nodeinfo.index) + { + mdp->nodeinfo.foundP=1; + mdp->nodeinfo.localP=0; + mdp->nodeinfo.neighbourP=1; + mdp->nodeinfo.time_since_last_observation + =overlay_gettime_ms() + -overlay_neighbours[n].last_observation_time_ms; + mdp->nodeinfo.score=-1; + mdp->nodeinfo.interface_number=-1; + int i; + for(i=0;imdp->nodeinfo.score) + { + mdp->nodeinfo.score=overlay_neighbours[n].scores[i]; + mdp->nodeinfo.interface_number=i; + } + + bcopy(&overlay_neighbours[n].node->sid[0], + &mdp->nodeinfo.sid[0],SID_SIZE); + } + mdp->nodeinfo.count++; + } + } + + /* check if it is an indirectly connected node that we know about */ + for(bin=0;binnodeinfo.sid[0], + &overlay_nodes[bin][slot].sid[0], + mdp->nodeinfo.sid_prefix_length)) + { + if (mdp->nodeinfo.count==mdp->nodeinfo.index) + { + mdp->nodeinfo.foundP=1; + mdp->nodeinfo.localP=0; + mdp->nodeinfo.neighbourP=0; + mdp->nodeinfo.time_since_last_observation=overlay_gettime_ms(); + mdp->nodeinfo.score=-1; + mdp->nodeinfo.interface_number=-1; + int o; + for(o=0;ocorrected_score>mdp->nodeinfo.score) { + mdp->nodeinfo.score=ob->corrected_score; + } + if ((now-ob->rx_time) + nodeinfo.time_since_last_observation) + mdp->nodeinfo.time_since_last_observation=now-ob->rx_time; + } + + bcopy(&overlay_nodes[bin][slot].sid[0], + &mdp->nodeinfo.sid[0],SID_SIZE); + } + mdp->nodeinfo.count++; + } + } + + return overlay_mdp_reply(mdp_named_socket,addr,addrlen,mdp); + + return 0; +} diff --git a/serval.h b/serval.h index 55528c39..1ee94894 100644 --- a/serval.h +++ b/serval.h @@ -1193,6 +1193,22 @@ typedef struct overlay_mdp_vompevent { }; } overlay_mdp_vompevent; +#define MDP_NODEINFO 8 +typedef struct overlay_mdp_nodeinfo { + unsigned char sid[SID_SIZE]; + int sid_prefix_length; /* allow wildcard matching */ + char did[64]; + int foundP; + int localP; + int neighbourP; + int score; + int interface_number; + int resolve_did; + unsigned long long time_since_last_observation; + int index; /* which record to return or was returned (incase there are multiple matches) */ + int count; /* number of matching records */ +} overlay_mdp_nodeinfo; + typedef struct overlay_mdp_frame { #define MDP_AWAITREPLY 9999 unsigned int packetTypeAndFlags; @@ -1202,6 +1218,7 @@ typedef struct overlay_mdp_frame { overlay_mdp_bind_request bind; overlay_mdp_addrlist addrlist; overlay_mdp_vompevent vompevent; + overlay_mdp_nodeinfo nodeinfo; overlay_mdp_error error; /* 2048 is too large (causes EMSGSIZE errors on OSX, but probably fine on Linux) */ @@ -1338,6 +1355,8 @@ int cli_delim(const char *opt); int overlay_mdp_getmyaddr(int index,unsigned char *sid); int overlay_mdp_bind(unsigned char *localaddr,int port); +int overlay_route_node_info(overlay_mdp_frame *mdp, + struct sockaddr_un *addr,int addrlen); int app_vomp_status(int argc, const char *const *argv, struct command_line_option *o); int app_vomp_dial(int argc, const char *const *argv, struct command_line_option *o);