Skip to content

Commit

Permalink
Use raw sockets for injection instead of pcap
Browse files Browse the repository at this point in the history
  • Loading branch information
svpcom committed Mar 19, 2024
1 parent e8901a8 commit e4ad659
Show file tree
Hide file tree
Showing 3 changed files with 80 additions and 52 deletions.
4 changes: 2 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ DOCKER_SRC_IMAGE ?= "p2ptech/cross-build:2023-02-21-raspios-bullseye-armhf-lite"

export VERSION COMMIT SOURCE_DATE_EPOCH

_LDFLAGS := $(LDFLAGS) -lrt -lpcap -lsodium
_LDFLAGS := $(LDFLAGS) -lrt -lsodium
_CFLAGS := $(CFLAGS) -Wall -O2 -DWFB_VERSION='"$(VERSION)-$(shell /bin/bash -c '_tmp=$(COMMIT); echo $${_tmp::8}')"'

all: all_bin gs.key test
Expand All @@ -29,7 +29,7 @@ src/%.o: src/%.cpp src/*.hpp src/*.h
$(CXX) $(_CFLAGS) -std=gnu++11 -c -o $@ $<

wfb_rx: src/rx.o src/radiotap.o src/fec.o src/wifibroadcast.o
$(CXX) -o $@ $^ $(_LDFLAGS)
$(CXX) -o $@ $^ $(_LDFLAGS) -lpcap

wfb_tx: src/tx.o src/fec.o src/wifibroadcast.o
$(CXX) -o $@ $^ $(_LDFLAGS)
Expand Down
118 changes: 73 additions & 45 deletions src/tx.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,12 @@
#include <poll.h>
#include <time.h>
#include <sys/resource.h>
#include <pcap/pcap.h>
#include <assert.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <net/if.h>
#include <linux/if_packet.h>
#include <linux/if_ether.h>
#include <linux/random.h>
#include <inttypes.h>

Expand Down Expand Up @@ -122,89 +124,115 @@ void Transmitter::make_session_key(void)
}
}


PcapTransmitter::PcapTransmitter(int k, int n, const string &keypair, uint64_t epoch, uint32_t channel_id, const vector<string> &wlans) : \
RawSocketTransmitter::RawSocketTransmitter(int k, int n, const string &keypair, uint64_t epoch, uint32_t channel_id, const vector<string> &wlans) : \
Transmitter(k, n, keypair, epoch, channel_id),
channel_id(channel_id),
current_output(0),
ieee80211_seq(0)
{
char errbuf[PCAP_ERRBUF_SIZE];
for(auto it=wlans.begin(); it!=wlans.end(); it++)
{
pcap_t *p = pcap_create(it->c_str(), errbuf);
if (p == NULL){
throw runtime_error(string_format("Unable to open interface %s in pcap: %s", it->c_str(), errbuf));
int fd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
if (fd < 0)
{
throw runtime_error(string_format("Unable to open PF_PACKET socket: %s", strerror(errno)));
}

struct ifreq ifr;
memset(&ifr, '\0', sizeof(ifr));
strncpy(ifr.ifr_name, it->c_str(), sizeof(ifr.ifr_name) - 1);

if (ioctl(fd, SIOCGIFINDEX, &ifr) < 0)
{
close(fd);
throw runtime_error(string_format("Unable to get interface index for %s", it->c_str()));
}

struct sockaddr_ll sll;
memset(&sll, '\0', sizeof(sll));
sll.sll_family = AF_PACKET;
sll.sll_ifindex = ifr.ifr_ifindex;
sll.sll_protocol = htons(ETH_P_ALL);

if (bind(fd, (struct sockaddr *) &sll, sizeof(sll)) < 0)
{
close(fd);
throw runtime_error(string_format("Unable to bind to %s", it->c_str()));
}
if (pcap_set_snaplen(p, 4096) !=0) throw runtime_error("set_snaplen failed");
if (pcap_set_promisc(p, 1) != 0) throw runtime_error("set_promisc failed");
//if (pcap_set_rfmon(p, 1) !=0) throw runtime_error("set_rfmon failed");
if (pcap_set_timeout(p, -1) !=0) throw runtime_error("set_timeout failed");
//if (pcap_set_buffer_size(p, 2048) !=0) throw runtime_error("set_buffer_size failed");
if (pcap_set_immediate_mode(p, 1) != 0) throw runtime_error(string_format("pcap_set_immediate_mode failed: %s", pcap_geterr(p)));
if (pcap_activate(p) !=0) throw runtime_error(string_format("pcap_activate failed: %s", pcap_geterr(p)));
//if (pcap_setnonblock(p, 1, errbuf) != 0) throw runtime_error(string_format("set_nonblock failed: %s", errbuf));

ppcap.push_back(p);

sockfds.push_back(fd);
}
}


void PcapTransmitter::inject_packet(const uint8_t *buf, size_t size)
void RawSocketTransmitter::inject_packet(const uint8_t *buf, size_t size)
{
uint8_t txbuf[MAX_PACKET_SIZE];
uint8_t *p = txbuf;

assert(size <= MAX_FORWARDER_PACKET_SIZE);

// radiotap header
memcpy(p, radiotap_header, sizeof(radiotap_header));
p += sizeof(radiotap_header);

// ieee80211 header
memcpy(p, ieee80211_header, sizeof(ieee80211_header));
uint8_t ieee_hdr[sizeof(ieee80211_header)];
memcpy(ieee_hdr, ieee80211_header, sizeof(ieee80211_header));

// channel_id
uint32_t channel_id_be = htobe32(channel_id);
memcpy(p + SRC_MAC_THIRD_BYTE, &channel_id_be, sizeof(uint32_t));
memcpy(p + DST_MAC_THIRD_BYTE, &channel_id_be, sizeof(uint32_t));
memcpy(ieee_hdr + SRC_MAC_THIRD_BYTE, &channel_id_be, sizeof(uint32_t));
memcpy(ieee_hdr + DST_MAC_THIRD_BYTE, &channel_id_be, sizeof(uint32_t));

// sequence number
p[FRAME_SEQ_LB] = ieee80211_seq & 0xff;
p[FRAME_SEQ_HB] = (ieee80211_seq >> 8) & 0xff;
ieee_hdr[FRAME_SEQ_LB] = ieee80211_seq & 0xff;
ieee_hdr[FRAME_SEQ_HB] = (ieee80211_seq >> 8) & 0xff;
ieee80211_seq += 16;
p += sizeof(ieee80211_header);

// FEC data
memcpy(p, buf, size);
p += size;
struct iovec iov[3] = \
{
// radiotap header
{ .iov_base = (void*)radiotap_header,
.iov_len = sizeof(radiotap_header)
},
// ieee80211 header
{ .iov_base = (void*)ieee_hdr,
.iov_len = sizeof(ieee_hdr)
},
// FEC encoded data
{ .iov_base = (void*)buf,
.iov_len = size
}
};

struct msghdr msghdr = \
{ .msg_name = NULL,
.msg_namelen = 0,
.msg_iov = iov,
.msg_iovlen = 3,
.msg_control = NULL,
.msg_controllen = 0,
.msg_flags = 0};

if (current_output >= 0)
{
// Normal mode
if (pcap_inject(ppcap[current_output], txbuf, p - txbuf) != p - txbuf)
if (sendmsg(sockfds[current_output], &msghdr, 0) < 0)
{
throw runtime_error(string_format("Unable to inject packet"));
throw runtime_error(string_format("Unable to inject packet: %s", strerror(errno)));
}
}
else
{
// Mirror mode - transmit packet via all cards
// Use only for different frequency channels
for(auto it=ppcap.begin(); it != ppcap.end(); it++)
for(auto it=sockfds.begin(); it != sockfds.end(); it++)
{
if (pcap_inject(*it, txbuf, p - txbuf) != p - txbuf)
if (sendmsg(*it, &msghdr, 0) < 0)
{
throw runtime_error(string_format("Unable to inject packet"));
throw runtime_error(string_format("Unable to inject packet: %s", strerror(errno)));
}
}
}
}

PcapTransmitter::~PcapTransmitter()
RawSocketTransmitter::~RawSocketTransmitter()
{
for(auto it=ppcap.begin(); it != ppcap.end(); it++){
pcap_close(*it);
for(auto it=sockfds.begin(); it != sockfds.end(); it++)
{
close(*it);
}
}

Expand Down Expand Up @@ -611,7 +639,7 @@ int main(int argc, char * const *argv)
fprintf(stderr, "Using %zu ports from %d for wlan emulation\n", wlans.size(), debug_port);
t = shared_ptr<UdpTransmitter>(new UdpTransmitter(k, n, keypair, "127.0.0.1", debug_port, epoch, channel_id));
} else {
t = shared_ptr<PcapTransmitter>(new PcapTransmitter(k, n, keypair, epoch, channel_id, wlans));
t = shared_ptr<RawSocketTransmitter>(new RawSocketTransmitter(k, n, keypair, epoch, channel_id, wlans));
}

data_source(t, rx_fd, poll_timeout, mirror);
Expand Down
10 changes: 5 additions & 5 deletions src/tx.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,19 +61,18 @@ class Transmitter
uint8_t session_key_packet[sizeof(wsession_hdr_t) + sizeof(wsession_data_t) + crypto_box_MACBYTES];
};


class PcapTransmitter : public Transmitter
class RawSocketTransmitter : public Transmitter
{
public:
PcapTransmitter(int k, int m, const std::string &keypair, uint64_t epoch, uint32_t channel_id, const std::vector<std::string> &wlans);
virtual ~PcapTransmitter();
RawSocketTransmitter(int k, int m, const std::string &keypair, uint64_t epoch, uint32_t channel_id, const std::vector<std::string> &wlans);
virtual ~RawSocketTransmitter();
virtual void select_output(int idx) { current_output = idx; }
private:
virtual void inject_packet(const uint8_t *buf, size_t size);
const uint32_t channel_id;
int current_output;
uint16_t ieee80211_seq;
std::vector<pcap_t*> ppcap;
std::vector<int> sockfds;
};


Expand Down Expand Up @@ -107,6 +106,7 @@ class UdpTransmitter : public Transmitter
private:
virtual void inject_packet(const uint8_t *buf, size_t size)
{
assert(size <= MAX_FORWARDER_PACKET_SIZE);
wrxfwd_t fwd_hdr = { .wlan_idx = (uint8_t)(rand() % 2) };

memset(fwd_hdr.antenna, 0xff, sizeof(fwd_hdr.antenna));
Expand Down

0 comments on commit e4ad659

Please sign in to comment.