xref: /openwifi/user_space/inject_80211/inject_80211.c (revision 7273ec43e17ceddce2fc08da166686f9b26c5c00)
1*7273ec43Smmehari // (c)2007 Andy Green <[email protected]>
2*7273ec43Smmehari // (r)2020 Michael Tetemke Mehari <[email protected]>
3*7273ec43Smmehari 
4*7273ec43Smmehari /*
5*7273ec43Smmehari  *   This program is free software; you can redistribute it and/or modify
6*7273ec43Smmehari  *   it under the terms of the GNU General Public License as published by
7*7273ec43Smmehari  *   the Free Software Foundation; version 2.
8*7273ec43Smmehari  *
9*7273ec43Smmehari  *   This program is distributed in the hope that it will be useful,
10*7273ec43Smmehari  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
11*7273ec43Smmehari  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12*7273ec43Smmehari  *   GNU General Public License for more details.
13*7273ec43Smmehari  *
14*7273ec43Smmehari  *   You should have received a copy of the GNU General Public License along
15*7273ec43Smmehari  *   with this program; if not, write to the Free Software Foundation, Inc.,
16*7273ec43Smmehari  *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17*7273ec43Smmehari  */
18*7273ec43Smmehari 
19*7273ec43Smmehari // Thanks for contributions:
20*7273ec43Smmehari // 2007-03-15 fixes to getopt_long code by Matteo Croce [email protected]
21*7273ec43Smmehari 
22*7273ec43Smmehari #include "inject_80211.h"
23*7273ec43Smmehari #include "radiotap.h"
24*7273ec43Smmehari 
25*7273ec43Smmehari /* wifi bitrate to use in 500kHz units */
26*7273ec43Smmehari static const u8 u8aRatesToUse[] = {
27*7273ec43Smmehari 	6*2,
28*7273ec43Smmehari 	9*2,
29*7273ec43Smmehari 	12*2,
30*7273ec43Smmehari 	18*2,
31*7273ec43Smmehari 	24*2,
32*7273ec43Smmehari 	36*2,
33*7273ec43Smmehari 	48*2,
34*7273ec43Smmehari 	54*2
35*7273ec43Smmehari };
36*7273ec43Smmehari 
37*7273ec43Smmehari /* this is the template radiotap header we send packets out with */
38*7273ec43Smmehari static const u8 u8aRadiotapHeader[] =
39*7273ec43Smmehari {
40*7273ec43Smmehari 	0x00, 0x00, // <-- radiotap version
41*7273ec43Smmehari 	0x1c, 0x00, // <- radiotap header length
42*7273ec43Smmehari 	0x6f, 0x08, 0x08, 0x00, // <-- bitmap
43*7273ec43Smmehari 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // <-- timestamp
44*7273ec43Smmehari 	0x00, // <-- flags (Offset +0x10)
45*7273ec43Smmehari 	0x6c, // <-- rate (0ffset +0x11)
46*7273ec43Smmehari 	0x71, 0x09, 0xc0, 0x00, // <-- channel
47*7273ec43Smmehari 	0xde, // <-- antsignal
48*7273ec43Smmehari 	0x00, // <-- antnoise
49*7273ec43Smmehari 	0x01, // <-- antenna
50*7273ec43Smmehari 	0x02, 0x00, 0x0f,  // <-- MCS
51*7273ec43Smmehari };
52*7273ec43Smmehari 
53*7273ec43Smmehari #define	OFFSET_RATE 0x11
54*7273ec43Smmehari #define MCS_OFFSET 0x19
55*7273ec43Smmehari #define GI_OFFSET 0x1a
56*7273ec43Smmehari #define MCS_RATE_OFFSET 0x1b
57*7273ec43Smmehari 
58*7273ec43Smmehari /* IEEE80211 header */
59*7273ec43Smmehari static const u8 ieee_hdr[] =
60*7273ec43Smmehari {
61*7273ec43Smmehari 	0x08, 0x01, 0x00, 0x00,
62*7273ec43Smmehari 	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
63*7273ec43Smmehari 	0x66, 0x55, 0x44, 0x33, 0x22, 0x11,
64*7273ec43Smmehari 	0x66, 0x55, 0x44, 0x33, 0x22, 0x11,
65*7273ec43Smmehari 	0x10, 0x86,
66*7273ec43Smmehari };
67*7273ec43Smmehari 
68*7273ec43Smmehari // Generate random string
69*7273ec43Smmehari void gen_rand_str(int size, char *rand_char)
70*7273ec43Smmehari {
71*7273ec43Smmehari 	int i, randNum = 0;
72*7273ec43Smmehari 
73*7273ec43Smmehari 	// Seed the random number generator with packet size
74*7273ec43Smmehari 	srand(size);
75*7273ec43Smmehari 	for (i = 0; i < size; i++)
76*7273ec43Smmehari 	{
77*7273ec43Smmehari 		// First, pick a number between 0 and 25.
78*7273ec43Smmehari 		randNum = 255 * (rand() / (RAND_MAX + 1.0));
79*7273ec43Smmehari 
80*7273ec43Smmehari 		if(randNum == 0)
81*7273ec43Smmehari 		{
82*7273ec43Smmehari 			i--;
83*7273ec43Smmehari 			continue;
84*7273ec43Smmehari 		}
85*7273ec43Smmehari 
86*7273ec43Smmehari 		// Type cast to character
87*7273ec43Smmehari 		rand_char[i] = (char) randNum;
88*7273ec43Smmehari 	}
89*7273ec43Smmehari 	rand_char[i] = '\0';
90*7273ec43Smmehari }
91*7273ec43Smmehari 
92*7273ec43Smmehari int flagHelp = 0;
93*7273ec43Smmehari 
94*7273ec43Smmehari void usage(void)
95*7273ec43Smmehari {
96*7273ec43Smmehari 	printf(
97*7273ec43Smmehari 	    "(c)2006-2007 Andy Green <[email protected]>  Licensed under GPL2\n"
98*7273ec43Smmehari 		"(r)2020 Michael Tetemke Mehari <[email protected]>"
99*7273ec43Smmehari 	    "\n"
100*7273ec43Smmehari 	    "Usage: inject_80211 [options] <interface>\n\nOptions\n"
101*7273ec43Smmehari 	    "-m/--hw_mode <hardware operation mode> (a,g,n)\n"
102*7273ec43Smmehari 	    "-r/--rate_index <rate/MCS index> (0,1,2,3,4,5,6,7)\n"
103*7273ec43Smmehari 	    "-i/--sgi_flag (0,1)\n"
104*7273ec43Smmehari 	    "-n/--num_packets <number of packets>\n"
105*7273ec43Smmehari 	    "-s/--payload_size <payload size in bytes>\n"
106*7273ec43Smmehari 	    "-d/--delay <delay between packets in usec>\n"
107*7273ec43Smmehari 	    "-h   this menu\n\n"
108*7273ec43Smmehari 
109*7273ec43Smmehari 	    "Example:\n"
110*7273ec43Smmehari 	    "  iw dev wlan0 interface add mon0 type monitor && ifconfig mon0 up\n"
111*7273ec43Smmehari 	    "  inject_80211 mon0\n"
112*7273ec43Smmehari 	    "\n");
113*7273ec43Smmehari 	exit(1);
114*7273ec43Smmehari }
115*7273ec43Smmehari 
116*7273ec43Smmehari 
117*7273ec43Smmehari int main(int argc, char *argv[])
118*7273ec43Smmehari {
119*7273ec43Smmehari 	u8 buffer[1536];
120*7273ec43Smmehari 	char szErrbuf[PCAP_ERRBUF_SIZE], rand_char[1536], hw_mode = 'n';
121*7273ec43Smmehari 	int i, nLinkEncap = 0, r, rate_index = 0, sgi_flag = 0, num_packets = 10, payload_size = 64, packet_size, nDelay = 100000;
122*7273ec43Smmehari 	pcap_t *ppcap = NULL;
123*7273ec43Smmehari 
124*7273ec43Smmehari 	while (1)
125*7273ec43Smmehari 	{
126*7273ec43Smmehari 		int nOptionIndex;
127*7273ec43Smmehari 		static const struct option optiona[] =
128*7273ec43Smmehari 		{
129*7273ec43Smmehari 			{ "hw_mode", required_argument, NULL, 'm' },
130*7273ec43Smmehari 			{ "rate_index", required_argument, NULL, 'r' },
131*7273ec43Smmehari 			{ "sgi_flag", no_argument, NULL, 'i' },
132*7273ec43Smmehari 			{ "num_packets", required_argument, NULL, 'n' },
133*7273ec43Smmehari 			{ "payload_size", required_argument, NULL, 's' },
134*7273ec43Smmehari 			{ "delay", required_argument, NULL, 'd' },
135*7273ec43Smmehari 			{ "help", no_argument, &flagHelp, 1 },
136*7273ec43Smmehari 			{ 0, 0, 0, 0 }
137*7273ec43Smmehari 		};
138*7273ec43Smmehari 		int c = getopt_long(argc, argv, "m:r:i:n:s:d:h", optiona, &nOptionIndex);
139*7273ec43Smmehari 
140*7273ec43Smmehari 		if (c == -1)
141*7273ec43Smmehari 			break;
142*7273ec43Smmehari 		switch (c)
143*7273ec43Smmehari 		{
144*7273ec43Smmehari 			case 0: // long option
145*7273ec43Smmehari 				break;
146*7273ec43Smmehari 
147*7273ec43Smmehari 			case 'h':
148*7273ec43Smmehari 				usage();
149*7273ec43Smmehari 
150*7273ec43Smmehari 			case 'm':
151*7273ec43Smmehari 				hw_mode = optarg[0];
152*7273ec43Smmehari 				break;
153*7273ec43Smmehari 
154*7273ec43Smmehari 			case 'r':
155*7273ec43Smmehari 				rate_index = atoi(optarg);
156*7273ec43Smmehari 				break;
157*7273ec43Smmehari 
158*7273ec43Smmehari 			case 'i':
159*7273ec43Smmehari 				sgi_flag = atoi(optarg);
160*7273ec43Smmehari 				break;
161*7273ec43Smmehari 
162*7273ec43Smmehari 			case 'n':
163*7273ec43Smmehari 				num_packets = atoi(optarg);
164*7273ec43Smmehari 				break;
165*7273ec43Smmehari 
166*7273ec43Smmehari 			case 's':
167*7273ec43Smmehari 				payload_size = atoi(optarg);
168*7273ec43Smmehari 				break;
169*7273ec43Smmehari 
170*7273ec43Smmehari 			case 'd':
171*7273ec43Smmehari 				nDelay = atoi(optarg);
172*7273ec43Smmehari 				break;
173*7273ec43Smmehari 
174*7273ec43Smmehari 			default:
175*7273ec43Smmehari 				printf("unknown switch %c\n", c);
176*7273ec43Smmehari 				usage();
177*7273ec43Smmehari 				break;
178*7273ec43Smmehari 		}
179*7273ec43Smmehari 	}
180*7273ec43Smmehari 
181*7273ec43Smmehari 	if (optind >= argc)
182*7273ec43Smmehari 		usage();
183*7273ec43Smmehari 
184*7273ec43Smmehari 	// open the interface in pcap
185*7273ec43Smmehari 	szErrbuf[0] = '\0';
186*7273ec43Smmehari 	ppcap = pcap_open_live(argv[optind], 800, 1, 20, szErrbuf);
187*7273ec43Smmehari 	if (ppcap == NULL)
188*7273ec43Smmehari 	{
189*7273ec43Smmehari 		printf("Unable to open interface %s in pcap: %s\n", argv[optind], szErrbuf);
190*7273ec43Smmehari 		return (1);
191*7273ec43Smmehari 	}
192*7273ec43Smmehari 
193*7273ec43Smmehari 	nLinkEncap = pcap_datalink(ppcap);
194*7273ec43Smmehari 	switch (nLinkEncap)
195*7273ec43Smmehari 	{
196*7273ec43Smmehari 		case DLT_PRISM_HEADER:
197*7273ec43Smmehari 			printf("DLT_PRISM_HEADER Encap\n");
198*7273ec43Smmehari 			break;
199*7273ec43Smmehari 
200*7273ec43Smmehari 		case DLT_IEEE802_11_RADIO:
201*7273ec43Smmehari 			printf("DLT_IEEE802_11_RADIO Encap\n");
202*7273ec43Smmehari 			break;
203*7273ec43Smmehari 
204*7273ec43Smmehari 		default:
205*7273ec43Smmehari 			printf("!!! unknown encapsulation on %s !\n", argv[1]);
206*7273ec43Smmehari 			return (1);
207*7273ec43Smmehari 	}
208*7273ec43Smmehari 
209*7273ec43Smmehari 	pcap_setnonblock(ppcap, 1, szErrbuf);
210*7273ec43Smmehari 
211*7273ec43Smmehari 	// Generate random string
212*7273ec43Smmehari 	gen_rand_str(payload_size, rand_char);
213*7273ec43Smmehari 	packet_size = sizeof(u8aRadiotapHeader) + sizeof(ieee_hdr) + strlen(rand_char);
214*7273ec43Smmehari 	printf("mode = 802.11%c, rate index = %d, SHORT GI = %d, number of packets = %d and packet size = %d bytes, delay = %d usec\n", hw_mode, rate_index, sgi_flag, num_packets, packet_size, nDelay);
215*7273ec43Smmehari 
216*7273ec43Smmehari 	// Clear storage buffer
217*7273ec43Smmehari 	memset(buffer, 0, sizeof (buffer));
218*7273ec43Smmehari 
219*7273ec43Smmehari 	// Insert default radiotap header
220*7273ec43Smmehari 	memcpy(buffer, u8aRadiotapHeader, sizeof (u8aRadiotapHeader));
221*7273ec43Smmehari 	// Update radiotap header (i.e. hw_mode, rate, GI)
222*7273ec43Smmehari 	if(hw_mode == 'g' || hw_mode == 'a')
223*7273ec43Smmehari 	{
224*7273ec43Smmehari 		buffer[OFFSET_RATE] = u8aRatesToUse[rate_index];
225*7273ec43Smmehari 		buffer[MCS_OFFSET] = 0x00;
226*7273ec43Smmehari 	}
227*7273ec43Smmehari 	else
228*7273ec43Smmehari 	{
229*7273ec43Smmehari 		buffer[MCS_OFFSET] = 0x07;
230*7273ec43Smmehari 		if(sgi_flag)
231*7273ec43Smmehari 			buffer[GI_OFFSET] = IEEE80211_RADIOTAP_MCS_SGI;
232*7273ec43Smmehari 		buffer[MCS_RATE_OFFSET] = rate_index;
233*7273ec43Smmehari 	}
234*7273ec43Smmehari 	// Insert IEEE DATA header
235*7273ec43Smmehari 	memcpy(buffer + sizeof(u8aRadiotapHeader), ieee_hdr, sizeof (ieee_hdr));
236*7273ec43Smmehari 	// Insert IEEE DATA payload
237*7273ec43Smmehari 	sprintf((char *)(buffer + sizeof(u8aRadiotapHeader) + sizeof(ieee_hdr)), "%s", rand_char);
238*7273ec43Smmehari 
239*7273ec43Smmehari 	// Inject packets
240*7273ec43Smmehari 	for(i = 1; i <= num_packets; i++)
241*7273ec43Smmehari 	{
242*7273ec43Smmehari 		r = pcap_inject(ppcap, buffer, packet_size);
243*7273ec43Smmehari 		if (r != packet_size) {
244*7273ec43Smmehari 			perror("Trouble injecting packet");
245*7273ec43Smmehari 			return (1);
246*7273ec43Smmehari 		}
247*7273ec43Smmehari 
248*7273ec43Smmehari 		printf("number of packets sent = %d\r", i);
249*7273ec43Smmehari 		fflush(stdout);
250*7273ec43Smmehari 
251*7273ec43Smmehari 		if (nDelay)
252*7273ec43Smmehari 			usleep(nDelay);
253*7273ec43Smmehari 	}
254*7273ec43Smmehari 
255*7273ec43Smmehari 	printf("\n");
256*7273ec43Smmehari 
257*7273ec43Smmehari 	return (0);
258*7273ec43Smmehari }
259