aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTrygve Laugstøl <trygvis@inamo.no>2017-04-07 21:49:36 +0200
committerTrygve Laugstøl <trygvis@inamo.no>2017-04-07 21:49:36 +0200
commit4eba89add8db804c33e8692edf5b27c2d3a2e365 (patch)
tree5fba0a0fa4d6010d13f99215508212086a116063
parent36e59a1991f075e36e117a08321d5e4c4dc00eac (diff)
downloadwifi-triangulator-4eba89add8db804c33e8692edf5b27c2d3a2e365.tar.gz
wifi-triangulator-4eba89add8db804c33e8692edf5b27c2d3a2e365.tar.bz2
wifi-triangulator-4eba89add8db804c33e8692edf5b27c2d3a2e365.tar.xz
wifi-triangulator-4eba89add8db804c33e8692edf5b27c2d3a2e365.zip
o Cleaning up code, fixing many small bugs.HEADmaster
o Making a better envelope format. o Reading out the interface's channel.
-rw-r--r--CMakeLists.txt10
-rw-r--r--README.md15
-rw-r--r--include/wifi-triangulator/core.h27
-rw-r--r--src/capture.cpp45
-rw-r--r--src/core.cpp133
-rw-r--r--src/formatter.cpp50
-rw-r--r--src/misc.cpp28
-rw-r--r--src/receiver.cpp29
-rw-r--r--src/transmitter.cpp28
-rw-r--r--wifi-triangulator.proto24
10 files changed, 259 insertions, 130 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 141beda..df5472a 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -16,9 +16,15 @@ if (NOT HAVE_PCAP_H)
endif ()
find_package(Protobuf REQUIRED)
-include_directories(${Protobuf_INCLUDE_DIRS} ${Protobuf_INCLUDE_DIR})
+
+check_include_files("iwlib.h" HAVE_IWLIB_H)
+
+if (NOT HAVE_IWLIB_H)
+ message(FATAL_ERROR "Missing iwlib.h. You should probably install libiw-dev.")
+endif ()
# lib wifi-triangulator
+include_directories(${Protobuf_INCLUDE_DIRS} ${Protobuf_INCLUDE_DIR})
protobuf_generate_cpp(PROTO_SRC PROTO_HEADER wifi-triangulator.proto)
add_library(wifi-triangulator
@@ -35,7 +41,7 @@ target_link_libraries(wifi-triangulator PUBLIC pcap ${Protobuf_LIBRARIES})
# capture
add_executable(capture src/capture.cpp)
-target_link_libraries(capture PUBLIC wifi-triangulator)
+target_link_libraries(capture PUBLIC wifi-triangulator iw)
# transmitter
add_executable(transmitter src/transmitter.cpp)
diff --git a/README.md b/README.md
index 8d94a33..72cc478 100644
--- a/README.md
+++ b/README.md
@@ -7,6 +7,15 @@
# Running
- sudo ifconfig wlan0 down
- sudo iwconfig wlan0 mode monitor
- sudo build/wifi-triangulator wlan0
+Set all available wlan interfaces in monitor mode on different channels:
+
+ /sbin/iw dev | sed -n 's,.*Interface \(.*\),\1,p' |sort -n | while read iface; do
+ echo "Configuring $iface"
+ sudo ifconfig $iface down
+ n=$(echo $iface | sed 's,wlan\(.*\),\1,')
+ sudo ifconfig $iface channel $(($n+1))
+ sudo iwconfig $iface mode monitor
+ sudo ifconfig $iface up
+ done
+
+ sudo build/capture wlan0 | build/transmitter 10.13.37.30
diff --git a/include/wifi-triangulator/core.h b/include/wifi-triangulator/core.h
index 042490a..15fb07b 100644
--- a/include/wifi-triangulator/core.h
+++ b/include/wifi-triangulator/core.h
@@ -9,6 +9,10 @@
namespace wifi_triangulator {
+extern std::string app_name;
+
+typedef std::basic_string<uint8_t> bstring;
+
struct eth_mac {
uint8_t a, b, c, d, e, f;
@@ -45,21 +49,36 @@ struct eth_mac {
class data {
public:
- pb::packet_type type;
+ pb::frame_type type;
long sec;
long usec;
int rssi;
+ int mhz;
eth_mac src, dst;
- data(pb::packet_type type, long sec, long usec, int rssi, eth_mac src, eth_mac dst) :
- type(type), sec(sec), usec(usec), src(src), rssi(rssi), dst(dst) {}
+ data(pb::frame_type type, long sec, long usec, int rssi, int mhz, eth_mac src, eth_mac dst) :
+ type(type), sec(sec), usec(usec), rssi(rssi), mhz(mhz), src(src), dst(dst) {}
};
int launch_capture(std::string dev, std::function<void(const class data &)>);
+int launch_reader(std::function<bool(uint16_t size, const uint8_t *data)> on_buffer);
+
+int launch_reader_envelope(std::function<bool(const pb::envelope &)> on_envelope);
+
+ssize_t read_stdin(uint8_t *data, size_t left);
+
+//void write_stdout(const bstring &s);
+
+void write_stdout(const std::string &s);
+
+void write_stdout(const uint8_t *data, size_t count);
+
+void write_envelope(pb::letter_type lt, pb::envelope &envelope);
+
} // namespace wifi_triangulator
namespace std {
-string to_string(wifi_triangulator::pb::packet_type t);
+string to_string(wifi_triangulator::pb::frame_type t);
} // namespace std
diff --git a/src/capture.cpp b/src/capture.cpp
index 5844b25..a6cc713 100644
--- a/src/capture.cpp
+++ b/src/capture.cpp
@@ -1,10 +1,20 @@
#include <iostream>
+#include <iwlib.h>
#include "wifi-triangulator/core.h"
using namespace std;
using namespace wifi_triangulator;
+void send_info(uint64_t freq) {
+ pb::envelope envelope;
+ pb::listener_station_info *i = envelope.mutable_listener_station_info();
+ i->set_freq(freq);
+ write_envelope(pb::letter_type::listener_station_info_lt, envelope);
+}
+
int main(int argc, char *argv[]) {
+ app_name = argv[0];
+
if (argc != 2) {
fprintf(stderr, "usage: %s [interface]\n", argv[0]);
return EXIT_FAILURE;
@@ -14,24 +24,39 @@ int main(int argc, char *argv[]) {
GOOGLE_PROTOBUF_VERIFY_VERSION;
- string str;
- str.reserve(1 << 16);
+ int iw;
+ if ((iw = iw_sockets_open()) < 0) {
+ perror("Could not open iw sockets");
+ return EXIT_FAILURE;
+ }
+
+ wireless_config wc;
+ if (iw_get_basic_config(iw, dev.c_str(), &wc) < 0) {
+ perror("iw_get_basic_config");
+ return EXIT_FAILURE;
+ }
+
+ auto freq = static_cast<uint64_t>(wc.freq);
+
+ send_info(freq);
int ret = launch_capture(dev, [&](const data &data) {
pb::envelope envelope;
envelope.set_time_s(data.sec);
envelope.set_time_us(data.usec);
- envelope.set_type(data.type);
- if (data.type == pb::packet_type::probe_request) {
- pb::probe *probe = envelope.mutable_probe();
+ pb::frame *frame = envelope.mutable_frame();
+ frame->set_type(data.type);
+
+ if (data.type == pb::frame_type ::probe_request) {
+ pb::probe *probe = frame->mutable_probe();
probe->set_src(data.src);
- probe->set_dst(static_cast<uint64_t>(data.dst));
- probe->set_rssi(data.rssi);
+ if (data.rssi) {
+ probe->set_rssi(data.rssi);
+ }
}
- envelope.SerializeToString(&str);
- cout << static_cast<uint16_t>(str.length()) << str << flush;
+ write_envelope(pb::letter_type::frame_lt, envelope);
// static int count = 0;
// cerr << "count=" << count << "!\r" << flush;
@@ -40,7 +65,7 @@ int main(int argc, char *argv[]) {
google::protobuf::ShutdownProtobufLibrary();
- cerr << "Capture exiting" << endl;
+ cerr << app_name << " exiting" << endl;
cout.flush();
return ret;
diff --git a/src/core.cpp b/src/core.cpp
index 8cb595f..69d38cf 100644
--- a/src/core.cpp
+++ b/src/core.cpp
@@ -1,4 +1,5 @@
-#include <stdlib.h>
+#include <unistd.h>
+#include <cstdlib>
#include <iostream>
#include <pcap.h>
#include <cinttypes>
@@ -7,11 +8,13 @@
#include "../third-party/radiotap-library/radiotap.h"
#include "wifi-triangulator/core.h"
-using std::string;
+using namespace std;
using namespace wifi_triangulator::pb;
namespace wifi_triangulator {
+std::string app_name;
+
struct ieee802_11_header {
uint8_t frame_1;
uint8_t frame_2;
@@ -97,6 +100,7 @@ void got_packet(u_char *args, const struct pcap_pkthdr *header, const u_char *pa
auto *present_ptr = &rtaphdr->it_present;
bool is_radiotap = true;
+ uint16_t mhz = 0;
int rssi = 0;
do {
uint32_t present = *present_ptr;
@@ -128,7 +132,7 @@ void got_packet(u_char *args, const struct pcap_pkthdr *header, const u_char *pa
present &= ~(1 << IEEE80211_RADIOTAP_RATE);
}
if (present & 1 << IEEE80211_RADIOTAP_CHANNEL) {
- uint16_t mhz = it.read16u();
+ mhz = it.read16u();
uint16_t bitmap = it.read16u();
snprintf(buf, 100, "IEEE80211_RADIOTAP_CHANNEL: %d MHz, flags=%04x\n", mhz, bitmap);
@@ -181,7 +185,7 @@ void got_packet(u_char *args, const struct pcap_pkthdr *header, const u_char *pa
if (present & 1 << IEEE80211_RADIOTAP_ANTENNA) {
uint8_t antenna = it.read8u();
- snprintf(buf, 100, "IEEE80211_RADIOTAP_ANTENNA: antenna=%d\n", antenna);
+// snprintf(buf, 100, "IEEE80211_RADIOTAP_ANTENNA: antenna=%d\n", antenna);
present &= ~(1 << IEEE80211_RADIOTAP_ANTENNA);
}
if (present & 1 << IEEE80211_RADIOTAP_DB_ANTSIGNAL) {
@@ -199,7 +203,7 @@ void got_packet(u_char *args, const struct pcap_pkthdr *header, const u_char *pa
if (present & 1 << IEEE80211_RADIOTAP_RX_FLAGS) {
uint16_t rx_flags = it.read16u();
- snprintf(buf, 100, "IEEE80211_RADIOTAP_RX_FLAGS: rx_flags=%d\n", rx_flags);
+// snprintf(buf, 100, "IEEE80211_RADIOTAP_RX_FLAGS: rx_flags=%d\n", rx_flags);
present &= ~(1 << IEEE80211_RADIOTAP_RX_FLAGS);
}
if (present & 1 << IEEE80211_RADIOTAP_TX_FLAGS) {
@@ -214,7 +218,8 @@ void got_packet(u_char *args, const struct pcap_pkthdr *header, const u_char *pa
break;
}
-// printf(buf);
+// fprintf(stderr, buf);
+// fflush(stderr);
/*
int bit = 0;
uint32_t mask = 1;
@@ -235,43 +240,43 @@ void got_packet(u_char *args, const struct pcap_pkthdr *header, const u_char *pa
uint8_t type = ieee802_11_header->frame_1;
- packet_type t;
+ frame_type t;
switch (type) {
case 0x40:
- t = packet_type::probe_request;
+ t = frame_type::probe_request;
break;
case 0x80:
- t = packet_type::beacon;
+ t = frame_type::beacon;
break;
case 0x50:
- t = packet_type::probe_response;
+ t = frame_type::probe_response;
break;
case 0x48:
- t = packet_type::null;
+ t = frame_type::null;
break;
case 0xd4:
- t = packet_type::ack;
+ t = frame_type::ack;
break;
case 0x08:
- t = packet_type::data;
+ t = frame_type::data;
break;
case 0xc4:
- t = packet_type::cts;
+ t = frame_type::cts;
break;
case 0xb4:
- t = packet_type::rts;
+ t = frame_type::rts;
break;
case 0x1e:
- t = packet_type::cf_end;
+ t = frame_type::cf_end;
break;
case 0x1f:
- t = packet_type::cf_end_cf_ack;
+ t = frame_type::cf_end_cf_ack;
break;
case 0x1a:
- t = packet_type::ps_poll;
+ t = frame_type::ps_poll;
break;
default:
- t = packet_type::unknown;
+ t = frame_type::unknown;
}
// printf("ieee802_11_header->frame_ctl=%02x, %s\n", type, type_str ? type_str : "???");
@@ -299,7 +304,8 @@ void got_packet(u_char *args, const struct pcap_pkthdr *header, const u_char *pa
ctx->data_consumer(data{
t,
header->ts.tv_sec, header->ts.tv_usec,
- rssi, src, dst});
+ rssi, mhz,
+ src, dst});
}
int launch_capture(string dev, std::function<void(const class data &)> data_consumer) {
@@ -336,12 +342,10 @@ int launch_capture(string dev, std::function<void(const class data &)> data_cons
auto ret = pcap_loop(handle, 1000, got_packet, reinterpret_cast<u_char *>(&ctx));
if (ret == -1) {
- printf("pcap failed: %s\n",
- pcap_geterr(handle)
- );
+ printf("pcap failed: %s\n", pcap_geterr(handle));
break;
} else if (ret == -2) {
-// someone called break loop
+ // someone called break loop
break;
}
}
@@ -351,4 +355,85 @@ int launch_capture(string dev, std::function<void(const class data &)> data_cons
return EXIT_SUCCESS;
}
+int launch_reader(std::function<bool(uint16_t size, const uint8_t *data)> on_buffer) {
+ uint8_t buffer[1 << 16];
+ while (true) {
+ uint16_t size;
+
+ if (read_stdin(reinterpret_cast<uint8_t *>(&size), 2) < 0) {
+ break;
+ }
+
+ ssize_t got;
+ if ((got = read_stdin(buffer, size)) != size) {
+ cout << "short read, got=" << got << endl;
+ return EXIT_FAILURE;
+ }
+
+ bool ok = on_buffer(size, buffer);
+
+ if (!ok) {
+ break;
+ }
+ }
+
+ return EXIT_SUCCESS;
+}
+
+int launch_reader_envelope(std::function<bool(const pb::envelope &)> on_envelope) {
+ pb::envelope envelope;
+
+ return launch_reader([&](uint16_t size, const uint8_t *data) {
+ bool ok = envelope.ParseFromArray(data, size);
+ return ok && on_envelope(envelope);
+ });
+}
+
+ssize_t read_stdin(uint8_t *data, const size_t count) {
+ auto left = count;
+ while (left > 0) {
+ ssize_t n_read = read(STDIN_FILENO, data, left);
+
+ if (n_read < 0) {
+ return n_read;
+ }
+
+ left -= n_read;
+ }
+
+ return count;
+}
+
+//void write_stdout(const bstring &s) {
+// write_stdout(s.c_str(), s.length());
+//}
+
+void write_stdout(const std::string &s) {
+ static_assert(sizeof(char) == sizeof(uint8_t), "bad sizes");
+ write_stdout(reinterpret_cast<const uint8_t *>(s.c_str()), s.length());
+}
+
+void write_stdout(const uint8_t *data, size_t count) {
+ size_t left = count;
+ const uint8_t *buf = data;
+ while (left > 0) {
+ auto written = write(STDOUT_FILENO, data, left);
+ buf += written;
+ left -= written;
+ }
+ syncfs(STDOUT_FILENO);
+}
+
+void write_envelope(pb::letter_type lt, pb::envelope &envelope) {
+ std::string str;
+ str.reserve(64 * 1024);
+
+ envelope.set_type(lt);
+
+ envelope.SerializeToString(&str);
+ uint16_t len = static_cast<uint16_t>(str.length());
+ write_stdout(reinterpret_cast<uint8_t *>(&len), 2);
+ write_stdout(str);
+}
+
} // namespace wifi_triangulator
diff --git a/src/formatter.cpp b/src/formatter.cpp
index b165a89..e4874dc 100644
--- a/src/formatter.cpp
+++ b/src/formatter.cpp
@@ -7,21 +7,42 @@ using namespace wifi_triangulator;
void on_probe_request(const pb::probe &p) {
cout << "PROBE REQUEST"
<< ", src=" << eth_mac(p.src()).to_string()
- << ", dst=" << eth_mac(p.dst()).to_string()
<< ", rssi=" << p.rssi()
<< flush
<< endl;
}
-void on_envelope(pb::envelope envelope) {
- if (envelope.type() == pb::probe_request) {
- on_probe_request(envelope.probe());
+void on_frame(const pb::frame &f) {
+ if (f.type() == pb::frame_type::probe_request) {
+ on_probe_request(f.probe());
} else {
- cout << to_string(envelope.type()) << endl;
+// cout << "frame: " << to_string(f.type()) << endl;
}
}
+void on_listener_station_info(const pb::listener_station_info &i) {
+ cout << "LISTENER STATION INFO"
+ << " mac=" << eth_mac(i.mac()).to_string()
+ << ", freq=" << i.freq()
+ << flush
+ << endl;
+}
+
+bool on_envelope(const pb::envelope &envelope) {
+ if (envelope.type() == pb::letter_type::frame_lt) {
+ on_frame(envelope.frame());
+ } else if (envelope.type() == pb::letter_type ::listener_station_info_lt) {
+ on_listener_station_info(envelope.listener_station_info());
+ } else {
+ cout << "Unknown letter type: " << envelope.type() << endl;
+ }
+
+ return true;
+}
+
int main(int argc, char *argv[]) {
+ app_name = argv[0];
+
GOOGLE_PROTOBUF_VERIFY_VERSION;
if (argc != 1) {
@@ -29,24 +50,7 @@ int main(int argc, char *argv[]) {
return EXIT_FAILURE;
}
- int count = 0;
- uint8_t buffer[1 << 16];
- while (!feof(stdin)) {
- pb::envelope envelope;
-
- uint16_t size;
- cin >> size;
- cin.read(reinterpret_cast<char *>(buffer), size);
- bool ok = envelope.ParseFromArray(buffer, size);
- if (!ok) {
- cerr << "bad read" << endl;
- continue;
- }
-
-// cerr << "count=" << count++ << endl;
-
- on_envelope(envelope);
- }
+ launch_reader_envelope(on_envelope);
google::protobuf::ShutdownProtobufLibrary();
diff --git a/src/misc.cpp b/src/misc.cpp
index ffe174f..cd45013 100644
--- a/src/misc.cpp
+++ b/src/misc.cpp
@@ -1,33 +1,33 @@
#include "wifi-triangulator/core.h"
namespace std {
-string to_string(wifi_triangulator::pb::packet_type t) {
- using wifi_triangulator::pb::packet_type;
+string to_string(wifi_triangulator::pb::frame_type t) {
+ using wifi_triangulator::pb::frame_type;
switch (t) {
- case packet_type::probe_request:
+ case frame_type::probe_request:
return "probe request";
- case packet_type::beacon:
+ case frame_type::beacon:
return "beacon";
- case packet_type::probe_response:
+ case frame_type::probe_response:
return "probe response";
- case packet_type::null:
+ case frame_type::null:
return "null";
- case packet_type::ack:
+ case frame_type::ack:
return "ack";
- case packet_type::data:
+ case frame_type::data:
return "data";
- case packet_type::cts:
+ case frame_type::cts:
return "cts";
- case packet_type::rts:
+ case frame_type::rts:
return "rts";
- case packet_type::cf_end:
+ case frame_type::cf_end:
return "cf-end";
- case packet_type::cf_end_cf_ack:
+ case frame_type::cf_end_cf_ack:
return "cf-end+cf-ack";
- case packet_type::ps_poll:
+ case frame_type::ps_poll:
return "ps-poll";
- case packet_type::unknown:
+ case frame_type::unknown:
default:
return "unknown";
}
diff --git a/src/receiver.cpp b/src/receiver.cpp
index c6c5bdc..7ac940a 100644
--- a/src/receiver.cpp
+++ b/src/receiver.cpp
@@ -9,15 +9,9 @@
using namespace std;
using namespace wifi_triangulator;
-void on_probe_request(const pb::probe &p) {
- cerr << "PROBE REQUEST"
- << ", src=" << eth_mac(p.src()).to_string()
- << ", dst=" << eth_mac(p.dst()).to_string()
- << ", rssi=" << p.rssi()
- << endl;
-}
-
int main(int argc, char *argv[]) {
+ app_name = argv[0];
+
if (argc != 1) {
fprintf(stderr, "usage: %s\n", argv[0]);
return EXIT_FAILURE;
@@ -48,23 +42,12 @@ int main(int argc, char *argv[]) {
struct sockaddr_in si_other;
socklen_t addr_len;
if ((n_read = ::recvfrom(s, bytes, len, 0, reinterpret_cast<struct sockaddr *>(&si_other), &addr_len)) == -1) {
- throw std::runtime_error("recvfrom");
+ throw std::runtime_error("recvfrom: " + string(strerror(errno)));
}
- string str;
- for (socklen_t i = 0; i < n_read; i++) {
- str += bytes[i];
- }
-
- istringstream ss{str};
- bool ok = envelope.ParseFromIstream(&ss);
- if (ok) {
- if (envelope.type() == pb::probe_request) {
- on_probe_request(envelope.probe());
- }
- } else {
- cerr << "FAIL n_read=" << n_read << flush << endl;
- }
+ uint16_t size = static_cast<uint16_t>(n_read);
+ write_stdout(reinterpret_cast<uint8_t *>(&size), 2);
+ write_stdout(bytes, static_cast<size_t>(n_read));
}
google::protobuf::ShutdownProtobufLibrary();
diff --git a/src/transmitter.cpp b/src/transmitter.cpp
index 047d37d..42295bb 100644
--- a/src/transmitter.cpp
+++ b/src/transmitter.cpp
@@ -46,32 +46,14 @@ int main(int argc, char *argv[]) {
addr = reinterpret_cast<struct sockaddr *>(&addr_si);
addr_len = sizeof(addr_si);
- int count = 0;
- uint8_t buffer[1 << 16];
- while (!feof(stdin)) {
- pb::envelope envelope;
-
- uint16_t size;
-
- cin >> size;
- cin.read(reinterpret_cast<char *>(buffer), size);
-
- /*
- bool ok = envelope.ParseFromArray(buffer, size);
- if (!ok) {
- cerr << "bad read" << endl;
- continue;
- }
- */
-
- if (sendto(s, buffer, size, 0, addr, addr_len) == -1) {
+ launch_reader([&](uint16_t size, const uint8_t* data) {
+ if (sendto(s, data, size, 0, addr, addr_len) == -1) {
throw std::runtime_error("sendto failed");
}
- cerr << "count=" << count++ << endl;
- }
-
- cerr << "transmitter exiting" << endl;
+ return true;
+ });
+ cerr << app_name << " exiting" << endl;
google::protobuf::ShutdownProtobufLibrary();
diff --git a/wifi-triangulator.proto b/wifi-triangulator.proto
index 959a370..accd829 100644
--- a/wifi-triangulator.proto
+++ b/wifi-triangulator.proto
@@ -2,7 +2,12 @@ syntax = "proto3";
package wifi_triangulator.pb;
-enum packet_type {
+message listener_station_info {
+ fixed64 mac = 1;
+ int64 freq = 2;
+}
+
+enum frame_type {
unknown = 0;
probe_request = 1;
beacon = 2;
@@ -20,13 +25,24 @@ enum packet_type {
message probe {
sint32 rssi = 1;
fixed64 src = 2;
- fixed64 dst = 3;
+}
+
+message frame {
+ frame_type type = 3;
+ probe probe = 20;
+}
+
+enum letter_type {
+ unknown_lt = 0;
+ listener_station_info_lt = 1;
+ frame_lt = 2;
}
message envelope {
sfixed64 time_s = 1;
sfixed64 time_us = 2;
- packet_type type = 3;
- probe probe = 20;
+ letter_type type = 3;
+ listener_station_info listener_station_info = 20;
+ frame frame = 21;
}