wireshark/tools/radiotap-gen/radiotap-gen.c

182 lines
4.9 KiB
C

/*
* 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 = ts;
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;
}