xref: /openwifi/user_space/inject_80211/inject_80211.c (revision 38796372a867b70f7d3ed3d3e62872f94c497953)
1 // Modified by: Michael Mehari
2 // SPDX-FileCopyrightText: 2020 UGent
3 // SPDX-FileCopyrightText: 2007 Andy Green <[email protected]>
4 // SPDX-License-Identifier: GPL-2.0-or-later
5 
6 /*
7  *   This program is free software; you can redistribute it and/or modify
8  *   it under the terms of the GNU General Public License as published by
9  *   the Free Software Foundation; version 2.
10  *
11  *   This program is distributed in the hope that it will be useful,
12  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *   GNU General Public License for more details.
15  *
16  *   You should have received a copy of the GNU General Public License along
17  *   with this program; if not, write to the Free Software Foundation, Inc.,
18  *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19  */
20 
21 // Thanks for contributions:
22 // 2007-03-15 fixes to getopt_long code by Matteo Croce [email protected]
23 
24 #include "inject_80211.h"
25 #include "radiotap.h"
26 
27 #define BUF_SIZE_MAX   (1536)
28 #define BUF_SIZE_TOTAL (BUF_SIZE_MAX+1) // +1 in case the sprintf insert the last 0
29 
30 /* wifi bitrate to use in 500kHz units */
31 static const u8 u8aRatesToUse[] = {
32 	6*2,
33 	9*2,
34 	12*2,
35 	18*2,
36 	24*2,
37 	36*2,
38 	48*2,
39 	54*2
40 };
41 
42 /* this is the template radiotap header we send packets out with */
43 static const u8 u8aRadiotapHeader[] =
44 {
45 	0x00, 0x00, // <-- radiotap version
46 	0x1c, 0x00, // <- radiotap header length
47 	0x6f, 0x08, 0x08, 0x00, // <-- bitmap
48 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // <-- timestamp
49 	0x00, // <-- flags (Offset +0x10)
50 	0x6c, // <-- rate (0ffset +0x11)
51 	0x71, 0x09, 0xc0, 0x00, // <-- channel
52 	0xde, // <-- antsignal
53 	0x00, // <-- antnoise
54 	0x01, // <-- antenna
55 	0x02, 0x00, 0x0f,  // <-- MCS
56 };
57 
58 #define	OFFSET_RATE 0x11
59 #define MCS_OFFSET 0x19
60 #define GI_OFFSET 0x1a
61 #define MCS_RATE_OFFSET 0x1b
62 
63 /* IEEE80211 header */
64 static u8 ieee_hdr_data[] =
65 {
66 	0x08, 0x02, 0x00, 0x00,             // FC 0x0801. 0--subtype; 8--type&version; 02--toDS0 fromDS1 (data packet from DS to STA)
67 	0x66, 0x55, 0x44, 0x33, 0x22, 0x11, // BSSID/MAC of AP
68 	0x66, 0x55, 0x44, 0x33, 0x22, 0x22, // Source address (STA)
69 	0x66, 0x55, 0x44, 0x33, 0x22, 0x33, // Destination address (another STA under the same AP)
70 	0x10, 0x86,                         // 0--fragment number; 0x861=2145--sequence number
71 };
72 
73 static u8 ieee_hdr_mgmt[] =
74 {
75 	0x00, 0x00, 0x00, 0x00,             // FC 0x0000. 0--subtype; 0--type&version;
76 	0x66, 0x55, 0x44, 0x33, 0x22, 0x11, // BSSID/MAC of AP
77 	0x66, 0x55, 0x44, 0x33, 0x22, 0x22, // Source address (STA)
78 	0x66, 0x55, 0x44, 0x33, 0x22, 0x33, // Destination address (another STA under the same AP)
79 	0x10, 0x86,                         // 0--fragment number; 0x861=2145--sequence number
80 };
81 
82 static u8 ieee_hdr_ack_cts[] =
83 {
84 	0xd4, 0x00, 0x00, 0x00,             // FC 0xd400. d--subtype; 4--type&version;
85 	0x66, 0x55, 0x44, 0x33, 0x22, 0x11, // mac addr of the peer
86 };
87 
88 static u8 ieee_hdr_rts[] =
89 {
90 	0xb4, 0x00, 0x00, 0x00,             // FC 0xb400. b--subtype; 4--type&version;
91 	0x66, 0x55, 0x44, 0x33, 0x22, 0x11, // mac addr of the peer
92 	0x66, 0x55, 0x44, 0x33, 0x22, 0x22, // mac addr of the peer
93 };
94 
95 // Generate random string
96 void gen_rand_str(int size, char *rand_char)
97 {
98 	int i, randNum = 0;
99 
100 	// Seed the random number generator with packet size
101 	srand(size);
102 	for (i = 0; i < size; i++)
103 	{
104 		// First, pick a number between 0 and 25.
105 		randNum = 255 * (rand() / (RAND_MAX + 1.0));
106 
107 		if(randNum == 0)
108 		{
109 			i--;
110 			continue;
111 		}
112 
113 		// Type cast to character
114 		rand_char[i] = (char) randNum;
115 	}
116 	rand_char[i] = '\0';
117 }
118 
119 int flagHelp = 0;
120 
121 void usage(void)
122 {
123 	printf(
124 	    "(c)2006-2007 Andy Green <[email protected]>  Licensed under GPL2\n"
125 		"(r)2020 Michael Tetemke Mehari <[email protected]>\n"
126 		"(r)2022 Xianjun Jiao <[email protected]>"
127 	    "\n"
128 	    "Usage: inject_80211 [options] <interface>\n\nOptions\n"
129 	    "-m/--hw_mode <hardware operation mode> (a,g,n)\n"
130 	    "-r/--rate_index <rate/MCS index> (0,1,2,3,4,5,6,7)\n"
131 		"-t/--packet_type (m/c/d/r for management/control/data/reserved)\n"
132 		"-e/--sub_type (hex value. example:\n"
133 		"     8/A/B/C for Beacon/Disassociation/Authentication/Deauth, when packet_type m\n"
134 		"     A/B/C/D for PS-Poll/RTS/CTS/ACK, when packet_type c\n"
135 		"     0/1/2/8 for Data/Data+CF-Ack/Data+CF-Poll/QoS-Data, when packet_type d)\n"
136 		"-a/--addr1 <the last byte of addr1 in hex>\n"
137 		"-b/--addr2 <the last byte of addr2 in hex>\n"
138 	    "-i/--sgi_flag (0,1)\n"
139 	    "-n/--num_packets <number of packets>\n"
140 	    "-s/--payload_size <payload size in bytes>\n"
141 	    "-d/--delay <delay between packets in usec>\n"
142 	    "-h   this menu\n\n"
143 
144 	    "Example:\n"
145 	    "  iw dev wlan0 interface add mon0 type monitor && ifconfig mon0 up\n"
146 	    "  inject_80211 mon0\n"
147 	    "\n");
148 	exit(1);
149 }
150 
151 
152 int main(int argc, char *argv[])
153 {
154 	u8 buffer[BUF_SIZE_TOTAL], addr1=1, addr2=2, sub_type=1, *ieee_hdr;
155 	char szErrbuf[PCAP_ERRBUF_SIZE], rand_char[1484], hw_mode = 'n', packet_type = 'd';
156 	int i, nLinkEncap = 0, r, rate_index = 0, sgi_flag = 0, num_packets = 10, payload_size = 64, packet_size, nDelay = 100000;
157 	int ieee_hdr_len, payload_len;
158 	pcap_t *ppcap = NULL;
159 
160 	while (1)
161 	{
162 		int nOptionIndex;
163 		static const struct option optiona[] =
164 		{
165 			{ "hw_mode", required_argument, NULL, 'm' },
166 			{ "rate_index", required_argument, NULL, 'r' },
167 			{ "packet_type", required_argument, NULL, 't' },
168 			{ "sub_type", required_argument, NULL, 'e' },
169 			{ "addr1", required_argument, NULL, 'a' },
170 			{ "addr2", required_argument, NULL, 'b' },
171 			{ "sgi_flag", no_argument, NULL, 'i' },
172 			{ "num_packets", required_argument, NULL, 'n' },
173 			{ "payload_size", required_argument, NULL, 's' },
174 			{ "delay", required_argument, NULL, 'd' },
175 			{ "help", no_argument, &flagHelp, 1 },
176 			{ 0, 0, 0, 0 }
177 		};
178 		int c = getopt_long(argc, argv, "m:r:t:e:a:b:i:n:s:d:h", optiona, &nOptionIndex);
179 
180 		if (c == -1)
181 			break;
182 		switch (c)
183 		{
184 			case 0: // long option
185 				break;
186 
187 			case 'h':
188 				usage();
189 
190 			case 'm':
191 				hw_mode = optarg[0];
192 				break;
193 
194 			case 'r':
195 				rate_index = atoi(optarg);
196 				break;
197 
198 			case 't':
199 				packet_type = optarg[0];
200 				break;
201 
202 			case 'e':
203 				sub_type = strtol(optarg, NULL, 16);
204 				break;
205 
206 			case 'a':
207 				addr1 = strtol(optarg, NULL, 16);
208 				break;
209 
210 			case 'b':
211 				addr2 = strtol(optarg, NULL, 16);
212 				break;
213 
214 			case 'i':
215 				sgi_flag = atoi(optarg);
216 				break;
217 
218 			case 'n':
219 				num_packets = atoi(optarg);
220 				break;
221 
222 			case 's':
223 				payload_size = atoi(optarg);
224 				break;
225 
226 			case 'd':
227 				nDelay = atoi(optarg);
228 				break;
229 
230 			default:
231 				printf("unknown switch %c\n", c);
232 				usage();
233 				break;
234 		}
235 	}
236 
237 	if (optind >= argc)
238 		usage();
239 
240 	// open the interface in pcap
241 	szErrbuf[0] = '\0';
242 	ppcap = pcap_open_live(argv[optind], 800, 1, 20, szErrbuf);
243 	if (ppcap == NULL)
244 	{
245 		printf("Unable to open interface %s in pcap: %s\n", argv[optind], szErrbuf);
246 		return (1);
247 	}
248 
249 	nLinkEncap = pcap_datalink(ppcap);
250 	switch (nLinkEncap)
251 	{
252 		case DLT_PRISM_HEADER:
253 			printf("DLT_PRISM_HEADER Encap\n");
254 			break;
255 
256 		case DLT_IEEE802_11_RADIO:
257 			printf("DLT_IEEE802_11_RADIO Encap\n");
258 			break;
259 
260 		default:
261 			printf("!!! unknown encapsulation on %s !\n", argv[1]);
262 			return (1);
263 	}
264 
265 	pcap_setnonblock(ppcap, 1, szErrbuf);
266 
267 	// Fill the IEEE hdr
268 	if (packet_type == 'd') // data packet
269 	{
270 		ieee_hdr_data[0]  = ( ieee_hdr_data[0]|(sub_type<<4) );
271 		ieee_hdr_data[9]  = addr1;
272 		ieee_hdr_data[15] = addr2;
273 		ieee_hdr_len = sizeof(ieee_hdr_data);
274 		ieee_hdr = ieee_hdr_data;
275 	}
276 	else if (packet_type == 'm') // managment packet
277 	{
278 		ieee_hdr_mgmt[0]  = ( ieee_hdr_mgmt[0]|(sub_type<<4) );
279 		ieee_hdr_mgmt[9]  = addr1;
280 		ieee_hdr_mgmt[15] = addr2;
281 		ieee_hdr_len = sizeof(ieee_hdr_mgmt);
282 		ieee_hdr = ieee_hdr_mgmt;
283 	}
284 	else if (packet_type == 'c')
285 	{
286 		payload_size = 0;
287 		if (sub_type == 0xC || sub_type == 0xD)
288 		{
289 			ieee_hdr_ack_cts[0] = ( ieee_hdr_ack_cts[0]|(sub_type<<4) );
290 			ieee_hdr_ack_cts[9] = addr1;
291 			ieee_hdr_len = sizeof(ieee_hdr_ack_cts);
292 			ieee_hdr = ieee_hdr_ack_cts;
293 		}
294 		else if (sub_type == 0xA || sub_type == 0xB)
295 		{
296 			ieee_hdr_rts[0]  = ( ieee_hdr_rts[0]|(sub_type<<4) );
297 			ieee_hdr_rts[9]  = addr1;
298 			ieee_hdr_rts[15] = addr2;
299 			ieee_hdr_len = sizeof(ieee_hdr_rts);
300 			ieee_hdr = ieee_hdr_rts;
301 		}
302 		else
303 		{
304 			printf("!!! sub_type %x is not supported yet!\n", sub_type);
305 			return (1);
306 		}
307 	}
308 	else
309 	{
310 		printf("!!! packet_type %c is not supported yet!\n", packet_type);
311 		return (1);
312 	}
313 
314 	// Generate random string
315 	gen_rand_str(payload_size+4, rand_char); //4 for space reserved for crc
316 	payload_len = strlen(rand_char);
317 
318 	packet_size = sizeof(u8aRadiotapHeader) + ieee_hdr_len + payload_len;
319 	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);
320 	printf("packet_type %c sub_type %x payload_len %d ieee_hdr_len %d addr1 %02x addr2 %02x\n", packet_type, sub_type, payload_len, ieee_hdr_len, addr1, addr2);
321 
322 	if (packet_size > BUF_SIZE_MAX) {
323 		printf("packet_size %d > %d! Quite\n", packet_size, BUF_SIZE_MAX);
324 		return(1);
325 	}
326 
327 	// Clear storage buffer
328 	memset(buffer, 0, sizeof (buffer));
329 
330 	// Insert default radiotap header
331 	memcpy(buffer, u8aRadiotapHeader, sizeof (u8aRadiotapHeader));
332 	// Update radiotap header (i.e. hw_mode, rate, GI)
333 	if(hw_mode == 'g' || hw_mode == 'a')
334 	{
335 		buffer[OFFSET_RATE] = u8aRatesToUse[rate_index];
336 		buffer[MCS_OFFSET] = 0x00;
337 	}
338 	else
339 	{
340 		buffer[MCS_OFFSET] = 0x07;
341 		if(sgi_flag)
342 			buffer[GI_OFFSET] = IEEE80211_RADIOTAP_MCS_SGI;
343 		buffer[MCS_RATE_OFFSET] = rate_index;
344 	}
345 	// Insert IEEE DATA header
346 	memcpy(buffer + sizeof(u8aRadiotapHeader), ieee_hdr, ieee_hdr_len);
347 	// Insert IEEE DATA payload
348 	sprintf((char *)(buffer + sizeof(u8aRadiotapHeader) + ieee_hdr_len), "%s", rand_char);
349 
350 	// Inject packets
351 	for(i = 1; i <= num_packets; i++)
352 	{
353 		r = pcap_inject(ppcap, buffer, packet_size);
354 		if (r != packet_size) {
355 			perror("Trouble injecting packet");
356 			return (1);
357 		}
358 
359 		printf("number of packets sent = %d\r", i);
360 		fflush(stdout);
361 
362 		if (nDelay)
363 			usleep(nDelay);
364 	}
365 
366 	printf("\n");
367 
368 	return (0);
369 }
370