Professional Documents
Culture Documents
/*
*
*
*
*
*
*
*
*
*
*
*
*
*/
#include
#include
#include
#include
#include
"lib.h"
"wifibroadcast.h"
"radiotap.h"
<pthread.h>
<limits.h>
usage(void)
{
printf(
"(c)2015 befinitiv. Based on packetspammer by Andy Green. Licensed
under GPL2\n"
"\n"
"Usage: rx [options] <interfaces>\n\nOptions\n"
"-p <port> Port number 0-255 (default 0)\n"
"-b <block_numsize> Number of packets in a retransmissio
n block (default 1). "
"Needs to match with tx.\n"
"Example:\n"
" echo -n mon0 > /sys/class/ieee80211/phy0/add_iface\n"
" iwconfig mon0 mode monitor\n"
" ifconfig mon0 up\n"
" rx mon0
Receive raw packets on mon0 and output the payload
to stdout\n"
"\n");
exit(1);
}
void open_and_configure_interface(const char *name, int port, monitor_interface_
t *interface) {
struct bpf_program bpfprogram;
char szProgram[512];
char szErrbuf[PCAP_ERRBUF_SIZE];
// open the interface in pcap
szErrbuf[0] = '\0';
strcpy(interface->name, name);
interface->last_block_num = -1;
interface->num_sent = 0;
interface->num_lost = 0;
interface->ppcap = pcap_open_live(name, 2048, 1, 0, szErrbuf);
if (interface->ppcap == NULL) {
fprintf(stderr, "Unable to open interface %s in pcap: %s\n",
name, szErrbuf);
exit(1);
}
if(pcap_setnonblock(interface->ppcap, 0, szErrbuf) < 0) {
fprintf(stderr, "Error setting %s to nonblocking mode: %s\n", na
me, szErrbuf);
}
int nLinkEncap = pcap_datalink(interface->ppcap);
switch (nLinkEncap) {
case DLT_PRISM_HEADER:
fprintf(stderr, "DLT_PRISM_HEADER Encap [%s]\n", interfa
ce->name);
interface->n80211HeaderLength = 0x20; // ieee80211 comes
after this
sprintf(szProgram, "radio[0x4a:4]==0x13223344 && radio[0
x4e:2] == 0x55%.2x", port);
break;
case DLT_IEEE802_11_RADIO:
case IEEE80211_RADIOTAP_FLAGS:
prd.m_nRadiotapFlags = *rti.this_arg;
break;
}
}
pu8Payload += u16HeaderLen + interface->n80211HeaderLength;
if (prd.m_nRadiotapFlags & IEEE80211_RADIOTAP_F_FCS)
bytes -= 4;
checksum_correct = (prd.m_nRadiotapFlags & 0x40) == 0;
//first 4 bytes are the sequence number
seq_nr = *(uint32_t*)pu8Payload;
pu8Payload += 4;
bytes -= 4;
block_num = seq_nr / param_retransmission_block_size;
//handle case where block_num arrived malformed or stream has re
started
if(abs((block_num - last_block_written)) > 5000
&& last_block_written != 0) {
if(block_num < last_block_written) { //did the stream re
start??
newblocks++;
pthread_mutex_lock(&thread_mutex);
if(newblocks > 100) {
last_block_written = block_num;
}
pthread_mutex_unlock(&thread_mutex);
}
return;
}
newblocks = 0;
//calculate any errors
if(checksum_correct
&& interface->last_block_num >= 0
&& (block_num > interface->last_block_num + 1)) {
int lost_block_nums = block_num - interface->last_block_
num - 1;
interface->num_lost += lost_block_nums * param_retransmi
ssion_block_size;
interface->num_sent += lost_block_nums * param_retransmi
ssion_block_size;
fprintf(stderr, "[%s] Lost %d blocks! Lossrate %f\t(%d /
%d)\n",
interface->name, block_num - interface->last_blo
ck_num - 1,
1.0 * interface->num_lost/interface->num_sent, i
nterface->num_lost,
interface->num_sent);
}
//safety first: we only go to the next block if the FCS is corre
ct
if(checksum_correct && block_num > interface->last_block_num)
interface->last_block_num = block_num;
packet_num = seq_nr % param_retransmission_block_size;
pthread_mutex_lock(&thread_mutex);
packet_buffer_t *packet_buffer_list = NULL;
int a;
int o;
int lb = INT_MAX;
for(a=0; a<BLOCKCACHE_SIZE; a++) {
if(block_nums[a] == block_num) {
fprintf(stderr, "%s match block=%d last_block_wr
itten=%d crc=%d\n",
interface->name, block_num, last_block_w
ritten, checksum_correct);
packet_buffer_list = packet_buffer_list_cache[a]
;
break;
}
if(block_nums[a] < lb) {
lb = block_nums[a];
o = a;
}
}
if(packet_buffer_list == NULL) {
if(block_nums[o] > last_block_written) {
fprintf(stderr, "%s writing block=%d, newblock=%
d\n", interface->name,
block_nums[o], block_num);
if(block_nums[o]-1 != last_block_written
&& last_block_written != 0) {
fprintf(stderr, "ERROR: lost block [%d]\
n", (block_nums[o]-1));
packet_buffer_list = packet_buffer_list_
cache[o];
packet_buffer_list[packet_num].valid = 1
;
//fill in lost block (hopefully more goo
d than harm)
writeblock(interface, packet_buffer_list
, block_nums[o]);
}
writeblock(interface, packet_buffer_list_cache[o
], block_nums[o]);
last_block_written = block_nums[o];
}
packet_buffer_list = packet_buffer_list_cache[o];
block_nums[o] = block_num;
}
int g = 1;
if(packet_buffer_list[packet_num].crc_correct && !checksum_corre
ct) {
//fprintf(stderr, "[%s] corruption averted (%d)\n", inte
rface->name, block_num);
g = 0;
}
if(g) {
memcpy(packet_buffer_list[packet_num].data, pu8Payload,
bytes);
packet_buffer_list[packet_num].len = bytes;
packet_buffer_list[packet_num].valid = 1;
packet_buffer_list[packet_num].crc_correct = checksum_co
rrect;
}
pthread_mutex_unlock(&thread_mutex);
return;
}
void *capture(void *i) {
monitor_interface_t *interface = (monitor_interface_t*)i;
for(;;) {
process_packet(interface);
}
}
int
main(int argc, char *argv[])
{
monitor_interface_t interfaces[MAX_PENUMBRA_INTERFACES];
int num_interfaces = 0;
memset(block_nums, 0, sizeof(block_nums));
while (1) {
int nOptionIndex;
static const struct option optiona[] = {
{ "help", no_argument, &flagHelp, 1 },
{ 0, 0, 0, 0 }
};
int c = getopt_long(argc, argv, "hp:b:",
optiona, &nOptionIndex);
if (c == -1)
break;
switch (c) {
case 0: //long option
break;
case 'h': //help
usage();
case 'p': //port
param_port = atoi(optarg);
break;
case 'b': //retransmission block size
param_retransmission_block_size = atoi(optarg);
break;
default:
fprintf(stderr, "unknown switch %c\n", c);
usage();
break;
}
}
if (optind >= argc)
usage();
int a;
for(a=0; a<BLOCKCACHE_SIZE; a++) {
packet_buffer_list_cache[a] = lib_alloc_packet_buffer_list(param
_retransmission_block_size,
MAX_PACKET_LENGTH);
}
int x = optind;
while(x < argc && num_interfaces < MAX_PENUMBRA_INTERFACES) {
open_and_configure_interface(argv[x], param_port, interfaces + n
um_interfaces);
pthread_t tid;
pthread_create(&tid, NULL, capture, interfaces + num_interfaces)
;
++num_interfaces;
++x;
}
sleep(1000000L);
return (0);
}