Skip to content

Instantly share code, notes, and snippets.

@mic159
Last active March 16, 2024 22:33
Show Gist options
  • Save mic159/f546974d642f4189958423fbefe27902 to your computer and use it in GitHub Desktop.
Save mic159/f546974d642f4189958423fbefe27902 to your computer and use it in GitHub Desktop.
ESP32 raw packets
#include <WiFi.h>
#include "wifi_headers.h"
#include <esp_wifi.h>
//#include <esp_wifi_internal.h>
#include <lwip/err.h>
typedef union {
uint8_t fix_rate;
uint8_t b5;
uint8_t b4;
struct {
uint8_t b3;
uint8_t b2;
} b1;
struct {
uint32_t a1;
uint8_t a2;
uint8_t a3;
uint8_t a4;
uint8_t a5;
struct {
uint8_t a6;
uint8_t a7;
} a8[4];
uint8_t a9;
uint8_t a10;
uint8_t a11;
uint8_t a12;
} a13;
} wifi_internal_rate_t;
#define RATE_MCS4_SP 28 // N 43.3Mb MCS4 SP
// buffer: Raw IEEE 802.11 packet to send
// len: Length of IEEE 802.11 packet
// en_sys_seq: see https://github.com/espressif/esp-idf/blob/master/docs/api-guides/wifi.rst#wi-fi-80211-packet-send for details
extern "C" {
esp_err_t esp_wifi_80211_tx(wifi_interface_t ifx, const void *buffer, int len, bool en_sys_seq);
esp_err_t esp_wifi_internal_set_rate(int a, int b, int c, wifi_internal_rate_t *d);
}
mac_t BCAST(true);
mac_t ME;
void setup() {
Serial.begin(115200);
Serial.println("Start");
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
esp_wifi_init(&cfg);
esp_wifi_set_mode(WIFI_MODE_NULL);
wifi_internal_rate_t rate;
rate.fix_rate = RATE_MCS4_SP;
esp_wifi_internal_set_rate(100, 1, 4, &rate);
esp_wifi_start();
esp_wifi_set_ps(WIFI_PS_NONE);
Serial.println("Done setup");
WiFi.macAddress(ME.mac);
}
void loop() {
byte data[sizeof(WiFiHeader) + 20];
WiFiHeader* pkt = (WiFiHeader*)data;
pkt->frame_control.type = WIFI_TYPE_DATA;
pkt->frame_control.subtype = 0;
pkt->frame_control.to_ds = 1;
pkt->address_1 = BCAST;
pkt->address_2 = ME;
pkt->address_3 = ME;
memset(data + sizeof(WiFiHeader), 40, 20);
int result = esp_wifi_80211_tx(WIFI_IF_AP, data, sizeof(data), true);
switch (result) {
case ERR_OK: Serial.println("ERR_OK"); break;
case ERR_MEM: Serial.println("ERR_MEM"); break;
case ERR_IF: Serial.println("ERR_IF"); break;
case ERR_ARG: Serial.println("ERR_ARG"); break;
default: Serial.println(result);
}
delay(1000);
}
#ifndef WIFI_HEADERS_H
#define WIFI_HEADERS_H
// https://www.safaribooksonline.com/library/view/80211-wireless-networks/0596100523/ch04.html
// https://mrncciew.files.wordpress.com/2014/10/cwap-mgmt-beacon-01.png
#define WIFI_TYPE_MANAGEMENT 0
#define WIFI_TYPE_CONTROL 1
#define WIFI_TYPE_DATA 2
#define WIFI_SUBTYPE_PROBE 4
#define WIFI_SUBTYPE_PROBE_RESPONSE 5
#define WIFI_SUBTYPE_BEACON 8
#define WIFI_SUBTYPE_CONTROL_ACK 13
#define WIFI_SUBTYPE_DATA_ACK 5
struct mac_t {
byte mac[6];
mac_t() {}
mac_t(byte addr[6]) {
memcpy(&this->mac, addr, 6);
}
mac_t(bool bcast) {
memset(&this->mac, bcast ? 255:0, 6);
}
inline bool operator==(const mac_t& lhs) const {
return memcmp(lhs.mac, this->mac, 6) == 0;
}
String print() const;
const char* to_str() const;
};
struct FrameControl {
uint8_t version:2;
uint8_t type:2;
uint8_t subtype:4;
bool to_ds:1;
bool from_ds:1;
bool more:1;
bool retry:1;
bool power_mgmt:1;
bool more_data:1;
bool WEP:1;
bool order:1;
} __attribute__((packed));
struct Sequence {
uint8_t fragment_number:4;
uint16_t sequence_number:12;
} __attribute__((packed));
struct WiFiHeader {
FrameControl frame_control; // Frame Control (2 bytes)
uint16_t duration; // Duration/ID (2 bytes) Set by SDK
mac_t address_1; // Address 1 (6 bytes) (to)
mac_t address_2; // Address 2 (6 bytes) (from)
mac_t address_3; // Address 3 (6 bytes) (Origin/BSSID)
Sequence sequence; // Squence (2 bytes)
WiFiHeader() {
memset(this, 0, sizeof(WiFiHeader));
}
WiFiHeader(uint8_t type, uint8_t subtype) {
memset(this, 0, sizeof(WiFiHeader));
frame_control.type = type;
frame_control.subtype = subtype;
}
} __attribute__((packed));
struct CapabilityInfo { // 16 bits - 2 bytes
bool ESS:1; // is infrastructure
bool IBSS:1; // is IBSS network (ad-hock)
bool cf_pollable:1; // Contention-free polling bits
bool cf_poll_request:1;// Contention-free polling bits
bool privacy:1; // WEP encryption.
bool short_preamable:1;// short preamble. Always 1 for g, optional for b.
bool PBCC:1; // Fast bitrate encoding for 802.11b or g
bool channel_agility:1;// High rate for 802.11b
unsigned:2;
bool short_slot_time:1;// for 802.11g
unsigned:2;
bool DSSS_OFDM:1; // ?
unsigned:2;
CapabilityInfo() {
memset(this, 0, sizeof(CapabilityInfo));
}
} __attribute__((packed));
struct BeaconHeader {
uint64_t timestamp;
uint16_t interval; // how often is this sent? in ms
CapabilityInfo capabilities;
};
struct Tag {
uint8_t element_id;
uint8_t length;
byte data[0];
inline const Tag* next() const {
return (Tag*)&(data[length]);
}
} __attribute__((packed));
template<typename T, uint8_t ID>
struct TagParameter {
uint8_t element_id;
uint8_t length;
T data;
TagParameter(const T& d)
: element_id(ID)
, length(sizeof(T))
, data(d)
{}
TagParameter()
: element_id(ID)
, length(sizeof(T))
, data()
{}
} __attribute__((packed));
template<typename T, int NUM, uint8_t ID>
struct TagParameterArray {
uint8_t element_id;
uint8_t length;
T data[NUM];
TagParameterArray()
: element_id(ID)
, length(sizeof(T) * NUM)
{}
} __attribute__((packed));
struct SSIDZero { // Element ID 0
uint8_t element_id;
uint8_t length;
SSIDZero() : element_id(0), length(0) {}
} __attribute__((packed));
struct SSIDTag {
uint8_t element_id;
uint8_t length;
char ssid[1];
} __attribute__((packed));
typedef TagParameterArray<uint8_t, 8, 1> SupportedRates;
// RxControl struct from ESP8266 SDK Programming Guide 1.5 (Page 191)
//struct RxControl { // Size = 12 bytes
// signed rssi:8; // signal intensity of packet
// unsigned rate:4;
// unsigned is_group:1;
// unsigned:1;
// unsigned sig_mode:2; // 0:is 11n packet; 1:is not 11n packet;
// unsigned legacy_length:12;// if not 11n packet, shows length of packet.
// unsigned damatch0:1;
// unsigned damatch1:1;
// unsigned bssidmatch0:1;
// unsigned bssidmatch1:1;
// unsigned MCS:7; // if is 11n packet, shows the modulation and code used (range from 0 to 76)
// unsigned CWB:1; // if is 11n packet, shows if is HT40 packet or not
// unsigned HT_length:16; // if is 11n packet, shows length of packet.
// unsigned Smoothing:1;
// unsigned Not_Sounding:1;
// unsigned:1;
// unsigned Aggregation:1;
// unsigned STBC:2;
// unsigned FEC_CODING:1; // if is 11n packet, shows if is LDPC packet or not.
// unsigned SGI:1;
// unsigned rxend_state:8;
// unsigned ampdu_cnt:8;
// unsigned channel:4; // which channel this packet in.
// unsigned:12;
//} __attribute__((packed));
#endif
@aknik
Copy link

aknik commented Mar 23, 2018

Where I can find "wifi_headers.h" ?
fatal error: wifi_headers.h: No such file or directory

@Nik-001
Copy link

Nik-001 commented Apr 28, 2022

Hello, would you be able to provide the "wifi_headers.h" library? Thanks

@mic159
Copy link
Author

mic159 commented May 1, 2022

Okay, I have updated the gist with the header file

@JayTSX
Copy link

JayTSX commented Jun 16, 2023

Hi, I get the following error on compile

ESP32_raw_packet.ino:56: undefined reference to `esp_wifi_internal_set_rate'

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment