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