13
0
Fork 1
dedected/com-on-air_cs-linux/tools/dect_cli.c

1094 lines
22 KiB
C

/*
* dect_cli async and sync interface to DECT, can dump pcap files
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* authors:
* (C) 2008 Matthias Wenzel <dect at mazzoo dot de>
* (C) 2008 Andreas Schuler <krater at badterrorist dot com>
*
*/
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdint.h>
#include <sys/ioctl.h>
#include <time.h>
#include <limits.h>
#include <signal.h>
#include <ctype.h>
#include <pcap.h>
#include "com_on_air_user.h"
#include "dect_cli.h"
struct cli_info cli;
#define RXBUF 8192
char buf[RXBUF];
/* pcap errors */
char errbuf[PCAP_ERRBUF_SIZE];
int rfpi_is_ignored(const uint8_t * RFPI);
char * get_cli_mode(void)
{
switch(cli.mode){
case MODE_STOP: return "stopped"; break;
case MODE_FPSCAN: return "fpscan"; break;
case MODE_PPSCAN: return "ppscan"; break;
case MODE_CALLSCAN: return "callscan"; break;
case MODE_JAM: return "jam"; break;
default:
return "unknown";
}
}
void print_help(void)
{
LOG("\n");
LOG(" help - this help\n");
LOG(" fpscan - async scan for basestations, dump RFPIs\n");
LOG(" callscan - async scan for active calls, dump RFPIs\n");
LOG(" autorec - sync on any calls in callscan, autodump in pcap\n");
LOG(" ppscan <rfpi> - sync scan for active calls\n");
LOG(" chan <ch> - set current channel [0-9], currently %d\n", cli.channel);
// LOG(" slot <sl> - set current slot [0-23], currently %d\n", cli.slot);
// LOG(" jam - jam current channel\n");
LOG(" band - toggle between EMEA/DECT and US/DECT6.0 bands\n");
LOG(" ignore <rfpi> - toggle ignoring of an RFPI in autorec\n");
LOG(" dump - dump stations and calls we have seen\n");
LOG(" name <rfpi> <name> - name stations we have seen\n");
LOG(" hop - toggle channel hopping, currently %s\n", cli.hop ? "ON":"OFF");
LOG(" verb - toggle verbosity, currently %s\n", cli.verbose ? "ON":"OFF");
LOG(" mode - report current mode, currently %s\n", get_cli_mode());
LOG(" stop - stop it - whatever we were doing\n");
LOG(" quit - well :)\n");
LOG("\n");
}
void set_channel(uint32_t channel)
{
if (cli.verbose)
LOG("### mode: %s, switching to channel %d\n", get_cli_mode(), ch2etsi[channel]);
if (ioctl(cli.fd, COA_IOCTL_CHAN, &ch2etsi[channel])){
LOG("!!! couldn't ioctl()\n");
exit(1);
}
cli.last_hop = time(NULL);
}
void set_slot(uint32_t slot)
{
LOG("!!! not yet implemented :(\n");
}
void do_ppscan(uint8_t * RFPI)
{
LOG("### trying to sync on %.2x %.2x %.2x %.2x %.2x\n",
RFPI[0],
RFPI[1],
RFPI[2],
RFPI[3],
RFPI[4]
);
/* set sync sniff mode */
uint16_t val;
val = COA_MODE_SNIFF | COA_SUBMODE_SNIFF_SYNC;
if (ioctl(cli.fd, COA_IOCTL_MODE, &val)){
LOG("!!! couldn't ioctl()\n");
exit(1);
}
/* set rfpi to sync with */
if(ioctl(cli.fd, COA_IOCTL_SETRFPI, RFPI)){
LOG("!!! couldn't ioctl()\n");
exit(1);
}
set_channel(cli.channel);
memcpy(cli.RFPI, RFPI, 5);
cli.mode = MODE_PPSCAN;
cli.autorec_last_bfield = time(NULL);
}
void add_station(struct dect_station * station)
{
int i;
LOG("### found new %s", station->type == TYPE_FP ? "station":"call on");
for (i=0; i<5; i++)
LOG(" %.2x", station->RFPI[i]);
LOG(" on channel %d RSSI %d", station->channel, station->RSSI);
struct dect_station * p = cli.station_list;
if (p)
{ /* append to existing list */
while (p->next)
p = p->next;
p->next = malloc(sizeof(*p));
p = p->next;
}else /* create 1st element in list */
{
cli.station_list = malloc(sizeof(*cli.station_list));
p = cli.station_list;
}
if (!p)
{
LOG("!!! out of memory\n");
exit(1);
}
memset(p, 0, sizeof(*p));
memcpy(p->RFPI, station->RFPI, 5);
p->channel = station->channel;
p->RSSI = station->RSSI;
p->type = station->type;
p->first_seen = time(NULL);
p->last_seen = p->first_seen;
p->count_seen = 1;
p->name = NULL;
struct station_name * sn = cli.station_names;
while(sn)
{
if(!memcmp(p->RFPI, sn->RFPI, 5))
{
p->name = sn->name;
LOG(" name \"%s\"",p->name);
if(sn->prev)
sn->prev->next = sn->next;
else
cli.station_names = sn->next;
if(sn->next)
sn->next->prev = sn->prev;
if(sn->prev == NULL && sn->next == NULL)
{
free(sn);
cli.station_names = NULL;
}else
free(sn);
break;
}
sn = sn->next;
}
LOG("\n");
}
void try_add_station(struct dect_station * station)
{
struct dect_station * p = cli.station_list;
int found = 0;
while (p)
{
if (!memcmp(p->RFPI, station->RFPI, 5))
{
if (p->type == station->type)
{
if ( (p->channel != station->channel) &&
(cli.verbose) )
{
int i;
LOG("### station");
for (i=0; i<5; i++)
LOG(" %.2x", station->RFPI[i]);
LOG(" switched from channel %d to channel %d\n",
p->channel,
station->channel);
}
found = 1;
p->channel = station->channel;
p->count_seen++;
p->last_seen = time(NULL);
p->RSSI += station->RSSI; /* we avg on dump */
}
}
p = p->next;
}
if (!found)
add_station(station);
if (cli.autorec && (cli.mode != MODE_PPSCAN))
{
if (rfpi_is_ignored(station->RFPI))
{
if (cli.verbose)
{
LOG("### skipping ignored RFPI %.2x %.2x %.2x %.2x %.2x\n",
station->RFPI[0], station->RFPI[1], station->RFPI[2],
station->RFPI[3], station->RFPI[4]);
}
}
else
{
do_ppscan(station->RFPI);
}
}
}
void do_fpscan(void)
{
LOG("### starting fpscan\n");
uint16_t val;
val = COA_MODE_SNIFF | COA_SUBMODE_SNIFF_SCANFP;
if (ioctl(cli.fd, COA_IOCTL_MODE, &val)){
LOG("!!! couldn't ioctl()\n");
exit(1);
}
/* set start channel */
set_channel(cli.channel);
cli.mode = MODE_FPSCAN;
cli.autorec = 0;
}
void do_callscan(void)
{
LOG("### starting callscan\n");
uint16_t val;
val = COA_MODE_SNIFF | COA_SUBMODE_SNIFF_SCANPP;
if (ioctl(cli.fd, COA_IOCTL_MODE, &val)){
LOG("!!! couldn't ioctl()\n");
exit(1);
}
/* set start channel */
set_channel(cli.channel);
cli.mode = MODE_CALLSCAN;
}
int hexvalue(int hexdigit)
{
if (hexdigit >= '0' && hexdigit <= '9')
return hexdigit - '0';
if (hexdigit >= 'a' && hexdigit <= 'f')
return hexdigit - ('a' - 10);
if (hexdigit >= 'A' && hexdigit <= 'F')
return hexdigit - ('A' - 10);
return -1;
}
int parse_rfpi(const char * str_rfpi, uint8_t * rfpi)
{
int i = 0;
int read = 0;
// Skip initial whitespace:
while (isspace(*str_rfpi))
{
str_rfpi++;
read++;
}
for (;;)
{
int highnibble, lownibble;
highnibble = hexvalue(str_rfpi[0]);
// Need to check for validity of the first character before
// continuing with the next, in case the first one was \0:
if (highnibble == -1)
return -1;
lownibble = hexvalue(str_rfpi[1]);
if (lownibble == -1)
return -1;
rfpi[i] = (highnibble << 4) | lownibble;
read += 2;
if (i == 4)
break;
i++;
str_rfpi += 2;
// Accept space or colon as byte separator. None at all is ok too.
if (*str_rfpi == ' ' || *str_rfpi == ':')
{
str_rfpi++;
read++;
}
}
return read;
}
void do_ppscan_str(char * str_rfpi)
{
uint8_t RFPI[5];
if (parse_rfpi(str_rfpi, RFPI) == -1)
{
LOG("!!! please enter a valid RFPI (e.g. 00 01 02 03 04)\n");
return;
}
do_ppscan(RFPI);
}
void do_add_name(char * str_rfpi_name)
{
uint8_t RFPI[5];
int read;
struct dect_station * p = cli.station_list;
if ((read = parse_rfpi(str_rfpi_name, RFPI)) == -1)
{
LOG("!!! please enter a valid RFPI (e.g. 00 01 02 03 04)\n");
return;
}
str_rfpi_name += read;
while (isspace(*str_rfpi_name))
str_rfpi_name++;
LOG("### named %.2x %.2x %.2x %.2x %.2x as %s\n",
RFPI[0],
RFPI[1],
RFPI[2],
RFPI[3],
RFPI[4],
str_rfpi_name);
while(p)
{
if (!memcmp(p->RFPI, RFPI, 5))
{
if(p->name != NULL)
{
LOG("### renaming station %s\n", p->name);
free(p->name);
}
p->name = malloc(strlen(str_rfpi_name) + 1);
strcpy(p->name, str_rfpi_name);
return;
}
p = p->next;
}
LOG("!!! station %.2x %.2x %.2x %.2x %.2x not found yet\n",
RFPI[0],
RFPI[1],
RFPI[2],
RFPI[3],
RFPI[4]);
}
// Returns true if 'RFPI' occurs in 'list'.
int rfpi_list_present(struct rfpi_list * list, const uint8_t * RFPI)
{
for (; list != NULL; list = list->next)
{
if (!memcmp(RFPI, list->RFPI, 5))
return 1;
}
return 0;
}
// Adds 'RFPI' at the front of '*list_ptr'.
void rfpi_list_add(struct rfpi_list ** list_ptr, const uint8_t * RFPI)
{
struct rfpi_list * new_link = malloc(sizeof (struct rfpi_list));
memcpy(new_link->RFPI, RFPI, 5);
new_link->next = *list_ptr;
*list_ptr = new_link;
}
// Removes the first occurence of 'RFPI' from '*list_ptr'.
void rfpi_list_remove(struct rfpi_list ** list_ptr, const uint8_t * RFPI)
{
for (; *list_ptr != NULL; list_ptr = &(*list_ptr)->next)
{
struct rfpi_list * link = *list_ptr;
if (!memcmp(RFPI, link->RFPI, 5))
{
*list_ptr = link->next;
free(link);
return;
}
}
}
int rfpi_is_ignored(const uint8_t * RFPI)
{
return rfpi_list_present(cli.ignored_rfpis, RFPI);
}
void rfpi_ignore_rfpi(const uint8_t * RFPI)
{
rfpi_list_add(&cli.ignored_rfpis, RFPI);
}
void rfpi_unignore_rfpi(const uint8_t * RFPI)
{
rfpi_list_remove(&cli.ignored_rfpis, RFPI);
}
void do_ignore_str(const char * str_rfpi)
{
uint8_t RFPI[5];
if (parse_rfpi(str_rfpi, RFPI) == -1)
{
LOG("!!! please enter a valid RFPI (e.g. 00 01 02 03 04)\n");
return;
}
if (rfpi_is_ignored(RFPI))
{
LOG("### no longer ignoring RFPI %.2x %.2x %.2x %.2x %.2x\n",
RFPI[0], RFPI[1], RFPI[2], RFPI[3], RFPI[4]);
rfpi_unignore_rfpi(RFPI);
}
else
{
LOG("### ignoring RFPI %.2x %.2x %.2x %.2x %.2x\n",
RFPI[0], RFPI[1], RFPI[2], RFPI[3], RFPI[4]);
rfpi_ignore_rfpi(RFPI);
}
}
void do_chan(char * str_chan)
{
uint32_t channel;
char * end;
errno = 0;
channel = strtoul(str_chan, &end, 0);
if ((errno == ERANGE && (channel == LONG_MAX || channel == LONG_MIN))
|| (errno != 0 && channel == 0))
{
LOG("!!! please enter a valid channel number [0-14]\n");
return;
}
if (end == str_chan)
{
LOG("!!! please enter a valid channel number [0-14]\n");
return;
}
if (! ((channel >= 0) && (channel <= 14)) )
{
LOG("!!! please enter a valid channel number [0-14]\n");
return;
}
if(channel<10)
channel = 9 - channel;
cli.channel = channel;
set_channel(cli.channel);
}
void do_slot(char * str_slot)
{
uint32_t slot;
char * end;
errno = 0;
slot = strtoul(str_slot, &end, 0);
if ((errno == ERANGE && (slot == LONG_MAX || slot == LONG_MIN))
|| (errno != 0 && slot == 0))
{
LOG("!!! please enter a valid slot number [0-23]\n");
return;
}
if (end == str_slot)
{
LOG("!!! please enter a valid slot number [0-23]\n");
return;
}
if (slot > 23)
{
LOG("!!! please enter a valid slot number [0-23]\n");
return;
}
cli.slot = slot;
set_slot(cli.slot);
}
void do_jam(void)
{
LOG("!!! not yet implemented :(\n");
}
void do_band(void)
{
switch (cli.band)
{
case DECT_BAND_EMEA:
cli.band = DECT_BAND_US;
cli.hop_start = 10;
cli.hop_end = 14;
cli.channel = cli.hop_start;
LOG("### using US/DECT6.0 band\n");
break;
case DECT_BAND_US:
cli.band = DECT_BAND_EMEA | DECT_BAND_US;
cli.hop_start = 0;
cli.hop_end = 14;
cli.channel = cli.hop_start;
LOG("### using both EMEA/DECT and US/DECT6.0 band\n");
break;
case DECT_BAND_EMEA | DECT_BAND_US:
cli.band = DECT_BAND_EMEA;
cli.hop_start = 0;
cli.hop_end = 9;
cli.channel = cli.hop_start;
LOG("### using EMEA/DECT band\n");
break;
}
}
void do_dump(void)
{
int i;
struct dect_station * p = cli.station_list;
struct rfpi_list * r = cli.ignored_rfpis;
if (!p)
{
LOG("### nothing found so far\n");
goto dump_ignore;
}
LOG("### stations\n");
do
{
if (p->type == TYPE_FP)
{
LOG(" ");
for (i=0; i<5; i++)
LOG(" %.2x", p->RFPI[i]);
LOG(" ch %1.1d ", p->channel);
LOG(" RSSI %5.2f ", (double)p->RSSI / p->count_seen);
LOG(" count %4.u ", p->count_seen);
LOG(" first %u ", p->first_seen);
LOG(" last %u ", p->last_seen);
if (p->name)
LOG(" name \"%s\"", p->name);
LOG("\n");
}
} while ((p = p->next));
p = cli.station_list;
LOG("### calls\n");
do
{
if (p->type == TYPE_PP)
{
LOG(" ");
for (i=0; i<5; i++)
LOG(" %.2x", p->RFPI[i]);
LOG(" ch %1.1d ", p->channel);
LOG(" RSSI %5.2f ", (double)p->RSSI / p->count_seen);
LOG(" count %4.u ", p->count_seen);
LOG(" first %u ", p->first_seen);
LOG(" last %u ", p->last_seen);
LOG("\n");
}
} while ((p = p->next));
dump_ignore:
if (!r)
return;
LOG("### RFPIs ignored\n");
do{
LOG(" %.2x %.2x %.2x %.2x %.2x is ignored\n",
r->RFPI[0],
r->RFPI[1],
r->RFPI[2],
r->RFPI[3],
r->RFPI[4]
);
} while ((r = r->next));
}
void do_hop(void)
{
cli.hop = cli.hop ? 0:1;
LOG("### channel hopping turned %s\n", cli.hop ? "ON":"OFF");
}
void do_verb(void)
{
cli.verbose = cli.verbose ? 0:1;
LOG("### verbosity turned %s\n", cli.verbose ? "ON":"OFF");
}
void do_mode(void)
{
LOG("### current mode: %s, verbosity %s, channel hopping %s\n",
get_cli_mode(),
cli.verbose ? "ON":"OFF",
cli.hop ? "ON":"OFF");
}
void do_autorec(void)
{
cli.autorec = cli.autorec ? 0:1;
LOG("### starting autorec\n");
}
void do_stop_keep_autorec(void)
{
LOG("### stopping DIP\n");
uint16_t val;
val = COA_MODE_IDLE;
if (ioctl(cli.fd, COA_IOCTL_MODE, &val)){
LOG("couldn't ioctl()\n");
exit(1);
}
cli.mode = MODE_STOP;
}
void do_stop(void)
{
if (!(cli.mode & MODE_STOP))
{
do_stop_keep_autorec();
}
cli.autorec = 0;
}
void do_save_station_names()
{
struct dect_station * sl = cli.station_list;
struct station_name * sn = cli.station_names;
FILE * fd = fopen("stations.rc", "w");
while(sn)
{
fprintf(fd, "%.2x %.2x %.2x %.2x %.2x %s\n",
sn->RFPI[0],
sn->RFPI[1],
sn->RFPI[2],
sn->RFPI[3],
sn->RFPI[4],
sn->name);
free(sn->name);
sn = sn->next;
}
while(sl)
{
if (sl->name != NULL)
{
fprintf(fd, "%.2x %.2x %.2x %.2x %.2x %s\n",
sl->RFPI[0],
sl->RFPI[1],
sl->RFPI[2],
sl->RFPI[3],
sl->RFPI[4],
sl->name);
free(sl->name);
}
sl = sl->next;
}
fclose(fd);
}
void do_quit(void)
{
do_stop();
do_dump();
do_save_station_names();
exit(0);
}
void process_cli_data()
{
int ret;
ret = read(cli.in, buf, RXBUF);
buf[ret]=0;
if(buf[ret-1] == '\n')
buf[ret-1] = 0;
int done = 0;
if ( !strncasecmp((char *)buf, "help", 4) )
{ print_help(); done = 1; }
if ( !strncasecmp((char *)buf, "fpscan", 6) )
{ do_fpscan(); done = 1; }
if ( !strncasecmp((char *)buf, "callscan", 8) )
{ do_callscan(); done = 1; }
if ( !strncasecmp((char *)buf, "autorec", 7) )
{ do_autorec(); done = 1; }
if ( !strncasecmp((char *)buf, "ppscan", 6) )
{ do_ppscan_str(&buf[6]); done = 1; }
if ( !strncasecmp((char *)buf, "chan", 4) )
{ do_chan(&buf[4]); done = 1; }
if ( !strncasecmp((char *)buf, "slot", 4) )
{ do_slot(&buf[4]); done = 1; }
if ( !strncasecmp((char *)buf, "jam", 3) )
{ do_jam(); done = 1; }
if ( !strncasecmp((char *)buf, "band", 4) )
{ do_band(); done = 1; }
if ( !strncasecmp((char *)buf, "ignore", 6) )
{ do_ignore_str(&buf[6]); done = 1; }
if ( !strncasecmp((char *)buf, "dump", 4) )
{ do_dump(); done = 1; }
if ( !strncasecmp((char *)buf, "name", 4) )
{ do_add_name(&buf[4]); done = 1; }
if ( !strncasecmp((char *)buf, "hop", 3) )
{ do_hop(); done = 1; }
if ( !strncasecmp((char *)buf, "verb", 4) )
{ do_verb(); done = 1; }
if ( !strncasecmp((char *)buf, "mode", 4) )
{ do_mode(); done = 1; }
if ( !strncasecmp((char *)buf, "stop", 4) )
{ do_stop(); done = 1; }
if ( !strncasecmp((char *)buf, "quit", 4) )
do_quit();
if(!done)
LOG("!!! no such command %s\n", buf);
}
void init_pcap(struct sniffed_packet * packet)
{
char fname[512];
char ftime[256];
time_t rawtime;
struct tm *timeinfo;
time (&rawtime);
timeinfo = localtime(&rawtime);
strftime(ftime, sizeof(ftime), "%Y-%m-%d_%H_%M_%S", timeinfo);
sprintf(fname, "dump_%s_RFPI_%.2x_%.2x_%.2x_%.2x_%.2x.pcap",
ftime,
cli.RFPI[0],
cli.RFPI[1],
cli.RFPI[2],
cli.RFPI[3],
cli.RFPI[4]);
LOG("### dumping to %s\n", fname);
cli.pcap = pcap_open_dead(DLT_EN10MB, 73);
if (!cli.pcap)
{
LOG("!!! couldn't pcap_open_dead(\"%s\")\n", fname);
}
cli.pcap_d = pcap_dump_open(cli.pcap, fname);
if (!cli.pcap_d)
{
LOG("!!! couldn't pcap_dump_open(\"%s\")\n", fname);
}
}
int has_b_field()
{
if ((cli.packet.data[5] & 0x0e) != 0x0e)
return 1;
return 0;
}
void process_dect_data()
{
int ret;
switch (cli.mode)
{
case MODE_FPSCAN:
while (7 == (ret = read(cli.fd, buf, 7))){
memcpy(cli.station.RFPI, &buf[2], 5);
cli.station.channel = buf[0];
cli.station.RSSI = buf[1];
cli.station.type = TYPE_FP;
try_add_station(&cli.station);
}
break;
case MODE_CALLSCAN:
while (7 == (ret = read(cli.fd, buf, 7))){
memcpy(cli.station.RFPI, &buf[2], 5);
cli.station.channel = buf[0];
cli.station.RSSI = buf[1];
cli.station.type = TYPE_PP;
try_add_station(&cli.station);
}
break;
case MODE_PPSCAN:
while ( sizeof(cli.packet) ==
read(cli.fd, &cli.packet, sizeof(cli.packet)))
{
memcpy(cli.station.RFPI, cli.RFPI, 5);
cli.station.channel = cli.packet.channel;
cli.station.RSSI = cli.packet.rssi;
cli.station.type = TYPE_PP;
/* to ypdate statistics only we try_add_station() */
try_add_station(&cli.station);
/* stop hopping once we're synchronized */
cli.hop = 0;
if (!cli.pcap)
{
LOG("### got sync\n");
init_pcap(&cli.packet);
/* this is not actually a B-Field,
* but we expect some to come soon
* and the val needs to be non-0 */
cli.autorec_last_bfield = time(NULL);
}
if (has_b_field())
cli.autorec_last_bfield = time(NULL);
struct pcap_pkthdr pcap_hdr;
pcap_hdr.caplen = 73;
pcap_hdr.len = 73;
ret = gettimeofday(&pcap_hdr.ts, NULL);
if (ret)
{
LOG("!!! couldn't gettimeofday(): %s\n",
strerror(errno));
exit(1);
}
uint8_t pcap_packet[100];
memset(pcap_packet, 0, 100);
pcap_packet[12] = 0x23;
pcap_packet[13] = 0x23;
pcap_packet[14] = 0x00; /* decttype (receive) */
pcap_packet[15] = cli.packet.channel;
pcap_packet[16] = 0x00;
pcap_packet[17] = cli.packet.slot;
pcap_packet[18] = cli.packet.frameflags&0x0f;
pcap_packet[19] = cli.packet.rssi;
memcpy(&pcap_packet[20], cli.packet.data, 53);
pcap_dump(cli.pcap_d, &pcap_hdr, pcap_packet);
}
break;
}
}
void init_dect()
{
cli.fd = open(DEV, O_RDWR | O_NONBLOCK);
if (cli.fd < 0)
{
LOG("!!! couldn't open(\"%s\"): %s\n",
DEV,
strerror(errno));
exit(1);
}
cli.pcap = NULL;
}
void init_station_names(void)
{
uint8_t RFPI[5];
int read;
char str_buf[80];
FILE * fd = fopen("stations.rc", "r");
if (!fd)
return;
while(fgets(str_buf, 80, fd))
{
if ((read = parse_rfpi(str_buf, &RFPI)) == -1)
continue;
char * start = str_buf+read;
while (isspace(*start))
start++;
char * name = start;
while(*start && *start != '\n')
start++;
*start = '\0';
struct station_name * p = cli.station_names;
if (p)
{
while(p->next)
p = p->next;
p->next = malloc(sizeof(*p));
p->next->prev = p;
p = p->next;
p->next = NULL;
}else{
cli.station_names = malloc(sizeof(*cli.station_names));
p = cli.station_names;
p->next = NULL;
p->prev = NULL;
}
if (!p)
{
LOG("!!! out of memory\n");
exit(1);
}
memcpy(p->RFPI, RFPI, 5);
p->name = malloc(sizeof(char)*(strlen(name)+1));
strcpy(p->name, name);
}
fclose(fd);
}
void signal_handler(int s)
{
LOG("### got signal %d, will dump & quit\n", s);
do_quit();
}
void init_cli(void)
{
cli.channel = 0;
cli.slot = 0;
cli.hop = 1;
cli.hop_ch_time = 1; /* in sec */
cli.mode = MODE_STOP;
cli.in = fileno(stdin);
cli.verbose = 0;
cli.station_list = NULL;
cli.ignored_rfpis= NULL;
cli.autorec = 0;
cli.autorec_timeout = 10;
cli.autorec_last_bfield = 0;
cli.band = DECT_BAND_EMEA;
cli.hop_start = 0;
cli.hop_end = 9;
signal(SIGHUP, signal_handler);
signal(SIGINT, signal_handler);
signal(SIGQUIT, signal_handler);
signal(SIGABRT, signal_handler);
signal(SIGKILL, signal_handler);
signal(SIGALRM, signal_handler);
signal(SIGTERM, signal_handler);
signal(SIGUSR1, signal_handler);
signal(SIGUSR2, signal_handler);
}
void init(void)
{
init_dect();
init_cli();
init_station_names();
}
int max_int(int a, int b)
{
if (a>b)
return a;
else
return b;
}
void mainloop(void)
{
fd_set rfd;
fd_set wfd;
fd_set efd;
int nfds = max_int(cli.in, cli.fd);
nfds++;
struct timeval tv;
int ret;
while (0xDEC + 'T')
{
tv.tv_sec = 1;
tv.tv_usec = 0;
FD_ZERO(&rfd);
FD_ZERO(&wfd);
FD_ZERO(&efd);
FD_SET(cli.in, &rfd);
FD_SET(cli.fd, &rfd);
FD_SET(cli.in, &efd);
FD_SET(cli.fd, &efd);
ret = select(nfds, &rfd, &wfd, &efd, &tv);
if (ret < 0)
{
LOG("!!! select()\n");
exit(1);
}
if (FD_ISSET(cli.in, &efd))
{
LOG("!!! select() on in: %s\n",
strerror(errno));
exit(1);
}
if (FD_ISSET(cli.fd, &efd))
{
LOG("!!! select() on fd: %s\n",
strerror(errno));
exit(1);
}
if (FD_ISSET(cli.in, &rfd))
process_cli_data();
if (FD_ISSET(cli.fd, &rfd))
process_dect_data();
if( (cli.hop) &&
( (cli.mode & MODE_FPSCAN) ||
(cli.mode & MODE_PPSCAN) ||
(cli.mode & MODE_CALLSCAN) ||
(cli.mode & MODE_JAM ) ))
{
if ( time(NULL) > cli.last_hop + cli.hop_ch_time )
{
cli.channel++;
if (cli.channel > cli.hop_end)
cli.channel = cli.hop_start;
set_channel(cli.channel);
}
}
if (cli.autorec)
{
if ( (time (NULL) - cli.autorec_last_bfield
> cli.autorec_timeout)
&&
(cli.mode != MODE_CALLSCAN)
)
{
do_stop_keep_autorec();
do_callscan();
if (cli.pcap)
{
pcap_dump_close(cli.pcap_d);
pcap_close(cli.pcap);
cli.pcap_d = NULL;
cli.pcap = NULL;
cli.hop = 1;
}
}
}
}
}
int main(int argc, char ** argv)
{
init();
/* make stdout unbuffered */
setvbuf(stdout,(char*)NULL,_IONBF,0);
printf("DECT command line interface\n");
printf("type \"help\" if you're lost\n");
mainloop();
return 0;
}