Files
gr-ieee802-11/utils/packetspammer/packetspammer.c
T
Bastian Bloessl 8e266d3f5c init
2013-03-24 17:34:51 +01:00

389 lines
8.9 KiB
C

// (c)2007 Andy Green <andy@warmcat.com>
/*
* This program 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; version 2.
*
* This program 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 this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
// Thanks for contributions:
// 2007-03-15 fixes to getopt_long code by Matteo Croce rootkit85@yahoo.it
#include "packetspammer.h"
#include "radiotap.h"
/* wifi bitrate to use in 500kHz units */
static const u8 u8aRatesToUse[] = {
54*2,
48*2,
36*2,
24*2,
18*2,
12*2,
9*2,
11*2,
11, // 5.5
2*2,
1*2
};
/* this is the template radiotap header we send packets out with */
static const u8 u8aRadiotapHeader[] = {
0x00, 0x00, // <-- radiotap version
0x16, 0x00, // <- radiotap header length
0x0f, 0x00, 0x00, 0x00, // <-- bitmap
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // <-- timestamp
0x00, // <-- flags (Offset +0x10)
0x6c, // <-- rate (0ffset +0x11)
0x64, 0x14, 0x40, 0x01, // <-- channel
// 0x00, // <-- antsignal
// 0x00, // <-- antnoise
// 0x00, // <-- antenna
};
#define OFFSET_FLAGS 0x10
#define OFFSET_RATE 0x11
/* Penumbra IEEE80211 header */
static const u8 u8aIeeeHeader[] = {
0x08, 0x01, 0x00, 0x00,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0x13, 0x22, 0x33, 0x44, 0x55, 0x66,
0x13, 0x22, 0x33, 0x44, 0x55, 0x66,
0x10, 0x86,
};
// this is where we store a summary of the
// information from the radiotap header
typedef struct {
int m_nChannel;
int m_nChannelFlags;
int m_nRate;
int m_nAntenna;
int m_nRadiotapFlags;
} __attribute__((packed)) PENUMBRA_RADIOTAP_DATA;
int flagHelp = 0, flagMarkWithFCS = 0;
void
Dump(u8 * pu8, int nLength)
{
char sz[256], szBuf[512], szChar[17], *buf, fFirst = 1;
unsigned char baaLast[2][16];
uint n, nPos = 0, nStart = 0, nLine = 0, nSameCount = 0;
buf = szBuf;
szChar[0] = '\0';
for (n = 0; n < nLength; n++) {
baaLast[(nLine&1)^1][n&0xf] = pu8[n];
if ((pu8[n] < 32) || (pu8[n] >= 0x7f))
szChar[n&0xf] = '.';
else
szChar[n&0xf] = pu8[n];
szChar[(n&0xf)+1] = '\0';
nPos += sprintf(&sz[nPos], "%02X ",
baaLast[(nLine&1)^1][n&0xf]);
if ((n&15) != 15)
continue;
if ((memcmp(baaLast[0], baaLast[1], 16) == 0) && (!fFirst)) {
nSameCount++;
} else {
if (nSameCount)
buf += sprintf(buf, "(repeated %d times)\n",
nSameCount);
buf += sprintf(buf, "%04x: %s %s\n",
nStart, sz, szChar);
nSameCount = 0;
printf("%s", szBuf);
buf = szBuf;
}
nPos = 0; nStart = n+1; nLine++;
fFirst = 0; sz[0] = '\0'; szChar[0] = '\0';
}
if (nSameCount)
buf += sprintf(buf, "(repeated %d times)\n", nSameCount);
buf += sprintf(buf, "%04x: %s", nStart, sz);
if (n & 0xf) {
*buf++ = ' ';
while (n & 0xf) {
buf += sprintf(buf, " ");
n++;
}
}
buf += sprintf(buf, "%s\n", szChar);
printf("%s", szBuf);
}
void
usage(void)
{
printf(
"(c)2006-2007 Andy Green <andy@warmcat.com> Licensed under GPL2\n"
"\n"
"Usage: packetspammer [options] <interface>\n\nOptions\n"
"-d/--delay <delay> Delay between packets\n\n"
"-f/--fcs Mark as having FCS (CRC) already\n"
" (pkt ends with 4 x sacrificial - chars)\n"
"Example:\n"
" echo -n mon0 > /sys/class/ieee80211/phy0/add_iface\n"
" iwconfig mon0 mode monitor\n"
" ifconfig mon0 up\n"
" packetspammer mon0 Spam down mon0 with\n"
" radiotap header first\n"
"\n");
exit(1);
}
int
main(int argc, char *argv[])
{
u8 u8aSendBuffer[500];
char szErrbuf[PCAP_ERRBUF_SIZE];
int nCaptureHeaderLength = 0, n80211HeaderLength = 0, nLinkEncap = 0;
int nOrdinal = 0, r, nDelay = 100000;
int nRateIndex = 0, retval, bytes;
pcap_t *ppcap = NULL;
struct bpf_program bpfprogram;
char * szProgram = "", fBrokenSocket = 0;
u16 u16HeaderLen;
char szHostname[PATH_MAX];
if (gethostname(szHostname, sizeof (szHostname) - 1)) {
perror("unable to get hostname");
}
szHostname[sizeof (szHostname) - 1] = '\0';
printf("Packetspammer (c)2007 Andy Green <andy@warmcat.com> GPL2\n");
while (1) {
int nOptionIndex;
static const struct option optiona[] = {
{ "delay", required_argument, NULL, 'd' },
{ "fcs", no_argument, &flagMarkWithFCS, 1 },
{ "help", no_argument, &flagHelp, 1 },
{ 0, 0, 0, 0 }
};
int c = getopt_long(argc, argv, "d:hf",
optiona, &nOptionIndex);
if (c == -1)
break;
switch (c) {
case 0: // long option
break;
case 'h': // help
usage();
case 'd': // delay
nDelay = atoi(optarg);
break;
case 'f': // mark as FCS attached
flagMarkWithFCS = 1;
break;
default:
printf("unknown switch %c\n", c);
usage();
break;
}
}
if (optind >= argc)
usage();
// open the interface in pcap
szErrbuf[0] = '\0';
ppcap = pcap_open_live(argv[optind], 800, 1, 20, szErrbuf);
if (ppcap == NULL) {
printf("Unable to open interface %s in pcap: %s\n",
argv[optind], szErrbuf);
return (1);
}
nLinkEncap = pcap_datalink(ppcap);
nCaptureHeaderLength = 0;
switch (nLinkEncap) {
case DLT_PRISM_HEADER:
printf("DLT_PRISM_HEADER Encap\n");
nCaptureHeaderLength = 0x40;
n80211HeaderLength = 0x20; // ieee80211 comes after this
szProgram = "radio[0x4a:4]==0x13223344";
break;
case DLT_IEEE802_11_RADIO:
printf("DLT_IEEE802_11_RADIO Encap\n");
nCaptureHeaderLength = 0x40;
n80211HeaderLength = 0x18; // ieee80211 comes after this
szProgram = "ether[0x0a:4]==0x13223344";
break;
default:
printf("!!! unknown encapsulation on %s !\n", argv[1]);
return (1);
}
if (pcap_compile(ppcap, &bpfprogram, szProgram, 1, 0) == -1) {
puts(szProgram);
puts(pcap_geterr(ppcap));
return (1);
} else {
if (pcap_setfilter(ppcap, &bpfprogram) == -1) {
puts(szProgram);
puts(pcap_geterr(ppcap));
} else {
printf("RX Filter applied\n");
}
pcap_freecode(&bpfprogram);
}
pcap_setnonblock(ppcap, 1, szErrbuf);
printf(" (delay between packets %dus)\n", nDelay);
memset(u8aSendBuffer, 0, sizeof (u8aSendBuffer));
while (!fBrokenSocket) {
u8 * pu8 = u8aSendBuffer;
struct pcap_pkthdr * ppcapPacketHeader = NULL;
struct ieee80211_radiotap_iterator rti;
PENUMBRA_RADIOTAP_DATA prd;
u8 * pu8Payload = u8aSendBuffer;
int n, nRate;
// receive
retval = pcap_next_ex(ppcap, &ppcapPacketHeader,
(const u_char**)&pu8Payload);
if (retval < 0) {
fBrokenSocket = 1;
continue;
}
if (retval != 1)
goto do_tx;
u16HeaderLen = (pu8Payload[2] + (pu8Payload[3] << 8));
printf("rtap: ");
Dump(pu8Payload, u16HeaderLen);
if (ppcapPacketHeader->len <
(u16HeaderLen + n80211HeaderLength))
continue;
bytes = ppcapPacketHeader->len -
(u16HeaderLen + n80211HeaderLength);
if (bytes < 0)
continue;
if (ieee80211_radiotap_iterator_init(&rti,
(struct ieee80211_radiotap_header *)pu8Payload,
bytes) < 0)
continue;
while ((n = ieee80211_radiotap_iterator_next(&rti)) == 0) {
switch (rti.this_arg_index) {
case IEEE80211_RADIOTAP_RATE:
prd.m_nRate = (*rti.this_arg);
break;
case IEEE80211_RADIOTAP_CHANNEL:
prd.m_nChannel =
le16_to_cpu(*((u16 *)rti.this_arg));
prd.m_nChannelFlags =
le16_to_cpu(*((u16 *)(rti.this_arg + 2)));
break;
case IEEE80211_RADIOTAP_ANTENNA:
prd.m_nAntenna = (*rti.this_arg) + 1;
break;
case IEEE80211_RADIOTAP_FLAGS:
prd.m_nRadiotapFlags = *rti.this_arg;
break;
}
}
pu8Payload += u16HeaderLen + n80211HeaderLength;
if (prd.m_nRadiotapFlags & IEEE80211_RADIOTAP_F_FCS)
bytes -= 4;
printf("RX: Rate: %2d.%dMbps, Freq: %d.%dGHz, "
"Ant: %d, Flags: 0x%X\n",
prd.m_nRate / 2, 5 * (prd.m_nRate & 1),
prd.m_nChannel / 1000,
prd.m_nChannel - ((prd.m_nChannel / 1000) * 1000),
prd.m_nAntenna,
prd.m_nRadiotapFlags);
Dump(pu8Payload, bytes);
do_tx:
// transmit
memcpy(u8aSendBuffer, u8aRadiotapHeader,
sizeof (u8aRadiotapHeader));
if (flagMarkWithFCS)
pu8[OFFSET_FLAGS] |= IEEE80211_RADIOTAP_F_FCS;
nRate = pu8[OFFSET_RATE] = u8aRatesToUse[nRateIndex++];
if (nRateIndex >= sizeof (u8aRatesToUse))
nRateIndex = 0;
pu8 += sizeof (u8aRadiotapHeader);
memcpy(pu8, u8aIeeeHeader, sizeof (u8aIeeeHeader));
pu8 += sizeof (u8aIeeeHeader);
pu8 += sprintf((char *)pu8,
"Packetspammer %02d"
"broadcast packet"
"#%05d -- :-D --%s ----",
nRate/2, nOrdinal++, szHostname);
r = pcap_inject(ppcap, u8aSendBuffer, pu8 - u8aSendBuffer);
if (r != (pu8-u8aSendBuffer)) {
perror("Trouble injecting packet");
return (1);
}
if (nDelay)
usleep(nDelay);
}
return (0);
}