1e69a4568SJiao Xianjun // Modified by: Michael Mehari 2e69a4568SJiao Xianjun // SPDX-FileCopyrightText: 2020 UGent 3a6085186SLina Ceballos // SPDX-FileCopyrightText: 2007 Andy Green <[email protected]> 4a6085186SLina Ceballos // SPDX-License-Identifier: GPL-2.0-or-later 57273ec43Smmehari 67273ec43Smmehari /* 77273ec43Smmehari * This program is free software; you can redistribute it and/or modify 87273ec43Smmehari * it under the terms of the GNU General Public License as published by 97273ec43Smmehari * the Free Software Foundation; version 2. 107273ec43Smmehari * 117273ec43Smmehari * This program is distributed in the hope that it will be useful, 127273ec43Smmehari * but WITHOUT ANY WARRANTY; without even the implied warranty of 137273ec43Smmehari * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 147273ec43Smmehari * GNU General Public License for more details. 157273ec43Smmehari * 167273ec43Smmehari * You should have received a copy of the GNU General Public License along 177273ec43Smmehari * with this program; if not, write to the Free Software Foundation, Inc., 187273ec43Smmehari * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 197273ec43Smmehari */ 207273ec43Smmehari 217273ec43Smmehari // Thanks for contributions: 227273ec43Smmehari // 2007-03-15 fixes to getopt_long code by Matteo Croce [email protected] 237273ec43Smmehari 247273ec43Smmehari #include "inject_80211.h" 2551e498afSXianjun Jiao #include "ieee80211_radiotap.h" 267273ec43Smmehari 27e9a08f26SXianjun Jiao #define BUF_SIZE_MAX (1536) 28e9a08f26SXianjun Jiao #define BUF_SIZE_TOTAL (BUF_SIZE_MAX+1) // +1 in case the sprintf insert the last 0 29e9a08f26SXianjun Jiao 307273ec43Smmehari /* wifi bitrate to use in 500kHz units */ 317273ec43Smmehari static const u8 u8aRatesToUse[] = { 327273ec43Smmehari 6*2, 337273ec43Smmehari 9*2, 347273ec43Smmehari 12*2, 357273ec43Smmehari 18*2, 367273ec43Smmehari 24*2, 377273ec43Smmehari 36*2, 387273ec43Smmehari 48*2, 397273ec43Smmehari 54*2 407273ec43Smmehari }; 417273ec43Smmehari 427273ec43Smmehari /* this is the template radiotap header we send packets out with */ 437273ec43Smmehari static const u8 u8aRadiotapHeader[] = 447273ec43Smmehari { 457273ec43Smmehari 0x00, 0x00, // <-- radiotap version 467273ec43Smmehari 0x1c, 0x00, // <- radiotap header length 477273ec43Smmehari 0x6f, 0x08, 0x08, 0x00, // <-- bitmap 487273ec43Smmehari 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // <-- timestamp 497273ec43Smmehari 0x00, // <-- flags (Offset +0x10) 507273ec43Smmehari 0x6c, // <-- rate (0ffset +0x11) 517273ec43Smmehari 0x71, 0x09, 0xc0, 0x00, // <-- channel 527273ec43Smmehari 0xde, // <-- antsignal 537273ec43Smmehari 0x00, // <-- antnoise 547273ec43Smmehari 0x01, // <-- antenna 557273ec43Smmehari 0x02, 0x00, 0x0f, // <-- MCS 567273ec43Smmehari }; 577273ec43Smmehari 587273ec43Smmehari #define OFFSET_RATE 0x11 597273ec43Smmehari #define MCS_OFFSET 0x19 607273ec43Smmehari #define GI_OFFSET 0x1a 617273ec43Smmehari #define MCS_RATE_OFFSET 0x1b 627273ec43Smmehari 637273ec43Smmehari /* IEEE80211 header */ 64e9a08f26SXianjun Jiao static u8 ieee_hdr_data[] = 657273ec43Smmehari { 66*33366f7cSXianjun Jiao 0x08, 0x02, 0x00, 0x00, // FC 0x0802. 0--subtype; 8--type&version; 02--toDS0 fromDS1 (data packet from DS to STA) 67b66028eeSXianjun Jiao 0x66, 0x55, 0x44, 0x33, 0x22, 0x11, // BSSID/MAC of AP 68b66028eeSXianjun Jiao 0x66, 0x55, 0x44, 0x33, 0x22, 0x22, // Source address (STA) 69b66028eeSXianjun Jiao 0x66, 0x55, 0x44, 0x33, 0x22, 0x33, // Destination address (another STA under the same AP) 70b66028eeSXianjun Jiao 0x10, 0x86, // 0--fragment number; 0x861=2145--sequence number 717273ec43Smmehari }; 727273ec43Smmehari 73e9a08f26SXianjun Jiao static u8 ieee_hdr_mgmt[] = 74e9a08f26SXianjun Jiao { 75e9a08f26SXianjun Jiao 0x00, 0x00, 0x00, 0x00, // FC 0x0000. 0--subtype; 0--type&version; 76e9a08f26SXianjun Jiao 0x66, 0x55, 0x44, 0x33, 0x22, 0x11, // BSSID/MAC of AP 77e9a08f26SXianjun Jiao 0x66, 0x55, 0x44, 0x33, 0x22, 0x22, // Source address (STA) 78e9a08f26SXianjun Jiao 0x66, 0x55, 0x44, 0x33, 0x22, 0x33, // Destination address (another STA under the same AP) 79e9a08f26SXianjun Jiao 0x10, 0x86, // 0--fragment number; 0x861=2145--sequence number 80e9a08f26SXianjun Jiao }; 81e9a08f26SXianjun Jiao 82e9a08f26SXianjun Jiao static u8 ieee_hdr_ack_cts[] = 83e9a08f26SXianjun Jiao { 84e9a08f26SXianjun Jiao 0xd4, 0x00, 0x00, 0x00, // FC 0xd400. d--subtype; 4--type&version; 85e9a08f26SXianjun Jiao 0x66, 0x55, 0x44, 0x33, 0x22, 0x11, // mac addr of the peer 86e9a08f26SXianjun Jiao }; 87e9a08f26SXianjun Jiao 88e9a08f26SXianjun Jiao static u8 ieee_hdr_rts[] = 89e9a08f26SXianjun Jiao { 90e9a08f26SXianjun Jiao 0xb4, 0x00, 0x00, 0x00, // FC 0xb400. b--subtype; 4--type&version; 91e9a08f26SXianjun Jiao 0x66, 0x55, 0x44, 0x33, 0x22, 0x11, // mac addr of the peer 92e9a08f26SXianjun Jiao 0x66, 0x55, 0x44, 0x33, 0x22, 0x22, // mac addr of the peer 93e9a08f26SXianjun Jiao }; 94e9a08f26SXianjun Jiao 957273ec43Smmehari // Generate random string 967273ec43Smmehari void gen_rand_str(int size, char *rand_char) 977273ec43Smmehari { 987273ec43Smmehari int i, randNum = 0; 997273ec43Smmehari 1007273ec43Smmehari // Seed the random number generator with packet size 1017273ec43Smmehari srand(size); 1027273ec43Smmehari for (i = 0; i < size; i++) 1037273ec43Smmehari { 1047273ec43Smmehari // First, pick a number between 0 and 25. 1057273ec43Smmehari randNum = 255 * (rand() / (RAND_MAX + 1.0)); 1067273ec43Smmehari 1077273ec43Smmehari if(randNum == 0) 1087273ec43Smmehari { 1097273ec43Smmehari i--; 1107273ec43Smmehari continue; 1117273ec43Smmehari } 1127273ec43Smmehari 1137273ec43Smmehari // Type cast to character 1147273ec43Smmehari rand_char[i] = (char) randNum; 1157273ec43Smmehari } 1167273ec43Smmehari rand_char[i] = '\0'; 1177273ec43Smmehari } 1187273ec43Smmehari 1197273ec43Smmehari int flagHelp = 0; 1207273ec43Smmehari 1217273ec43Smmehari void usage(void) 1227273ec43Smmehari { 1237273ec43Smmehari printf( 1247273ec43Smmehari "(c)2006-2007 Andy Green <[email protected]> Licensed under GPL2\n" 125e9a08f26SXianjun Jiao "(r)2020 Michael Tetemke Mehari <[email protected]>\n" 126e9a08f26SXianjun Jiao "(r)2022 Xianjun Jiao <[email protected]>" 1277273ec43Smmehari "\n" 1287273ec43Smmehari "Usage: inject_80211 [options] <interface>\n\nOptions\n" 1297273ec43Smmehari "-m/--hw_mode <hardware operation mode> (a,g,n)\n" 1307273ec43Smmehari "-r/--rate_index <rate/MCS index> (0,1,2,3,4,5,6,7)\n" 131e9a08f26SXianjun Jiao "-t/--packet_type (m/c/d/r for management/control/data/reserved)\n" 132e9a08f26SXianjun Jiao "-e/--sub_type (hex value. example:\n" 133e9a08f26SXianjun Jiao " 8/A/B/C for Beacon/Disassociation/Authentication/Deauth, when packet_type m\n" 134e9a08f26SXianjun Jiao " A/B/C/D for PS-Poll/RTS/CTS/ACK, when packet_type c\n" 135e9a08f26SXianjun Jiao " 0/1/2/8 for Data/Data+CF-Ack/Data+CF-Poll/QoS-Data, when packet_type d)\n" 136e9a08f26SXianjun Jiao "-a/--addr1 <the last byte of addr1 in hex>\n" 137e9a08f26SXianjun Jiao "-b/--addr2 <the last byte of addr2 in hex>\n" 1387273ec43Smmehari "-i/--sgi_flag (0,1)\n" 1397273ec43Smmehari "-n/--num_packets <number of packets>\n" 1407273ec43Smmehari "-s/--payload_size <payload size in bytes>\n" 1417273ec43Smmehari "-d/--delay <delay between packets in usec>\n" 1427273ec43Smmehari "-h this menu\n\n" 1437273ec43Smmehari 1447273ec43Smmehari "Example:\n" 1450802e503SXianjun Jiao " iw dev sdr0 interface add mon0 type monitor && ifconfig mon0 up\n" 1467273ec43Smmehari " inject_80211 mon0\n" 1477273ec43Smmehari "\n"); 1487273ec43Smmehari exit(1); 1497273ec43Smmehari } 1507273ec43Smmehari 1517273ec43Smmehari 1527273ec43Smmehari int main(int argc, char *argv[]) 1537273ec43Smmehari { 154e9a08f26SXianjun Jiao u8 buffer[BUF_SIZE_TOTAL], addr1=1, addr2=2, sub_type=1, *ieee_hdr; 155e9a08f26SXianjun Jiao char szErrbuf[PCAP_ERRBUF_SIZE], rand_char[1484], hw_mode = 'n', packet_type = 'd'; 1567273ec43Smmehari int i, nLinkEncap = 0, r, rate_index = 0, sgi_flag = 0, num_packets = 10, payload_size = 64, packet_size, nDelay = 100000; 157e9a08f26SXianjun Jiao int ieee_hdr_len, payload_len; 1587273ec43Smmehari pcap_t *ppcap = NULL; 1597273ec43Smmehari 1607273ec43Smmehari while (1) 1617273ec43Smmehari { 1627273ec43Smmehari int nOptionIndex; 1637273ec43Smmehari static const struct option optiona[] = 1647273ec43Smmehari { 1657273ec43Smmehari { "hw_mode", required_argument, NULL, 'm' }, 1667273ec43Smmehari { "rate_index", required_argument, NULL, 'r' }, 167e9a08f26SXianjun Jiao { "packet_type", required_argument, NULL, 't' }, 168e9a08f26SXianjun Jiao { "sub_type", required_argument, NULL, 'e' }, 169e9a08f26SXianjun Jiao { "addr1", required_argument, NULL, 'a' }, 170e9a08f26SXianjun Jiao { "addr2", required_argument, NULL, 'b' }, 1717273ec43Smmehari { "sgi_flag", no_argument, NULL, 'i' }, 1727273ec43Smmehari { "num_packets", required_argument, NULL, 'n' }, 1737273ec43Smmehari { "payload_size", required_argument, NULL, 's' }, 1747273ec43Smmehari { "delay", required_argument, NULL, 'd' }, 1757273ec43Smmehari { "help", no_argument, &flagHelp, 1 }, 1767273ec43Smmehari { 0, 0, 0, 0 } 1777273ec43Smmehari }; 178e9a08f26SXianjun Jiao int c = getopt_long(argc, argv, "m:r:t:e:a:b:i:n:s:d:h", optiona, &nOptionIndex); 1797273ec43Smmehari 1807273ec43Smmehari if (c == -1) 1817273ec43Smmehari break; 1827273ec43Smmehari switch (c) 1837273ec43Smmehari { 1847273ec43Smmehari case 0: // long option 1857273ec43Smmehari break; 1867273ec43Smmehari 1877273ec43Smmehari case 'h': 1887273ec43Smmehari usage(); 1897273ec43Smmehari 1907273ec43Smmehari case 'm': 1917273ec43Smmehari hw_mode = optarg[0]; 1927273ec43Smmehari break; 1937273ec43Smmehari 1947273ec43Smmehari case 'r': 1957273ec43Smmehari rate_index = atoi(optarg); 1967273ec43Smmehari break; 1977273ec43Smmehari 198e9a08f26SXianjun Jiao case 't': 199e9a08f26SXianjun Jiao packet_type = optarg[0]; 200e9a08f26SXianjun Jiao break; 201e9a08f26SXianjun Jiao 202e9a08f26SXianjun Jiao case 'e': 203e9a08f26SXianjun Jiao sub_type = strtol(optarg, NULL, 16); 204e9a08f26SXianjun Jiao break; 205e9a08f26SXianjun Jiao 206e9a08f26SXianjun Jiao case 'a': 207e9a08f26SXianjun Jiao addr1 = strtol(optarg, NULL, 16); 208e9a08f26SXianjun Jiao break; 209e9a08f26SXianjun Jiao 210e9a08f26SXianjun Jiao case 'b': 211e9a08f26SXianjun Jiao addr2 = strtol(optarg, NULL, 16); 212e9a08f26SXianjun Jiao break; 213e9a08f26SXianjun Jiao 2147273ec43Smmehari case 'i': 2157273ec43Smmehari sgi_flag = atoi(optarg); 2167273ec43Smmehari break; 2177273ec43Smmehari 2187273ec43Smmehari case 'n': 2197273ec43Smmehari num_packets = atoi(optarg); 2207273ec43Smmehari break; 2217273ec43Smmehari 2227273ec43Smmehari case 's': 2237273ec43Smmehari payload_size = atoi(optarg); 2247273ec43Smmehari break; 2257273ec43Smmehari 2267273ec43Smmehari case 'd': 2277273ec43Smmehari nDelay = atoi(optarg); 2287273ec43Smmehari break; 2297273ec43Smmehari 2307273ec43Smmehari default: 2317273ec43Smmehari printf("unknown switch %c\n", c); 2327273ec43Smmehari usage(); 2337273ec43Smmehari break; 2347273ec43Smmehari } 2357273ec43Smmehari } 2367273ec43Smmehari 2377273ec43Smmehari if (optind >= argc) 2387273ec43Smmehari usage(); 2397273ec43Smmehari 2407273ec43Smmehari // open the interface in pcap 2417273ec43Smmehari szErrbuf[0] = '\0'; 2427273ec43Smmehari ppcap = pcap_open_live(argv[optind], 800, 1, 20, szErrbuf); 2437273ec43Smmehari if (ppcap == NULL) 2447273ec43Smmehari { 2457273ec43Smmehari printf("Unable to open interface %s in pcap: %s\n", argv[optind], szErrbuf); 2467273ec43Smmehari return (1); 2477273ec43Smmehari } 2487273ec43Smmehari 2497273ec43Smmehari nLinkEncap = pcap_datalink(ppcap); 2507273ec43Smmehari switch (nLinkEncap) 2517273ec43Smmehari { 2527273ec43Smmehari case DLT_PRISM_HEADER: 2537273ec43Smmehari printf("DLT_PRISM_HEADER Encap\n"); 2547273ec43Smmehari break; 2557273ec43Smmehari 2567273ec43Smmehari case DLT_IEEE802_11_RADIO: 2577273ec43Smmehari printf("DLT_IEEE802_11_RADIO Encap\n"); 2587273ec43Smmehari break; 2597273ec43Smmehari 2607273ec43Smmehari default: 2617273ec43Smmehari printf("!!! unknown encapsulation on %s !\n", argv[1]); 2627273ec43Smmehari return (1); 2637273ec43Smmehari } 2647273ec43Smmehari 2657273ec43Smmehari pcap_setnonblock(ppcap, 1, szErrbuf); 2667273ec43Smmehari 267e9a08f26SXianjun Jiao // Fill the IEEE hdr 268e9a08f26SXianjun Jiao if (packet_type == 'd') // data packet 269e9a08f26SXianjun Jiao { 270e9a08f26SXianjun Jiao ieee_hdr_data[0] = ( ieee_hdr_data[0]|(sub_type<<4) ); 271e9a08f26SXianjun Jiao ieee_hdr_data[9] = addr1; 272e9a08f26SXianjun Jiao ieee_hdr_data[15] = addr2; 273a7af994bSXianjun Jiao ieee_hdr_data[21] = addr1; 274e9a08f26SXianjun Jiao ieee_hdr_len = sizeof(ieee_hdr_data); 275e9a08f26SXianjun Jiao ieee_hdr = ieee_hdr_data; 276e9a08f26SXianjun Jiao } 277e9a08f26SXianjun Jiao else if (packet_type == 'm') // managment packet 278e9a08f26SXianjun Jiao { 279e9a08f26SXianjun Jiao ieee_hdr_mgmt[0] = ( ieee_hdr_mgmt[0]|(sub_type<<4) ); 280e9a08f26SXianjun Jiao ieee_hdr_mgmt[9] = addr1; 281e9a08f26SXianjun Jiao ieee_hdr_mgmt[15] = addr2; 282a7af994bSXianjun Jiao ieee_hdr_mgmt[21] = addr1; 283e9a08f26SXianjun Jiao ieee_hdr_len = sizeof(ieee_hdr_mgmt); 284e9a08f26SXianjun Jiao ieee_hdr = ieee_hdr_mgmt; 285e9a08f26SXianjun Jiao } 286e9a08f26SXianjun Jiao else if (packet_type == 'c') 287e9a08f26SXianjun Jiao { 288e9a08f26SXianjun Jiao payload_size = 0; 289e9a08f26SXianjun Jiao if (sub_type == 0xC || sub_type == 0xD) 290e9a08f26SXianjun Jiao { 291e9a08f26SXianjun Jiao ieee_hdr_ack_cts[0] = ( ieee_hdr_ack_cts[0]|(sub_type<<4) ); 292e9a08f26SXianjun Jiao ieee_hdr_ack_cts[9] = addr1; 293e9a08f26SXianjun Jiao ieee_hdr_len = sizeof(ieee_hdr_ack_cts); 294e9a08f26SXianjun Jiao ieee_hdr = ieee_hdr_ack_cts; 295e9a08f26SXianjun Jiao } 296e9a08f26SXianjun Jiao else if (sub_type == 0xA || sub_type == 0xB) 297e9a08f26SXianjun Jiao { 298e9a08f26SXianjun Jiao ieee_hdr_rts[0] = ( ieee_hdr_rts[0]|(sub_type<<4) ); 299e9a08f26SXianjun Jiao ieee_hdr_rts[9] = addr1; 300e9a08f26SXianjun Jiao ieee_hdr_rts[15] = addr2; 301e9a08f26SXianjun Jiao ieee_hdr_len = sizeof(ieee_hdr_rts); 302e9a08f26SXianjun Jiao ieee_hdr = ieee_hdr_rts; 303e9a08f26SXianjun Jiao } 304e9a08f26SXianjun Jiao else 305e9a08f26SXianjun Jiao { 306e9a08f26SXianjun Jiao printf("!!! sub_type %x is not supported yet!\n", sub_type); 307e9a08f26SXianjun Jiao return (1); 308e9a08f26SXianjun Jiao } 309e9a08f26SXianjun Jiao } 310e9a08f26SXianjun Jiao else 311e9a08f26SXianjun Jiao { 312e9a08f26SXianjun Jiao printf("!!! packet_type %c is not supported yet!\n", packet_type); 313e9a08f26SXianjun Jiao return (1); 314e9a08f26SXianjun Jiao } 315e9a08f26SXianjun Jiao 3167273ec43Smmehari // Generate random string 317e9a08f26SXianjun Jiao gen_rand_str(payload_size+4, rand_char); //4 for space reserved for crc 318e9a08f26SXianjun Jiao payload_len = strlen(rand_char); 319e9a08f26SXianjun Jiao 320e9a08f26SXianjun Jiao packet_size = sizeof(u8aRadiotapHeader) + ieee_hdr_len + payload_len; 3217273ec43Smmehari 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); 322e9a08f26SXianjun Jiao printf("packet_type %c sub_type %x payload_len %d ieee_hdr_len %d addr1 %02x addr2 %02x\n", packet_type, sub_type, payload_len, ieee_hdr_len, addr1, addr2); 323e9a08f26SXianjun Jiao 324e9a08f26SXianjun Jiao if (packet_size > BUF_SIZE_MAX) { 325e9a08f26SXianjun Jiao printf("packet_size %d > %d! Quite\n", packet_size, BUF_SIZE_MAX); 326e9a08f26SXianjun Jiao return(1); 327e9a08f26SXianjun Jiao } 3287273ec43Smmehari 3297273ec43Smmehari // Clear storage buffer 3307273ec43Smmehari memset(buffer, 0, sizeof (buffer)); 3317273ec43Smmehari 3327273ec43Smmehari // Insert default radiotap header 3337273ec43Smmehari memcpy(buffer, u8aRadiotapHeader, sizeof (u8aRadiotapHeader)); 3347273ec43Smmehari // Update radiotap header (i.e. hw_mode, rate, GI) 3357273ec43Smmehari if(hw_mode == 'g' || hw_mode == 'a') 3367273ec43Smmehari { 3377273ec43Smmehari buffer[OFFSET_RATE] = u8aRatesToUse[rate_index]; 3387273ec43Smmehari buffer[MCS_OFFSET] = 0x00; 3397273ec43Smmehari } 3407273ec43Smmehari else 3417273ec43Smmehari { 3427273ec43Smmehari buffer[MCS_OFFSET] = 0x07; 3437273ec43Smmehari if(sgi_flag) 3447273ec43Smmehari buffer[GI_OFFSET] = IEEE80211_RADIOTAP_MCS_SGI; 3457273ec43Smmehari buffer[MCS_RATE_OFFSET] = rate_index; 3467273ec43Smmehari } 3477273ec43Smmehari // Insert IEEE DATA header 348e9a08f26SXianjun Jiao memcpy(buffer + sizeof(u8aRadiotapHeader), ieee_hdr, ieee_hdr_len); 3497273ec43Smmehari // Insert IEEE DATA payload 350e9a08f26SXianjun Jiao sprintf((char *)(buffer + sizeof(u8aRadiotapHeader) + ieee_hdr_len), "%s", rand_char); 3517273ec43Smmehari 3527273ec43Smmehari // Inject packets 3537273ec43Smmehari for(i = 1; i <= num_packets; i++) 3547273ec43Smmehari { 3557273ec43Smmehari r = pcap_inject(ppcap, buffer, packet_size); 3567273ec43Smmehari if (r != packet_size) { 3577273ec43Smmehari perror("Trouble injecting packet"); 3587273ec43Smmehari return (1); 3597273ec43Smmehari } 3607273ec43Smmehari 3617273ec43Smmehari printf("number of packets sent = %d\r", i); 3627273ec43Smmehari fflush(stdout); 3637273ec43Smmehari 3647273ec43Smmehari if (nDelay) 3657273ec43Smmehari usleep(nDelay); 3667273ec43Smmehari } 3677273ec43Smmehari 3687273ec43Smmehari printf("\n"); 3697273ec43Smmehari 3707273ec43Smmehari return (0); 3717273ec43Smmehari } 372