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