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