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