diff options
Diffstat (limited to 'tools/radiotap-gen/radiotap-gen.c')
-rw-r--r-- | tools/radiotap-gen/radiotap-gen.c | 182 |
1 files changed, 182 insertions, 0 deletions
diff --git a/tools/radiotap-gen/radiotap-gen.c b/tools/radiotap-gen/radiotap-gen.c new file mode 100644 index 00000000..3f319ab5 --- /dev/null +++ b/tools/radiotap-gen/radiotap-gen.c @@ -0,0 +1,182 @@ +/* + * A generic packet generator application for U-SIG radiotap packets. + * + * Copyright Richard Sharpe, 2022. + * + * You will need libpcap installed. + * + * SPDX-License-Identifier: GPL-2.0-or-later + * + * A sample program showing how to create packets with radiotap headers. This + * is mainly useful for those situations where you are adding a new radiotap + * TLV but the drivers for the hardware is not ready yet and you need to + * test your radiotap dissector. + */ + +#include <errno.h> +#include <glib.h> +#include <pcap.h> +#include <stdint.h> +#include <stdlib.h> +#include <string.h> + +struct u_sig_hdr { + uint16_t type; + uint16_t len; + uint32_t common; + uint32_t value; + uint32_t mask; +} __attribute__((packed)); + +struct radiotap_hdr { + uint8_t vers; + uint8_t pad; + uint16_t len; + uint32_t presence_flags; + uint32_t MAC_timestamp[2]; + uint8_t flags; + uint8_t data_rate; + uint16_t channel_freq; + uint16_t pad2; + uint16_t pad3; + struct u_sig_hdr u_sig_hdr; +} __attribute__((packed)); + +struct complete_pkt { + struct radiotap_hdr radiotap; + uint8_t pkt_data[26]; +} __attribute__((packed)); + +/* Some random 802.11 packet, an S1G beacon, I think */ +uint8_t pkt_data[26] = { 0x1c, 0x0b, 0x00, 0x00, 0x02, 0x00, 0xeb, 0x4b, + 0x02, 0x8b, 0x12, 0x52, 0xa7, 0x6b, 0x00, 0x62, + 0x9c, 0x6b, 0x64, 0x4e, 0x35, 0xae, 0x05, 0x02, + 0x00, 0x02 }; + +#define PHY_VERSION_ID_KNOWN 0x00000001 +#define BW_KNOWN 0x00000002 +#define UL_DL_KNOWN 0x00000004 +#define BSS_COLOR_KNOWN 0x00000008 +#define UL_DL 0x00040000 + +/* + * Generate some u_sig packets. + */ +static void gen_u_sig_pkts(pcap_dumper_t *dumper) +{ + struct pcap_pkthdr hdr; + struct complete_pkt pkt; + struct timeval ts; + /* + * Create the complete packet. + * + * 1. Set up the radiotap headers we need, including the TLVs. + */ + pkt.radiotap.vers = 0; + pkt.radiotap.pad = 0; + pkt.radiotap.len = sizeof(struct radiotap_hdr); + pkt.radiotap.presence_flags = 0x1000000F; + pkt.radiotap.MAC_timestamp[0] = 0x17860500; + pkt.radiotap.MAC_timestamp[1] = 0x22ac9b1a; + pkt.radiotap.flags = 0; + pkt.radiotap.data_rate = 0x02; + pkt.radiotap.channel_freq = 5600; + pkt.radiotap.pad2 = 0x0100; + pkt.radiotap.pad3 = 0x0000; + pkt.radiotap.u_sig_hdr.type = 33; /* The TLV we want U-SIG */ + pkt.radiotap.u_sig_hdr.len = 12; + + /* Set the BW to 80MHz for the moment */ + pkt.radiotap.u_sig_hdr.common = PHY_VERSION_ID_KNOWN | BW_KNOWN | \ + UL_DL_KNOWN | 0x00012000; + /* + * The bits are: U-SIG-1 B20-25: all 1s. + * PPDU Type and Comp mode: 0 + * Validate: 1 + * Punctured Channel Information: 0 (no puncturing) + * Validate: 1 + * EHT SIG MCS: 0 (EHT-MCS 0) + */ + pkt.radiotap.u_sig_hdr.value = 0x0000413F; + pkt.radiotap.u_sig_hdr.mask = 0x003fbec0; /* The Intel value */ + + /* Copy the packet data in */ + memcpy(pkt.pkt_data, pkt_data, sizeof(pkt.pkt_data)); + + gettimeofday(&ts, NULL); + hdr.ts.tv_sec = ts.tv_sec; + hdr.ts.tv_usec = ts.tv_usec; + hdr.caplen = sizeof(struct complete_pkt); + hdr.len = sizeof(struct complete_pkt); + + pcap_dump((u_char *)dumper, &hdr, (u_char *)&pkt); + + /* Dump another with different 160MHz */ + /* + * The bits are: U-SIG-1 B20-25: all 1s. + * PPDU Type and Comp mode: 0 + * Validate: 1 + * Punctured Channel Information: 1 ([x 1 1 1]puncturing) + * Validate: 1 + * EHT SIG MCS: 1 (EHT-MCS 1) + */ + pkt.radiotap.u_sig_hdr.common = PHY_VERSION_ID_KNOWN | BW_KNOWN | \ + UL_DL_KNOWN | 0x00018000;; + pkt.radiotap.u_sig_hdr.mask = 0x003fbec0; + pkt.radiotap.u_sig_hdr.value = 0x0001183F; + + /* We should probably update the timestamp */ + pcap_dump((u_char *)dumper, &hdr, (u_char *)&pkt); + + /* Dump another with different 160MHz */ + /* + * The bits are: U-SIG-1 B20-25: all 1s. + * PPDU Type and Comp mode: 0 + * Validate: 1 + * Punctured Channel Information: 1 ([x 1 1 1]puncturing) + * Validate: 1 + * EHT SIG MCS: 1 (EHT-MCS 1) + */ + pkt.radiotap.u_sig_hdr.common = PHY_VERSION_ID_KNOWN | BW_KNOWN | \ + UL_DL_KNOWN | UL_DL | 0x00018000; + pkt.radiotap.u_sig_hdr.mask = 0x003fbec0; + pkt.radiotap.u_sig_hdr.value = 0x0001183F; + + pcap_dump((u_char *)dumper, &hdr, (u_char *)&pkt); +} + +int main(int argc, char *argv[]) +{ + int err = -1; + pcap_t *pd = NULL; + pcap_dumper_t *dumper = NULL; + + if (argc < 2) { + printf("Usage: %s <pcap-file-name>\n", argv[0]); + return 1; + } + + pd = pcap_open_dead(DLT_IEEE802_11_RADIO, 65535); + if (pd == NULL) { + fprintf(stderr, "Unable to open pcap device: %s\n", + g_strerror(errno)); + return -1; + } + + dumper = pcap_dump_open(pd, argv[1]); + if (dumper == NULL) { + fprintf(stderr, "Unable to create dump file %s: %s\n", + argv[1], pcap_geterr(pd)); + goto close_pd; + } + + /* + * Add calls to any functions that generate packets. + */ + gen_u_sig_pkts(dumper); + + pcap_dump_close(dumper); +close_pd: + pcap_close(pd); + return err; +} |