FeitCSI/src/PacketInjector.cpp
2024-02-15 15:55:24 +01:00

192 lines
5.8 KiB
C++

/*
* FeitCSI is the tool for extracting CSI information from supported intel NICs.
* Copyright (C) 2023-2024 Miroslav Hutar.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "PacketInjector.h"
#include "main.h"
#include "Logger.h"
#include "Arguments.h"
#include <string.h>
#include <iostream>
#define SPATIAL_STREAM 16
uint8_t ieee80211Header[] = {
0xe0, 0x80, 0x00, 0x00, 0x00, 0x16, 0xea, 0x12, 0x34, 0x56, 0x00, 0x16, 0xea, 0x12, 0x34, 0x56, 0x98, 0x59, 0x7a, 0x8b, 0x34, 0x3b, 0x00, 0x00, 0x15, 0x03, 0x15, 0x20};
uint8_t ieee80211Body[] = {};
void PacketInjector::inject()
{
if (Arguments::arguments.verbose)
{
Logger::log(info) << "Injecting " << Arguments::arguments.format << "\n";
}
if (Arguments::arguments.format == "NOHT")
{
this->injectNoHT();
}
else if (Arguments::arguments.format == "HT")
{
this->injectHT();
}
else if (Arguments::arguments.format == "VHT")
{
this->injectVHT();
}
else if (Arguments::arguments.format == "HESU")
{
this->injectHE();
}
}
void PacketInjector::injectNoHT()
{
uint8_t mcs = 0;
if (RATE_LEGACY_RATE_MSK >= Arguments::arguments.mcs)
{
mcs = RATE_LEGACY_RATE_MSK & Arguments::arguments.mcs;
}
uint32_t rateNFlags = RATE_MCS_LEGACY_OFDM_MSK | mcs | Arguments::arguments.antenna;
this->send(rateNFlags);
}
void PacketInjector::injectHT()
{
uint8_t mcs = 0;
if (RATE_HT_MCS_CODE_MSK >= Arguments::arguments.mcs)
{
mcs = RATE_HT_MCS_CODE_MSK & Arguments::arguments.mcs;
}
uint32_t rateNFlags =
RATE_MCS_HT_MSK |
mcs |
Arguments::arguments.antenna |
(Arguments::arguments.channelWidth == 40 ? RATE_MCS_CHAN_WIDTH_40 : 0) |
(Arguments::arguments.spatialStreams == 2 ? SPATIAL_STREAM : 0) |
(Arguments::arguments.spatialStreams == 2 ? RATE_MCS_ANT_AB_MSK : 0) |
(Arguments::arguments.guardInterval == 400 ? RATE_MCS_SGI_MSK : 0) |
(Arguments::arguments.coding == "LDPC" ? RATE_MCS_LDPC_MSK : 0);
this->send(rateNFlags);
}
void PacketInjector::injectVHT()
{
uint8_t mcs = 0;
if (RATE_MCS_CODE_MSK >= Arguments::arguments.mcs)
{
mcs = RATE_MCS_CODE_MSK & Arguments::arguments.mcs;
}
uint32_t rateNFlags =
RATE_MCS_VHT_MSK |
mcs |
Arguments::arguments.antenna |
(Arguments::arguments.channelWidth == 40 ? RATE_MCS_CHAN_WIDTH_40 : 0) |
(Arguments::arguments.channelWidth == 80 ? RATE_MCS_CHAN_WIDTH_80 : 0) |
(Arguments::arguments.channelWidth == 160 ? RATE_MCS_CHAN_WIDTH_160 : 0) |
(Arguments::arguments.spatialStreams == 2 ? SPATIAL_STREAM : 0) |
(Arguments::arguments.spatialStreams == 2 ? RATE_MCS_ANT_AB_MSK : 0) |
(Arguments::arguments.guardInterval == 400 ? RATE_MCS_SGI_MSK : 0) |
(Arguments::arguments.coding == "LDPC" ? RATE_MCS_LDPC_MSK : 0);
this->send(rateNFlags);
}
void PacketInjector::injectHE()
{
uint8_t mcs = 0;
if (RATE_MCS_CODE_MSK >= Arguments::arguments.mcs)
{
mcs = RATE_MCS_CODE_MSK & Arguments::arguments.mcs;
}
uint32_t ltf = 1;
if (Arguments::arguments.ltf == "2xLTF+0.8")
{
ltf = 1;
}
else if (Arguments::arguments.ltf == "2xLTF+1.6")
{
ltf = 2;
}
else if (Arguments::arguments.ltf == "4xLTF+3.2")
{
ltf = 3;
}
else if (Arguments::arguments.ltf == "4xLTF+0.8")
{
ltf = 4;
}
ltf = (ltf << RATE_MCS_HE_GI_LTF_POS) & RATE_MCS_HE_GI_LTF_MSK;
uint32_t rateNFlags =
RATE_MCS_HE_MSK |
RATE_MCS_LDPC_MSK |
mcs |
Arguments::arguments.antenna |
ltf |
(Arguments::arguments.channelWidth == 40 ? RATE_MCS_CHAN_WIDTH_40 : 0) |
(Arguments::arguments.channelWidth == 80 ? RATE_MCS_CHAN_WIDTH_80 : 0) |
(Arguments::arguments.channelWidth == 160 ? RATE_MCS_CHAN_WIDTH_160 : 0) |
(Arguments::arguments.spatialStreams == 2 ? SPATIAL_STREAM : 0) |
(Arguments::arguments.spatialStreams == 2 ? RATE_MCS_ANT_AB_MSK : 0);
this->send(rateNFlags);
}
void PacketInjector::send(uint32_t rateNFlags)
{
uint32_t pos = 0;
struct ieee80211_radiotap_header rthdr;
rthdr.it_version = 0;
rthdr.it_pad = 0;
rthdr.it_present = 0;
rthdr.it_present |= BIT(IEEE80211_RADIOTAP_FLAGS);
rthdr.it_optional[pos++] = 0x80;
memcpy(&rthdr.it_optional[pos++], &rateNFlags, 4);
pos += 3;
rthdr.it_len = pos + 8;
uint8_t sendBuffer[1000];
memcpy(sendBuffer, (uint8_t *)&rthdr, rthdr.it_len);
memcpy(&sendBuffer[rthdr.it_len], ieee80211Header, sizeof(ieee80211Header));
memcpy(&sendBuffer[rthdr.it_len + sizeof(ieee80211Header)], ieee80211Body, sizeof(ieee80211Body));
int totalSize = rthdr.it_len + sizeof(ieee80211Header) + sizeof(ieee80211Body);
char szErrbuf[500];
if (ppcap == nullptr) {
ppcap = pcap_open_live("mon0", 800, 1, 20, szErrbuf);
}
int r = pcap_inject(ppcap, sendBuffer, totalSize);
if (r != totalSize)
{
//pcap_perror(ppcap, "Failed to inject packet");
pcap_close(ppcap);
ppcap = nullptr;
//throw std::ios_base::failure("Failed to inject packet\n");
}
//pcap_close(ppcap);
}