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 "ieee80211_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 0x0802. 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
gen_rand_str(int size,char * rand_char)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
usage(void)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 sdr0 interface add mon0 type monitor && ifconfig mon0 up\n"
146 " inject_80211 mon0\n"
147 "\n");
148 exit(1);
149 }
150
151
main(int argc,char * argv[])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 break;
190
191 case 'm':
192 hw_mode = optarg[0];
193 break;
194
195 case 'r':
196 rate_index = atoi(optarg);
197 break;
198
199 case 't':
200 packet_type = optarg[0];
201 break;
202
203 case 'e':
204 sub_type = strtol(optarg, NULL, 16);
205 break;
206
207 case 'a':
208 addr1 = strtol(optarg, NULL, 16);
209 break;
210
211 case 'b':
212 addr2 = strtol(optarg, NULL, 16);
213 break;
214
215 case 'i':
216 sgi_flag = atoi(optarg);
217 break;
218
219 case 'n':
220 num_packets = atoi(optarg);
221 break;
222
223 case 's':
224 payload_size = atoi(optarg);
225 break;
226
227 case 'd':
228 nDelay = atoi(optarg);
229 break;
230
231 default:
232 printf("unknown switch %c\n", c);
233 usage();
234 break;
235 }
236 }
237
238 if (optind >= argc)
239 usage();
240
241 // open the interface in pcap
242 szErrbuf[0] = '\0';
243 ppcap = pcap_open_live(argv[optind], 800, 1, 20, szErrbuf);
244 if (ppcap == NULL)
245 {
246 printf("Unable to open interface %s in pcap: %s\n", argv[optind], szErrbuf);
247 return (1);
248 }
249
250 nLinkEncap = pcap_datalink(ppcap);
251 switch (nLinkEncap)
252 {
253 case DLT_PRISM_HEADER:
254 printf("DLT_PRISM_HEADER Encap\n");
255 break;
256
257 case DLT_IEEE802_11_RADIO:
258 printf("DLT_IEEE802_11_RADIO Encap\n");
259 break;
260
261 default:
262 printf("!!! unknown encapsulation on %s !\n", argv[1]);
263 return (1);
264 }
265
266 pcap_setnonblock(ppcap, 1, szErrbuf);
267
268 // Fill the IEEE hdr
269 if (packet_type == 'd') // data packet
270 {
271 ieee_hdr_data[0] = ( ieee_hdr_data[0]|(sub_type<<4) );
272 ieee_hdr_data[9] = addr1;
273 ieee_hdr_data[15] = addr2;
274 ieee_hdr_data[21] = addr1;
275 ieee_hdr_len = sizeof(ieee_hdr_data);
276 ieee_hdr = ieee_hdr_data;
277 }
278 else if (packet_type == 'm') // managment packet
279 {
280 ieee_hdr_mgmt[0] = ( ieee_hdr_mgmt[0]|(sub_type<<4) );
281 ieee_hdr_mgmt[9] = addr1;
282 ieee_hdr_mgmt[15] = addr2;
283 ieee_hdr_mgmt[21] = addr1;
284 ieee_hdr_len = sizeof(ieee_hdr_mgmt);
285 ieee_hdr = ieee_hdr_mgmt;
286 }
287 else if (packet_type == 'c')
288 {
289 payload_size = 0;
290 if (sub_type == 0xC || sub_type == 0xD)
291 {
292 ieee_hdr_ack_cts[0] = ( ieee_hdr_ack_cts[0]|(sub_type<<4) );
293 ieee_hdr_ack_cts[9] = addr1;
294 ieee_hdr_len = sizeof(ieee_hdr_ack_cts);
295 ieee_hdr = ieee_hdr_ack_cts;
296 }
297 else if (sub_type == 0xA || sub_type == 0xB)
298 {
299 ieee_hdr_rts[0] = ( ieee_hdr_rts[0]|(sub_type<<4) );
300 ieee_hdr_rts[9] = addr1;
301 ieee_hdr_rts[15] = addr2;
302 ieee_hdr_len = sizeof(ieee_hdr_rts);
303 ieee_hdr = ieee_hdr_rts;
304 }
305 else
306 {
307 printf("!!! sub_type %x is not supported yet!\n", sub_type);
308 return (1);
309 }
310 }
311 else
312 {
313 printf("!!! packet_type %c is not supported yet!\n", packet_type);
314 return (1);
315 }
316
317 // Generate random string
318 gen_rand_str(payload_size+4, rand_char); //4 for space reserved for crc
319 payload_len = strlen(rand_char);
320
321 packet_size = sizeof(u8aRadiotapHeader) + ieee_hdr_len + payload_len;
322 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);
323 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);
324
325 if (packet_size > BUF_SIZE_MAX) {
326 printf("packet_size %d > %d! Quite\n", packet_size, BUF_SIZE_MAX);
327 return(1);
328 }
329
330 // Clear storage buffer
331 memset(buffer, 0, sizeof (buffer));
332
333 // Insert default radiotap header
334 memcpy(buffer, u8aRadiotapHeader, sizeof (u8aRadiotapHeader));
335 // Update radiotap header (i.e. hw_mode, rate, GI)
336 if(hw_mode == 'g' || hw_mode == 'a')
337 {
338 buffer[OFFSET_RATE] = u8aRatesToUse[rate_index];
339 buffer[MCS_OFFSET] = 0x00;
340 }
341 else
342 {
343 buffer[MCS_OFFSET] = 0x07;
344 if(sgi_flag)
345 buffer[GI_OFFSET] = IEEE80211_RADIOTAP_MCS_SGI;
346 buffer[MCS_RATE_OFFSET] = rate_index;
347 }
348 // Insert IEEE DATA header
349 memcpy(buffer + sizeof(u8aRadiotapHeader), ieee_hdr, ieee_hdr_len);
350 // Insert IEEE DATA payload
351 sprintf((char *)(buffer + sizeof(u8aRadiotapHeader) + ieee_hdr_len), "%s", rand_char);
352
353 // Inject packets
354 for(i = 1; i <= num_packets; i++)
355 {
356 r = pcap_inject(ppcap, buffer, packet_size);
357 if (r != packet_size) {
358 perror("Trouble injecting packet");
359 return (1);
360 }
361
362 printf("number of packets sent = %d\r", i);
363 fflush(stdout);
364
365 if (nDelay)
366 usleep(nDelay);
367 }
368
369 printf("\n");
370
371 return (0);
372 }
373