Skip to content
Browse files

Netlink driver and radiotap data reading added.

  • Loading branch information...
1 parent a4cb2c9 commit 2eb817875657e799450f9ec2ea20c825a1f8230e @sh0 committed Sep 14, 2011
Showing with 592 additions and 21 deletions.
  1. +46 −9 src/ao_context.cpp
  2. +1 −0 src/ao_context.h
  3. +3 −4 src/ao_main.cpp
  4. +345 −6 src/drv_nl.cpp
  5. +10 −2 src/drv_nl.h
  6. +151 −0 src/pck_radiotap.cpp
  7. +36 −0 src/pck_radiotap.h
View
55 src/ao_context.cpp
@@ -73,8 +73,10 @@ bool c_context::init(
m_rx_type = DRIVER_PCAP;
if (!g_strcmp0(conf_mode_rx, "file")) {
m_rx_mode = PCAP_MODE_FILE;
+ g_message("[sys] rx enabled: driver=pcap, mode=file, file=%s", conf_dev_rx);
} else if (!g_strcmp0(conf_mode_rx, "dev")) {
m_rx_mode = PCAP_MODE_DEV;
+ g_message("[sys] rx enabled: driver=pcap, mode=dev, device=%s", conf_dev_rx);
} else {
g_critical("[sys] driver pcap does not support rx mode %s, please use either \"file\" or \"dev\"!", conf_mode_rx);
goto err_drv_find;
@@ -86,7 +88,9 @@ bool c_context::init(
} else if (!g_strcmp0(conf_drv_rx, "lorcon")) {
#ifdef LORCON_FOUND
m_rx_type = DRIVER_LORCON;
- if (g_strcmp0(conf_mode_rx, "dev")) {
+ if (!g_strcmp0(conf_mode_rx, "dev")) {
+ g_message("[sys] rx enabled: driver=lorcon, mode=dev, device=%s", conf_dev_rx);
+ } else {
g_critical("[sys] driver lorcon does not support rx mode %s, please use \"dev\"!", conf_mode_rx);
goto err_drv_find;
}
@@ -97,7 +101,9 @@ bool c_context::init(
} else if (!g_strcmp0(conf_drv_rx, "netlink")) {
#ifdef NETLINK_FOUND
m_rx_type = DRIVER_NETLINK;
- if (g_strcmp0(conf_mode_rx, "dev")) {
+ if (!g_strcmp0(conf_mode_rx, "dev")) {
+ g_message("[sys] rx enabled: driver=netlink, mode=dev, device=%s", conf_dev_rx);
+ } else {
g_critical("[sys] driver netlink does not support rx mode %s, please use \"dev\"!", conf_mode_rx);
goto err_drv_find;
}
@@ -113,6 +119,7 @@ bool c_context::init(
m_tx_type = DRIVER_PCAP;
if (!g_strcmp0(conf_mode_tx, "file")) {
m_tx_mode = PCAP_MODE_FILE;
+ g_message("[sys] tx enabled: driver=pcap, mode=file, file=%s", conf_dev_tx);
} else {
g_critical("[sys] driver pcap does not support tx mode %s, please use \"file\"!", conf_mode_tx);
goto err_drv_find;
@@ -124,7 +131,9 @@ bool c_context::init(
} else if (!g_strcmp0(conf_drv_tx, "lorcon")) {
#ifdef LORCON_FOUND
m_tx_type = DRIVER_LORCON;
- if (g_strcmp0(conf_mode_tx, "dev")) {
+ if (!g_strcmp0(conf_mode_tx, "dev")) {
+ g_message("[sys] tx enabled: driver=lorcon, mode=dev, device=%s", conf_dev_tx);
+ } else {
g_critical("[sys] driver lorcon does not support tx mode %s, please use \"dev\"!", conf_mode_tx);
goto err_drv_find;
}
@@ -135,7 +144,9 @@ bool c_context::init(
} else if (!g_strcmp0(conf_drv_tx, "netlink")) {
#ifdef NETLINK_FOUND
m_tx_type = DRIVER_NETLINK;
- if (g_strcmp0(conf_mode_tx, "dev")) {
+ if (!g_strcmp0(conf_mode_tx, "dev")) {
+ g_message("[sys] tx enabled: driver=netlink, mode=dev, device=%s", conf_dev_tx);
+ } else {
g_critical("[sys] driver netlink does not support tx mode %s, please use \"dev\"!", conf_mode_tx);
goto err_drv_find;
}
@@ -198,7 +209,28 @@ bool c_context::init(
// Netlink
#ifdef NETLINK_FOUND
-
+ if (m_rx_type == DRIVER_NETLINK || m_tx_type == DRIVER_NETLINK) {
+ if (m_rx_type == DRIVER_NETLINK && m_tx_type == DRIVER_NETLINK && !g_strcmp0(conf_dev_rx, conf_dev_tx)) {
+ m_tx_drv = m_rx_drv = new c_drv_netlink(conf_dev_rx);
+ if (!m_rx_drv->init())
+ goto err_drv_init;
+ } else if (m_rx_type == DRIVER_NETLINK && m_tx_type == DRIVER_NETLINK) {
+ m_rx_drv = new c_drv_netlink(conf_dev_rx);
+ if (!m_rx_drv->init())
+ goto err_drv_init;
+ m_tx_drv = new c_drv_netlink(conf_dev_tx);
+ if (!m_tx_drv->init())
+ goto err_drv_init;
+ } else if (m_rx_type == DRIVER_NETLINK) {
+ m_rx_drv = new c_drv_netlink(conf_dev_rx);
+ if (!m_rx_drv->init())
+ goto err_drv_init;
+ } else if (m_tx_type == DRIVER_NETLINK) {
+ m_tx_drv = new c_drv_netlink(conf_dev_tx);
+ if (!m_tx_drv->init())
+ goto err_drv_init;
+ }
+ }
#endif
/*
@@ -212,6 +244,7 @@ bool c_context::init(
*/
// Mainloop
+ m_kill = false;
m_mainloop = g_main_loop_new(NULL, FALSE);
g_idle_add(c_context::f_loop_idle, this);
@@ -247,6 +280,9 @@ void c_context::end()
// Check
g_assert(m_active);
+ // Mainloop
+ g_main_loop_unref(m_mainloop);
+
// Driver
if (m_rx_drv && m_tx_drv && m_rx_drv == m_tx_drv) {
delete m_rx_drv;
@@ -282,8 +318,7 @@ void c_context::kill()
g_assert(m_active);
// Kill
- if (g_main_loop_is_running(m_mainloop))
- g_main_loop_quit(m_mainloop);
+ m_kill = true;
}
// Mainloop
@@ -296,17 +331,19 @@ gboolean c_context::f_loop_idle(gpointer data)
if (ctx->m_rx_drv) {
st_pck_drv* pck_drv = ctx->m_rx_drv->pck_rx();
if (pck_drv) {
- //g_message("[pck] <========================================================================>");
c_layer_hw* pck_hw = new c_layer_hw();
if (pck_hw->init_unpack(pck_drv)) {
- //pck_hw->str_dump();
ctx->m_pck_hw = g_list_append(ctx->m_pck_hw, pck_hw);
} else {
delete pck_hw;
}
}
}
+ // Kill
+ if (ctx->m_kill)
+ g_main_loop_quit(ctx->m_mainloop);
+
// Return
return TRUE;
}
View
1 src/ao_context.h
@@ -86,6 +86,7 @@ class c_context {
*/
// Mainloop
+ bool m_kill;
GMainLoop* m_mainloop;
static gboolean f_loop_idle(gpointer data);
};
View
7 src/ao_main.cpp
@@ -30,13 +30,11 @@
// Instance
static c_context* ao_inst = NULL;
-// Command-line
-
-
// Signal
static void ao_signal(int sig)
{
if (sig == SIGINT) {
+ g_print("\n");
if (ao_inst)
ao_inst->kill();
} else if (sig == SIGWINCH) {
@@ -51,7 +49,7 @@ int main(int argc, char* argv[])
const gchar* cmd_drv_rx = "pcap";
const gchar* cmd_mode_rx = "file";
const gchar* cmd_dev_rx = "test-rx.pcap";
- const gchar* cmd_drv_tx = "pcap";
+ const gchar* cmd_drv_tx = "none";
const gchar* cmd_mode_tx = "file";
const gchar* cmd_dev_tx = "test-tx.pcap";
GOptionEntry cmd_entry_main[] = {
@@ -151,6 +149,7 @@ int main(int argc, char* argv[])
if (ao_inst->init(cmd_drv_rx, cmd_mode_rx, cmd_dev_rx, cmd_drv_tx, cmd_mode_tx, cmd_dev_tx)) {
ao_inst->run();
}
+ delete ao_inst;
// Return
return 0;
View
351 src/drv_nl.cpp
@@ -29,13 +29,18 @@
/*
#include <sys/types.h>
#include <asm/types.h>
-#include <netlink/genl/genl.h>
#include <netlink/genl/family.h>
-#include <netlink/genl/ctrl.h>
#include <netlink/msg.h>
#include <netlink/attr.h>
*/
+
+#include <sys/socket.h>
+#include <netpacket/packet.h>
+#include <net/ethernet.h>
+
#include <netlink/netlink.h>
+#include <netlink/genl/genl.h>
+#include <netlink/genl/ctrl.h>
// Constructor and destructor
c_drv_netlink::c_drv_netlink(const gchar* dev)
@@ -61,12 +66,165 @@ c_drv_netlink::~c_drv_netlink()
// Init and end
bool c_drv_netlink::init()
{
- return false;
+ // Check
+ g_assert(!m_active);
+
+ // Variables
+ struct ifreq if_req;
+ struct sockaddr_ll sa_ll;
+ struct packet_mreq mr;
+ int optval;
+ socklen_t optlen;
+
+ // Interface name
+ m_nl_if = m_info_dev;
+
+ // Queues
+ m_queue_rx = g_async_queue_new_full(c_drv_netlink::f_delete_pck);
+ m_queue_tx = g_async_queue_new_full(c_drv_netlink::f_delete_pck);
+
+ // Netlink
+ if (f_nl_connect() != true) {
+ goto err_nl_connect;
+ }
+
+ // Socket
+ m_nl_fd = socket(PF_PACKET, SOCK_RAW, g_htons(ETH_P_ALL));
+ if (m_nl_fd < 0) {
+ g_critical("[drv] failed to create injection socket! error=%s", strerror(errno));
+ goto err_nl_fd;
+ }
+
+ // Interface index
+ memset(&if_req, 0, sizeof(if_req));
+ g_strlcpy(if_req.ifr_name, m_nl_if, IFNAMSIZ);
+ if (ioctl(m_nl_fd, SIOCGIFINDEX, &if_req) < 0) {
+ g_critical("[drv] failed to get interface index! error=%s", strerror(errno));
+ goto err_nl_index;
+ }
+
+ // Bind
+ memset(&sa_ll, 0, sizeof(sa_ll));
+ sa_ll.sll_family = AF_PACKET;
+ sa_ll.sll_protocol = g_htons(ETH_P_ALL);
+ sa_ll.sll_ifindex = if_req.ifr_ifindex;
+ if (bind(m_nl_fd, (struct sockaddr*) &sa_ll, sizeof(sa_ll)) != 0) {
+ g_critical("[drv] failed to bind injection socket! error=%s", strerror(errno));
+ goto err_nl_bind;
+ }
+
+ // Check if device is up
+ optlen = sizeof(optval);
+ optval = 0;
+ if (getsockopt(m_nl_fd, SOL_SOCKET, SO_ERROR, &optval, &optlen) == -1) {
+ g_critical("[drv] failed to get device error status! error=%s", strerror(errno));
+ goto err_nl_opt;
+ }
+ if (optval == ENETDOWN) {
+ g_critical("[drv] device seems to be down!");
+ goto err_nl_opt;
+ } else if (optval > 0) {
+ g_critical("[drv] unknown device error! error=%s", strerror(errno));
+ goto err_nl_opt;
+ }
+
+ // Priority option
+ optlen = sizeof(optval);
+ optval = 20;
+ if (setsockopt(m_nl_fd, SOL_SOCKET, SO_PRIORITY, &optval, optlen) == -1) {
+ g_critical("[drv] failed to set priority on socket! error=%s", strerror(errno));
+ goto err_nl_opt;
+ }
+
+ // Promisc option
+ memset(&mr, 0, sizeof(mr));
+ mr.mr_ifindex = if_req.ifr_ifindex;
+ mr.mr_type = PACKET_MR_PROMISC;
+ if (setsockopt(m_nl_fd, SOL_PACKET, PACKET_ADD_MEMBERSHIP, &mr, sizeof(mr)) == -1) {
+ g_critical("[drv] failed to set interface in promisc mode! error=%s", strerror(errno));
+ goto err_nl_opt;
+ }
+
+ // Buffer
+ m_nl_recv.iov_len = 64000;
+ m_nl_recv.iov_base = g_malloc(m_nl_recv.iov_len);
+
+ // Thread
+ {
+ GError* err = NULL;
+ m_thr_run = true;
+ m_thr_dead = false;
+ m_thr_mutex = g_mutex_new();
+ m_thr_thread = g_thread_create(f_loop, this, TRUE, &err);
+ if (!m_thr_thread) {
+ if (err) {
+ g_critical("[drv] failed to create thread! error=%s", err->message);
+ g_clear_error(&err);
+ } else {
+ g_critical("[drv] failed to create thread! error=unknown");
+ }
+ goto err_thread;
+ }
+ }
+
+ // Return
+ m_active = true;
+ return true;
+
+ // Error
+ err_thread:
+ // Thread
+ g_mutex_free(m_thr_mutex);
+
+ // Buffer
+ g_free(m_nl_recv.iov_base);
+
+ err_nl_opt:
+ err_nl_bind:
+ err_nl_index:
+ // Socket
+ close(m_nl_fd);
+
+ err_nl_fd:
+ // Disconnect
+ f_nl_disconnect();
+
+ err_nl_connect:
+ // Queues
+ g_async_queue_unref(m_queue_rx);
+ g_async_queue_unref(m_queue_tx);
+
+ // Return
+ return false;
}
void c_drv_netlink::end()
{
-
+ // Check
+ g_assert(m_active);
+
+ // Thread
+ g_mutex_lock(m_thr_mutex);
+ m_thr_run = false;
+ g_mutex_unlock(m_thr_mutex);
+ g_thread_join(m_thr_thread);
+ g_mutex_free(m_thr_mutex);
+
+ // Buffer
+ g_free(m_nl_recv.iov_base);
+
+ // Socket
+ close(m_nl_fd);
+
+ // Disconnect
+ f_nl_disconnect();
+
+ // Queues
+ g_async_queue_unref(m_queue_rx);
+ g_async_queue_unref(m_queue_tx);
+
+ // Deactive
+ m_active = false;
}
// Output
@@ -78,18 +236,199 @@ void c_drv_netlink::help()
const gchar* c_drv_netlink::name()
{
- return NULL;
+ // Check
+ g_assert(m_active);
+
+ // Return
+ return m_nl_if;
}
// Packets
st_pck_drv* c_drv_netlink::pck_rx()
{
- return NULL;
+ // Check
+ g_assert(m_active);
+
+ // Pop data
+ return (st_pck_drv*) g_async_queue_try_pop(m_queue_rx);
}
void c_drv_netlink::pck_tx(st_pck_drv* data)
{
+ // Check
+ g_assert(m_active);
+
+ // Push data
+ g_async_queue_push(m_queue_tx, data);
+}
+
+// Loop functions
+gpointer c_drv_netlink::f_loop(gpointer user)
+{
+ // Instance
+ c_drv_netlink* ctx = (c_drv_netlink*) user;
+
+ // Packet loop
+ while (true) {
+ // Exit check
+ g_mutex_lock(ctx->m_thr_mutex);
+ if (!ctx->m_thr_run) {
+ ctx->m_thr_dead = true;
+ g_mutex_unlock(ctx->m_thr_mutex);
+ return NULL;
+ }
+ g_mutex_unlock(ctx->m_thr_mutex);
+
+ // Packet loop
+ bool ok = true;
+ while (ok) {
+ // Ok
+ ok = false;
+
+ // Receive packet
+ //guint8 rx_ctmp[128];
+ struct msghdr rx_msg;
+ rx_msg.msg_name = NULL;
+ rx_msg.msg_namelen = 0;
+ rx_msg.msg_iov = &ctx->m_nl_recv;
+ rx_msg.msg_iovlen = 1;
+ rx_msg.msg_control = NULL; //&rx_ctmp;
+ rx_msg.msg_controllen = 0; //sizeof(rx_ctmp);
+ rx_msg.msg_flags = 0;
+ ssize_t rx_size = recvmsg(ctx->m_nl_fd, &rx_msg, MSG_DONTWAIT);
+ if (rx_size > 0) {
+ // Layer
+ /*
+ struct cmsghdr* rx_cmsg = CMSG_FIRSTHDR(&rx_msg);
+ if (rx_cmsg) {
+ g_message("[drv] got packet! level=%d", rx_cmsg->cmsg_level);
+ }
+ */
+
+ // Packet
+ st_pck_drv* pck_drv = g_new(st_pck_drv, 1);
+ pck_drv->data = g_byte_array_new();
+ pck_drv->type = LAYER_RADIOTAP_PCK;
+ pck_drv->driver = ctx;
+
+ // Data
+ g_byte_array_append(pck_drv->data, (guint8*) rx_msg.msg_iov[0].iov_base, rx_size);
+
+ // Queue
+ g_async_queue_push(ctx->m_queue_rx, pck_drv);
+
+ // Ok
+ ok = true;
+ } else if (errno != EAGAIN) {
+ // Error
+ g_critical("[drv] error reading packet! error=%s", strerror(errno));
+
+ // Exit loop
+ g_mutex_lock(ctx->m_thr_mutex);
+ ctx->m_thr_dead = true;
+ g_mutex_unlock(ctx->m_thr_mutex);
+ return NULL;
+ }
+
+ // Transmit packet
+ st_pck_drv* pck_drv = (st_pck_drv*) g_async_queue_try_pop(ctx->m_queue_tx);
+ if (pck_drv) {
+ // Message
+ struct iovec tx_iov;
+ tx_iov.iov_base = pck_drv->data->data;
+ tx_iov.iov_len = pck_drv->data->len;
+ struct msghdr tx_msg;
+ tx_msg.msg_name = NULL;
+ tx_msg.msg_namelen = 0;
+ tx_msg.msg_iovlen = 1;
+ tx_msg.msg_iov = &tx_iov;
+ tx_msg.msg_control = NULL;
+ tx_msg.msg_controllen = 0;
+ tx_msg.msg_flags = 0;
+
+ // Send
+ ssize_t tx_size = sendmsg(ctx->m_nl_fd, &tx_msg, 0);
+ if (tx_size < 0) {
+ // Error
+ g_critical("[drv] error sending packet! error=%s", strerror(errno));
+
+ // Exit loop
+ g_mutex_lock(ctx->m_thr_mutex);
+ ctx->m_thr_dead = true;
+ g_mutex_unlock(ctx->m_thr_mutex);
+ return NULL;
+ }
+
+ // Delete
+ g_byte_array_unref(pck_drv->data);
+ g_free(pck_drv);
+
+ // Ok
+ ok = true;
+ }
+ }
+
+ }
+
+ // Return
+ return NULL;
+}
+
+void c_drv_netlink::f_delete_pck(gpointer data)
+{
+ // Free packet
+ st_pck_drv* pck = (st_pck_drv*) data;
+ g_byte_array_unref(pck->data);
+ g_free(pck);
+}
+
+// Netlink functions
+bool c_drv_netlink::f_nl_connect()
+{
+ // Netlink handle
+ if ((m_nl_handle = nl_handle_alloc()) == NULL) {
+ g_critical("[drv] failed to allocate nl_handle!");
+ goto err_handle;
+ }
+ if (genl_connect(m_nl_handle)) {
+ g_critical("[drv] failed to connect to generic netlink!");
+ goto err_connect;
+ }
+
+ m_nl_cache = genl_ctrl_alloc_cache(m_nl_handle);
+ if (m_nl_cache == NULL) {
+ g_critical("[drv] failed to allocate generic netlink cache!");
+ goto err_cache;
+ }
+
+ if ((m_nl_family = genl_ctrl_search_by_name(m_nl_cache, "nl80211")) == NULL) {
+ g_critical("[drv] failed to find nl80211 controls, kernel may be too old!");
+ goto err_family;
+ }
+
+ // Return
+ return true;
+
+ // Error
+ err_family:
+ // Cache
+ nl_cache_free(m_nl_cache);
+
+ err_cache:
+ err_connect:
+ // Handle
+ nl_handle_destroy(m_nl_handle);
+
+ err_handle:
+ // Return
+ return false;
+}
+
+void c_drv_netlink::f_nl_disconnect()
+{
+ // Netlink handle
+ nl_handle_destroy(m_nl_handle);
}
#endif
View
12 src/drv_nl.h
@@ -56,12 +56,16 @@ class c_drv_netlink : public c_drv {
gchar* m_info_dev;
// Netlink
-
+ gchar* m_nl_if;
+ gint m_nl_fd;
+ struct iovec m_nl_recv;
+ struct nl_handle* m_nl_handle;
+ struct nl_cache* m_nl_cache;
+ struct genl_family* m_nl_family;
// Thread
GThread* m_thr_thread;
GMutex* m_thr_mutex;
- GCond* m_thr_cond;
bool m_thr_run;
bool m_thr_dead;
@@ -72,6 +76,10 @@ class c_drv_netlink : public c_drv {
// Loop functions
static gpointer f_loop(gpointer user);
static void f_delete_pck(gpointer data);
+
+ // Netlink functions
+ bool f_nl_connect();
+ void f_nl_disconnect();
};
#endif // NETLINK_FOUND
View
151 src/pck_radiotap.cpp
@@ -62,6 +62,122 @@ bool c_layer_radiotap::init_unpack(GNode* node, GByteArray* data)
if (m_hdr.it_version != 0)
return false;
+ // Extended presence
+ m_ext_val[0] = m_hdr.it_present;
+ for (guint i=1; i<m_ext_num; i++) {
+ if (m_ext_val[i - 1] & (1 << 31)) {
+ if (optlen < (gint)sizeof(guint32))
+ return false;
+ m_ext_val[i] = *((guint32*)data_cur);
+ data_cur += sizeof(guint32);
+ optlen -= sizeof(guint32);
+ } else {
+ m_ext_val[i] = 0;
+ break;
+ }
+ }
+
+ // Options
+ m_flags_set = false;
+ m_rate_set = false;
+ m_chan_set = false;
+ m_fhss_set = false;
+ m_ant_noise_set = false;
+ m_ant_signal_db_set = false;
+ m_txflags_set = false;
+ for (guint i=0; i<m_ext_num; i++) {
+ // Scan bits
+ for (guint b=0; b<31; b++) {
+ // Check
+ if (!(m_ext_val[i] & (1 << b)))
+ continue;
+
+ // Select field
+ guint id = (i * 30) + b + 1;
+ switch (id) {
+ case 1:
+ // Flags
+ if (optlen < (gint)sizeof(m_flags_val))
+ goto opt_continue;
+ m_flags_set = true;
+ m_flags_val = *data_cur;
+ data_cur += sizeof(m_flags_val);
+ optlen -= sizeof(m_flags_val);
+ break;
+
+ case 2:
+ // Rate
+ if (optlen < (gint)sizeof(m_rate_val))
+ goto opt_continue;
+ m_rate_set = true;
+ m_rate_val = *data_cur;
+ data_cur += sizeof(m_rate_val);
+ optlen -= sizeof(m_rate_val);
+ break;
+
+ case 3:
+ // Channel
+ if (optlen < (gint)sizeof(m_chan_val))
+ goto opt_continue;
+ m_chan_set = true;
+ g_memmove(&m_chan_val, data_cur, sizeof(m_chan_val));
+ data_cur += sizeof(m_chan_val);
+ optlen -= sizeof(m_chan_val);
+ break;
+
+ case 4:
+ // FHSS
+ if (optlen < (gint)sizeof(m_fhss_val))
+ goto opt_continue;
+ m_fhss_set = true;
+ g_memmove(&m_fhss_val, data_cur, sizeof(m_fhss_val));
+ data_cur += sizeof(m_fhss_val);
+ optlen -= sizeof(m_fhss_val);
+ break;
+
+ case 6:
+ // Antenna noise
+ if (optlen < (gint)sizeof(m_ant_noise_val))
+ goto opt_continue;
+ m_ant_noise_set = true;
+ m_ant_noise_val = (gint8) *data_cur;
+ data_cur += sizeof(m_ant_noise_val);
+ optlen -= sizeof(m_ant_noise_val);
+ break;
+
+ case 12:
+ // Antenna noise
+ if (optlen < (gint)sizeof(m_ant_signal_db_val))
+ goto opt_continue;
+ m_ant_signal_db_set = true;
+ m_ant_signal_db_val = *data_cur;
+ data_cur += sizeof(m_ant_signal_db_val);
+ optlen -= sizeof(m_ant_signal_db_val);
+ break;
+
+ case 15:
+ // TX flags
+ if (optlen < (gint)sizeof(m_txflags_val))
+ goto opt_continue;
+ m_txflags_set = true;
+ g_memmove(&m_txflags_val, data_cur, sizeof(m_txflags_val));
+ data_cur += sizeof(m_txflags_val);
+ optlen -= sizeof(m_txflags_val);
+ break;
+
+ default:
+ // Unknown op
+ g_message("[pck] unhandled=%u, optlen=%d", id, optlen);
+ goto opt_continue;
+ }
+ }
+
+ // End of flag variables
+ if (!(m_ext_val[i] & (1 << 31)))
+ break;
+ }
+ opt_continue:
+
// Skip options
data_cur += optlen;
@@ -102,6 +218,41 @@ void c_layer_radiotap::str_dump()
{
// Check
g_assert(m_active);
+
+ // Message
+ g_message(
+ "[pck] layer-radiotap: version=%u, len=%u, flags=%08x",
+ m_hdr.it_version, m_hdr.it_len, m_hdr.it_present
+ );
+ if (m_rate_set)
+ g_message("[pck] * rate=[%.2f Mbps]", (gdouble)m_rate_val * 0.5);
+ if (m_chan_set)
+ g_message(
+ "[pck] * freq=[%.3f GHz], turbo=%s, cck=%s, ofdm=%s, 2ghz=%s, 5ghz=%s, passive=%s",
+ (gdouble)m_chan_val.freq / 1000.0,
+ m_chan_val.flags & 0x0010 ? "true" : "false",
+ m_chan_val.flags & 0x0020 ? "true" : "false",
+ m_chan_val.flags & 0x0040 ? "true" : "false",
+ m_chan_val.flags & 0x0080 ? "true" : "false",
+ m_chan_val.flags & 0x0100 ? "true" : "false",
+ m_chan_val.flags & 0x0200 ? "true" : "false"
+ );
+ if (m_fhss_set)
+ g_message("[pck] * hop_set=%u, hop_pattern=%u", m_fhss_val.hop_set, m_fhss_val.hop_pattern);
+ if (m_ant_noise_set)
+ g_message("[pck] * ant_noise=[%d dBm]", m_ant_noise_val);
+ if (m_ant_signal_db_set)
+ g_message("[pck] * ant_signal=[%u dB]", m_ant_signal_db_val);
+ if (m_txflags_set) {
+ g_message(
+ "[pck] * retry_fail=%s, cts_to_self=%s, rts_cts_used=%s, no_ack_expected=%s, has_seqno=%s",
+ m_txflags_val & 0x0001 ? "true" : "false",
+ m_txflags_val & 0x0002 ? "true" : "false",
+ m_txflags_val & 0x0004 ? "true" : "false",
+ m_txflags_val & 0x0008 ? "true" : "false",
+ m_txflags_val & 0x0010 ? "true" : "false"
+ );
+ }
}
const gchar* c_layer_radiotap::str_name()
View
36 src/pck_radiotap.h
@@ -58,6 +58,42 @@ class c_layer_radiotap : public c_layer {
private:
// Headers
struct radiotap_header m_hdr;
+ static const guint m_ext_num = 5;
+ guint32 m_ext_val[m_ext_num];
+
+ // Flags
+ bool m_flags_set;
+ guint8 m_flags_val;
+
+ // Rate
+ bool m_rate_set;
+ guint8 m_rate_val;
+
+ // Channel
+ bool m_chan_set;
+ struct {
+ guint16 freq;
+ guint16 flags;
+ } __attribute__((__packed__)) m_chan_val;
+
+ // FHSS
+ bool m_fhss_set;
+ struct {
+ guint8 hop_set;
+ guint8 hop_pattern;
+ } __attribute__((__packed__)) m_fhss_val;
+
+ // Antenna noise
+ bool m_ant_noise_set;
+ gint8 m_ant_noise_val;
+
+ // Antenna signal dB
+ bool m_ant_signal_db_set;
+ guint8 m_ant_signal_db_val;
+
+ // TX flags
+ bool m_txflags_set;
+ guint16 m_txflags_val;
// Endpoints
st_ep m_ep;

0 comments on commit 2eb8178

Please sign in to comment.
Something went wrong with that request. Please try again.