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