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