Add manually triggered network scan command

This commit is contained in:
Jeremy Lakeman 2012-12-05 15:13:47 +10:30
parent 0ca9612a96
commit 3dfd64f4da
7 changed files with 126 additions and 7 deletions

View File

@ -1874,6 +1874,33 @@ int app_reverse_lookup(int argc, const char *const *argv, struct command_line_op
return 0;
}
int app_network_scan(int argc, const char *const *argv, struct command_line_option *o, void *context)
{
overlay_mdp_frame mdp;
bzero(&mdp,sizeof(mdp));
mdp.packetTypeAndFlags=MDP_SCAN;
struct overlay_mdp_scan *scan = (struct overlay_mdp_scan *)&mdp.raw;
const char *address;
if (cli_arg(argc, argv, o, "address", &address, NULL, NULL) == -1)
return -1;
if (address){
DEBUGF("Parsing arg %s", address);
if (!inet_aton(address, &scan->addr))
return WHY("Unable to parse the address");
}else
DEBUGF("Scanning local networks");
overlay_mdp_send(&mdp,MDP_AWAITREPLY,5000);
if (mdp.packetTypeAndFlags!=MDP_ERROR)
return -1;
cli_puts(mdp.error.message);
cli_delim("\n");
return mdp.error.error;
}
/* NULL marks ends of command structure.
"<anystring>" marks an arg that can take any value.
"[<anystring>]" marks an optional arg that can take any value.
@ -1963,6 +1990,8 @@ struct command_line_option command_line_options[]={
"Return identity of all known peers as URIs"},
{app_route_print, {"route","print",NULL},0,
"Print the routing table"},
{app_network_scan, {"scan","[<address>]",NULL},0,
"Scan the network for serval peers. If no argument is supplied, all local addresses will be scanned."},
{app_node_info,{"node","info","<sid>",NULL},0,
"Return routing information about a SID"},
{app_count_peers,{"peer","count",NULL},0,

View File

@ -147,6 +147,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#define MDP_ROUTING_TABLE 7
#define MDP_NODEINFO 8
#define MDP_GOODBYE 9
#define MDP_SCAN 10
// These are back-compatible with the old values of 'mode' when it was 'selfP'
#define MDP_ADDRLIST_MODE_ROUTABLE_PEERS 0

View File

@ -294,6 +294,9 @@ int overlay_mdp_relevant_bytes(overlay_mdp_frame *mdp)
case MDP_BIND:
len=(&mdp->raw[0] - (char *)mdp) + sizeof(sockaddr_mdp);
break;
case MDP_SCAN:
len=(&mdp->raw[0] - (char *)mdp) + sizeof(struct overlay_mdp_scan);
break;
case MDP_ERROR:
/* This formulation is used so that we don't copy any bytes after the
end of the string, to avoid information leaks */

View File

@ -21,6 +21,16 @@
#include "serval.h"
struct overlay_route_record{
unsigned char sid[SID_SIZE];
int reachable;
unsigned char neighbour[SID_SIZE];
};
struct overlay_mdp_scan{
struct in_addr addr;
};
/* Client-side MDP function */
extern int mdp_client_socket;
int overlay_mdp_client_init();

View File

@ -484,6 +484,9 @@ overlay_interface_init(char *name, struct in_addr src_addr, struct in_addr netma
char option_name[64];
snprintf(option_name, sizeof(option_name), "mdp.%s.tick_ms", (*name=='>'?name+1:name));
interface->tick_ms = confValueGetInt64Range(option_name, interface->tick_ms, 1LL, 3600000LL);
snprintf(option_name, sizeof(option_name), "interface.%s.default_route", (*name=='>'?name+1:name));
interface->default_route=confValueGetBoolean(option_name,0);
}
// disable announcements and other broadcasts if tick_ms=0.

View File

@ -859,6 +859,39 @@ static int routing_table(struct subscriber *subscriber, void *context){
return 0;
}
struct scan_state{
struct sched_ent alarm;
overlay_interface *interface;
uint32_t current;
uint32_t last;
};
struct scan_state scans[OVERLAY_MAX_INTERFACES];
static void overlay_mdp_scan(struct sched_ent *alarm)
{
struct sockaddr_in addr={
.sin_family=AF_INET,
.sin_port=htons(PORT_DNA),
};
struct scan_state *state = (struct scan_state *)alarm;
while(state->current <= state->last){
addr.sin_addr.s_addr=htonl(state->current);
if (overlay_send_probe(NULL, addr, state->interface))
break;
state->current++;
}
if (state->current <= state->last){
alarm->alarm=gettime_ms()+500;
schedule(alarm);
}else{
state->interface=NULL;
state->current=0;
state->last=0;
}
}
void overlay_mdp_poll(struct sched_ent *alarm)
{
if (alarm->poll.revents & POLLIN) {
@ -905,7 +938,7 @@ void overlay_mdp_poll(struct sched_ent *alarm)
}
return;
case MDP_GETADDRS:
{
overlay_mdp_frame mdpreply;
@ -955,6 +988,52 @@ void overlay_mdp_poll(struct sched_ent *alarm)
}
break;
case MDP_SCAN:
{
struct overlay_mdp_scan *scan = (struct overlay_mdp_scan *)&mdp->raw;
time_ms_t start=gettime_ms();
if (scan->addr.s_addr==0){
int i=0;
for (i=0;i<OVERLAY_MAX_INTERFACES;i++){
// skip any interface that is already being scanned
if (scans[i].interface)
continue;
struct overlay_interface *interface = &overlay_interfaces[i];
if (interface->state!=INTERFACE_STATE_UP)
continue;
scans[i].interface = interface;
scans[i].current = ntohl(interface->address.sin_addr.s_addr & interface->netmask.s_addr);
scans[i].last = ntohl(interface->broadcast_address.sin_addr.s_addr);
scans[i].alarm.alarm=start;
scans[i].alarm.function=overlay_mdp_scan;
start+=100;
schedule(&scans[i].alarm);
}
}else{
struct overlay_interface *interface = overlay_interface_find(scan->addr);
if (!interface){
overlay_mdp_reply_error(alarm->poll.fd,recvaddr_un,recvaddrlen, 1, "Unable to find matching interface");
return;
}
int i = interface - overlay_interfaces;
if (!scans[i].interface){
scans[i].interface = interface;
scans[i].current = ntohl(scan->addr.s_addr);
scans[i].last = ntohl(scan->addr.s_addr);
scans[i].alarm.alarm=start;
scans[i].alarm.function=overlay_mdp_scan;
schedule(&scans[i].alarm);
}
}
overlay_mdp_reply_ok(alarm->poll.fd,recvaddr_un,recvaddrlen,"Scan initiated");
}
break;
default:
/* Client is not allowed to send any other frame type */
WARNF("Unsupported MDP frame type: %d", mdp_type);

View File

@ -560,12 +560,6 @@ typedef struct overlay_mdp_addrlist {
unsigned char sids[MDP_MAX_SID_REQUEST][SID_SIZE];
} overlay_mdp_addrlist;
struct overlay_route_record{
unsigned char sid[SID_SIZE];
int reachable;
unsigned char neighbour[SID_SIZE];
};
typedef struct overlay_mdp_nodeinfo {
unsigned char sid[SID_SIZE];
int sid_prefix_length; /* must be long enough to be unique */