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