280 lines
6.9 KiB
C++
280 lines
6.9 KiB
C++
/*
|
|
This file is part of Kismet
|
|
|
|
Kismet 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 2 of the License, or
|
|
(at your option) any later version.
|
|
|
|
Kismet 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 Kismet; if not, write to the Free Software
|
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
|
|
DECT source v2
|
|
(c) 2008 by Mike Kershaw <dragorn (at) kismetwireless (dot) net,
|
|
Jacob Appelbaum <jacob (at) appelbaum (dot) net,
|
|
Christian Fromme <kaner (at) strace (dot) org
|
|
*/
|
|
|
|
#include "config.h"
|
|
|
|
#include <packetsource.h>
|
|
#include "packet_dect.h"
|
|
#include "packetsource_dect.h"
|
|
|
|
PacketSource_Dect::PacketSource_Dect(GlobalRegistry *in_globalreg):
|
|
KisPacketSource(in_globalreg) {
|
|
|
|
serial_fd = -1;
|
|
sync = false;
|
|
scan_mode = MODE_ASYNC_FP_SCAN;
|
|
}
|
|
|
|
PacketSource_Dect::PacketSource_Dect(GlobalRegistry *in_globalreg, string in_interface,
|
|
vector<opt_pair> *in_opts) :
|
|
KisPacketSource(in_globalreg, in_interface, in_opts) {
|
|
|
|
serial_fd = -1;
|
|
sync = false;
|
|
scan_mode = -1;
|
|
|
|
ParseOptions(in_opts);
|
|
}
|
|
|
|
PacketSource_Dect::~PacketSource_Dect() {
|
|
if (serial_fd >= 0) {
|
|
close(serial_fd);
|
|
serial_fd = -1;
|
|
}
|
|
}
|
|
|
|
int PacketSource_Dect::AutotypeProbe(string in_device) {
|
|
if (StrLower(in_device) == "dect") {
|
|
type = "dect";
|
|
return 1;
|
|
}
|
|
|
|
if (StrLower(in_device) == "dectus") {
|
|
type = "dectus";
|
|
return 1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int PacketSource_Dect::ParseOptions(vector<opt_pair> *in_opts) {
|
|
if ((serialdevice = FetchOpt("device", in_opts)) == "") {
|
|
_MSG("DECT packet source defaulting to default serial /dev/coa",
|
|
MSGFLAG_INFO);
|
|
serialdevice = "/dev/coa";
|
|
} else {
|
|
_MSG("DECT packet source using serial device " + serialdevice,
|
|
MSGFLAG_INFO);
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
int PacketSource_Dect::FetchDescriptor() {
|
|
return serial_fd;
|
|
}
|
|
|
|
int PacketSource_Dect::SetChannel(unsigned int in_ch) {
|
|
if (ioctl(serial_fd, COA_IOCTL_CHAN, &in_ch)) {
|
|
_MSG("DECT packet source '" + name + "': Failed to set channel: " +
|
|
string(strerror(errno)), MSGFLAG_ERROR);
|
|
return 0;
|
|
}
|
|
|
|
last_channel = in_ch;
|
|
|
|
// printf("debug - dect set channel %u\n", in_ch);
|
|
|
|
return 1;
|
|
}
|
|
|
|
int PacketSource_Dect::StartScanPp(mac_addr in_rfpi) {
|
|
if (serial_fd == -1)
|
|
return -1;
|
|
|
|
/* always accept mode set since we might change RFPI */
|
|
/* remove the sync early since we've disrupted the state of the world */
|
|
|
|
if (sync) {
|
|
sync = false;
|
|
}
|
|
|
|
/* Set sync sniff mode */
|
|
uint16_t val;
|
|
val = COA_MODE_SNIFF | COA_SUBMODE_SNIFF_SYNC;
|
|
if (ioctl(serial_fd, COA_IOCTL_MODE, &val)) {
|
|
_MSG("DECT packet source '" + name + "': Failed to set sniffer mode PP: " +
|
|
string(strerror(errno)), MSGFLAG_ERROR);
|
|
return -1;
|
|
}
|
|
|
|
/* set RFPI to sync with */
|
|
uint8_t mrfpi[5];
|
|
for (unsigned int x = 0; x < 5; x++)
|
|
mrfpi[x] = in_rfpi[x];
|
|
|
|
if (ioctl(serial_fd, COA_IOCTL_SETRFPI, mrfpi)) {
|
|
_MSG("DECT packet source '" + name + "': Failed to set PP RFPI: " +
|
|
string(strerror(errno)), MSGFLAG_ERROR);
|
|
return -1;
|
|
}
|
|
|
|
scan_mode = MODE_ASYNC_PP_SCAN;
|
|
|
|
// Caller should turn off PST channel hopping and set channel
|
|
// globalreg->sourcetracker->SetSourceHopping(FetchUUID(), 0, 0);
|
|
|
|
return 1;
|
|
}
|
|
|
|
int PacketSource_Dect::StartScanCalls(mac_addr in_rfpi, int in_channel) {
|
|
if (serial_fd == -1)
|
|
return -1;
|
|
|
|
if (sync)
|
|
sync = false;
|
|
|
|
/* Set sync sniff mode */
|
|
uint16_t val;
|
|
|
|
val = COA_MODE_SNIFF | COA_SUBMODE_SNIFF_SYNC;
|
|
|
|
if (ioctl(serial_fd, COA_IOCTL_MODE, &val)) {
|
|
_MSG("DECT packet source '" + name + "': Failed to set sniffer mode SYNC: " +
|
|
string(strerror(errno)), MSGFLAG_ERROR);
|
|
return -1;
|
|
}
|
|
|
|
/* set RFPI we're syncing to */
|
|
uint8_t mrfpi[5];
|
|
for (unsigned int x = 0; x < 5; x++)
|
|
mrfpi[x] = in_rfpi[x];
|
|
|
|
if (ioctl(serial_fd, COA_IOCTL_SETRFPI, mrfpi)) {
|
|
_MSG("DECT packet source '" + name + "': Failed to set sniffer sync RFPI: " +
|
|
string(strerror(errno)), MSGFLAG_ERROR);
|
|
return -1;
|
|
}
|
|
|
|
scan_mode = MODE_SYNC_CALL_SCAN;
|
|
|
|
// Caller should turn off PST channel hopping
|
|
// globalreg->sourcetracker->SetSourceHopping(FetchUUID(), 0, in_channel);
|
|
|
|
return 1;
|
|
}
|
|
|
|
int PacketSource_Dect::StartScanFp() {
|
|
if (serial_fd == -1)
|
|
return -1;
|
|
|
|
if (scan_mode == MODE_ASYNC_FP_SCAN)
|
|
return 0;
|
|
|
|
/* start sniffer mode */
|
|
int val = COA_MODE_SNIFF | COA_SUBMODE_SNIFF_SCANFP;
|
|
|
|
if (ioctl(serial_fd, COA_IOCTL_MODE, &val)) {
|
|
_MSG("DECT packet source '" + name + "': Failed to set sniffer scan FP: " +
|
|
string(strerror(errno)), MSGFLAG_ERROR);
|
|
return -1;
|
|
}
|
|
|
|
scan_mode = MODE_ASYNC_FP_SCAN;
|
|
|
|
if (sync)
|
|
sync = false;
|
|
|
|
// Caller should turn on hopping
|
|
// globalreg->sourcetracker->SetSourceHopping(FetchUUID(), 1, 0);
|
|
|
|
return 1;
|
|
}
|
|
|
|
int PacketSource_Dect::OpenSource() {
|
|
if ((serial_fd = open(serialdevice.c_str(), O_RDONLY)) == -1) {
|
|
_MSG("DECT packet source '" + name + "': Failed to open DECT serial device: " +
|
|
string(strerror(errno)), MSGFLAG_ERROR);
|
|
return 0;
|
|
}
|
|
|
|
return StartScanFp();
|
|
}
|
|
|
|
int PacketSource_Dect::CloseSource() {
|
|
if (serial_fd >= 0) {
|
|
close(serial_fd);
|
|
serial_fd = -1;
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
int PacketSource_Dect::Poll() {
|
|
unsigned char buf[7];
|
|
int rbytes = -1;
|
|
dect_packinfo *pi = new dect_packinfo;
|
|
kis_packet *newpack;
|
|
kis_datachunk *callchunk = NULL;
|
|
|
|
pi->sync = sync;
|
|
pi->scanmode = scan_mode;
|
|
pi->channel = FetchChannel();
|
|
|
|
if (scan_mode == MODE_ASYNC_FP_SCAN || scan_mode == MODE_ASYNC_PP_SCAN) {
|
|
if ((rbytes = read(serial_fd, &(pi->sdata), sizeof(dect_data_scan_t))) !=
|
|
sizeof(dect_data_scan_t)) {
|
|
_MSG("DECT packet source '" + name + "': Failed to read scan data: " +
|
|
string(strerror(errno)), MSGFLAG_ERROR);
|
|
delete(pi);
|
|
return 0;
|
|
}
|
|
} else if (scan_mode == MODE_SYNC_CALL_SCAN) {
|
|
if ((rbytes = read(serial_fd, &(pi->pdata), sizeof(pp_packet_t))) !=
|
|
sizeof(pp_packet_t)) {
|
|
_MSG("DECT packet source '" + name + "': Failed to read scan data: " +
|
|
string(strerror(errno)), MSGFLAG_ERROR);
|
|
delete(pi);
|
|
return 0;
|
|
} else {
|
|
if (!sync) {
|
|
_MSG("DECT packet source '" + name + "': Synced to call", MSGFLAG_INFO);
|
|
sync = true;
|
|
}
|
|
|
|
// Make a data chunk
|
|
callchunk = new kis_datachunk;
|
|
callchunk->length = 53;
|
|
callchunk->data = new uint8_t[callchunk->length];
|
|
memcpy(callchunk->data, pi->pdata.data, callchunk->length);
|
|
callchunk->source_id = source_id;
|
|
callchunk->dlt = KDLT_DECT;
|
|
}
|
|
} else {
|
|
// Unknown mode during poll
|
|
delete(pi);
|
|
return 0;
|
|
}
|
|
|
|
newpack = globalreg->packetchain->GeneratePacket();
|
|
newpack->insert(pack_comp_dect, pi);
|
|
if (callchunk)
|
|
newpack->insert(_PCM(PACK_COMP_LINKFRAME), callchunk);
|
|
globalreg->packetchain->ProcessPacket(newpack);
|
|
|
|
// printf("debug - dect newpack\n");
|
|
|
|
return 1;
|
|
}
|
|
|