Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
antoniovazquezblanco committed Oct 14, 2024
0 parents commit 8467e0e
Show file tree
Hide file tree
Showing 4 changed files with 363 additions and 0 deletions.
73 changes: 73 additions & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
name: Build
on: [push, pull_request, workflow_dispatch]

jobs:
build:
strategy:
matrix:
sys:
- { os: windows, shell: 'msys2 {0}' }
- { os: ubuntu, shell: bash }
- { os: macos, shell: bash }
wireshark:
- v4.4.0

runs-on: ${{ matrix.sys.os }}-latest

defaults:
run:
shell: ${{ matrix.sys.shell }}

steps:
- name: Checkout Wireshark
uses: actions/checkout@v4
with:
repository: wireshark/wireshark
ref: ${{ matrix.wireshark }}
path: wireshark
fetch-depth: 0

- name: Checkout CatSniffer Plugin
uses: actions/checkout@v4
with:
path: wireshark/plugins/epan/catsniffer
fetch-depth: 0

- name: Install dependencies (Ubuntu)
if: matrix.sys.os == 'ubuntu'
run: sudo wireshark/tools/debian-setup.sh --install-all python3-pip -y

- name: Install dependencies (Mac OS)
if: matrix.sys.os == 'macos'
run: wireshark/tools/macos-setup-brew.sh --install-optional --install-doc-deps --install-dmg-deps --install-test-deps
env:
HOMEBREW_NO_AUTO_UPDATE: 1

- name: Install MSYS2 (Windows)
if: matrix.sys.os == 'windows'
uses: msys2/setup-msys2@v2
with:
msystem: UCRT64
update: true
install: base-devel

- name: Install dependencies (Windows)
if: matrix.sys.os == 'windows'
run: wireshark/tools/msys2-setup.sh --install-all --noconfirm

- name: Configure
run: cmake -B build -S wireshark -G Ninja -DCUSTOM_PLUGIN_SRC_DIR=plugins/epan/catsniffer -DCMAKE_INSTALL_PREFIX=/

- name: Build
run: cmake --build build --target catsniffer

- name: Install
env:
DESTDIR: ${{ github.workspace }}/dist
run: cmake --build build --target plugins/epan/catsniffer/install

- name: Upload artifacts
uses: actions/upload-artifact@v4
with:
name: CatSniffer_Wireshark${{ matrix.wireshark }}_${{ matrix.sys.os }}
path: dist/
47 changes: 47 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
# CMakeLists.txt
#
# SPDX-FileCopyrightText: © 2024 Antonio Vázquez Blanco <[email protected]>
# SPDX-License-Identifier: GPL-2.0-or-later

include(WiresharkPlugin)

# Plugin name and version info (major minor micro extra)
set_module_info(catsniffer 0 0 1 0)

set(DISSECTOR_SRC
catsniffer.c
)

set(PLUGIN_FILES
plugin.c
${DISSECTOR_SRC}
)

set_source_files_properties(
${PLUGIN_FILES}
PROPERTIES
COMPILE_FLAGS "${WERROR_COMMON_FLAGS}"
)

register_plugin_files(plugin.c
plugin
${DISSECTOR_SRC}
)

add_wireshark_plugin_library(catsniffer epan)

target_link_libraries(catsniffer epan)

install_plugin(catsniffer epan)

file(GLOB DISSECTOR_HEADERS RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}" "*.h")
CHECKAPI(
NAME
catsniffer
SWITCHES
--group dissectors-prohibited
--group dissectors-restricted
SOURCES
${DISSECTOR_SRC}
${DISSECTOR_HEADERS}
)
35 changes: 35 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# CatSniffer Wireshark Plugin

This is a native version of a Wireshark plugin to inspect CatSniffer traffic.

## Building

Theoretically, there is a way to build Wireshark plugins out of tree.
Unfortunatelly, there are some outstanding bugs in the way of correctly achieve this feat.
See https://gitlab.com/wireshark/wireshark/-/issues/19976 and https://gitlab.com/wireshark/wireshark/-/issues/1199.
This means there is no good way of building this plugin out of Wireshark source code tree.
The good news is that the plugin can be built inside Wireshark source code and exported as a library to be distributed.

To compile this plugin first checkout Wireshark source code to your preferred wireshark version:
```bash
git clone https://gitlab.com/wireshark/wireshark.git
cd wireshark
git checkout v4.4.0
```

Then, you need to clone this repository onto the epan plugins folder inside wireshark:
```bash
cd plugins/epan/
git clone https://github.com/ElectronicCats/CatSniffer-Wireshark.git catsniffer
cd ../../
```

In Wireshark main directory, the project must be configured indicating there is an extra plugin.
```bash
cmake -B build -S . -DCUSTOM_PLUGIN_SRC_DIR=plugins/epan/catsniffer
```

You may now build the plugin target alone witout having to compile the full Wireshark source code:
```bash
cmake --build build --target catsniffer
```
208 changes: 208 additions & 0 deletions catsniffer.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,208 @@
/* catsniffer_rpi.c
*
* SPDX-FileCopyrightText: © 2024 Antonio Vázquez Blanco <[email protected]>
* SPDX-License-Identifier: GPL-2.0-or-later
*
* This file registers and handles CatSniffer Radio packets following the format shown below.
*
* | Version | Length | Interface Type | Interface ID | Protocol | PHY | Frequency | Channel | RSSI | Status | Payload |
* |---------|--------|----------------|--------------|----------|-----|-----------|---------|------|--------|----------|
* | 1B | 2B | 1B | 2B | 1B | 1B | 4B | 2B | 1B | 1B | Variable |
*
* If the received packet is BLE, there is a secondary header with the format below.
*
* | Connection Event Counter | Info | Payload |
* |--------------------------|------|-----------------|
* | 2B | 1B | Variable Length |
*
*/

#include <wireshark.h>
#include <epan/packet.h>
#include <epan/unit_strings.h>
#include <wiretap/wtap.h>

#define TI_RPI_MIN_LENGTH 17

// Dissector handles
static dissector_handle_t handle_catsniffer_rpi;
static dissector_handle_t handle_btle;
static dissector_handle_t handle_wpan;

// Protocol handles
static int proto_catsniffer_rpi;
static int proto_catsniffer_blepi;

// Header field handles
static int hf_catsniffer_rpi_version;
static int hf_catsniffer_rpi_length;
static int hf_catsniffer_rpi_interface_type;
static int hf_catsniffer_rpi_interface_id;
static int hf_catsniffer_rpi_protocol;
static int hf_catsniffer_rpi_phy;
static int hf_catsniffer_rpi_freq;
static int hf_catsniffer_rpi_channel;
static int hf_catsniffer_rpi_rssi;
static int hf_catsniffer_rpi_fcs;
static int hf_catsniffer_blepi_conn_event;

// Subtree pointers
static int ett_rpi;
static int ett_blepi;

// Value tables
static const value_string table_interface_type[] = {
{0, "COM"},
{1, "CEBAL"},
{0, NULL}};

static const value_string table_protocol[] = {
{0, "Generic"},
{1, "802.15.4g"},
{2, "802.15.4"},
{3, "BLE"},
{4, "WBMS"},
{0, NULL}};

static const value_string table_phy[] = {
{0, "Unused"},
{3, "O-QPSK"},
{5, "BLE 1 Mbps"},
{0, NULL}};

static const unit_name_string table_units_khz = {"kHz", NULL};

static const true_false_string table_fcs = {"Ok", "Bad FCS"};

static int dissect_catsniffer_blepi(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
{
int offset = 0;
(void)data;
if (tvb_reported_length(tvb) == 0)
return 0;
col_set_str(pinfo->cinfo, COL_PROTOCOL, "Catsniffer BLE");
proto_item *ti = proto_tree_add_item(tree, proto_catsniffer_blepi, tvb, 0, -1, ENC_NA);
proto_tree *ti_blepi = proto_item_add_subtree(ti, ett_blepi);
// Connection Event
proto_tree_add_item(ti_blepi, hf_catsniffer_blepi_conn_event, tvb, offset, 2, ENC_LITTLE_ENDIAN);
offset += 2;
proto_item_set_len(ti_blepi, offset);
return offset;
}

static dissector_handle_t get_protocol_dissector_handle(int protocol)
{
switch (protocol)
{
case 2:
// 802.15.4
return handle_wpan;
case 3:
// BLE
return handle_btle;
default:
return NULL;
}
}

static int dissect_catsniffer_rpi(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
{
int offset = 0;
int length;
int protocol;

if (tvb_captured_length(tvb) < TI_RPI_MIN_LENGTH)
return 0;

col_set_str(pinfo->cinfo, COL_PROTOCOL, "CatSniffer Radio");

proto_item *ti = proto_tree_add_item(tree, proto_catsniffer_rpi, tvb, 0, -1, ENC_NA);
proto_tree *ti_rpi = proto_item_add_subtree(ti, ett_rpi);
// Version
proto_tree_add_item(ti_rpi, hf_catsniffer_rpi_version, tvb, offset, 1, ENC_NA);
offset += 1;
// Packet length
proto_tree_add_item_ret_uint(ti_rpi, hf_catsniffer_rpi_length, tvb, offset, 2, ENC_LITTLE_ENDIAN, &length);
offset += 2;
// Interface type
proto_tree_add_item(ti_rpi, hf_catsniffer_rpi_interface_type, tvb, offset, 1, ENC_NA);
offset += 1;
// Interface id
proto_tree_add_item(ti_rpi, hf_catsniffer_rpi_interface_id, tvb, offset, 2, ENC_LITTLE_ENDIAN);
offset += 2;
// Protocol
proto_tree_add_item_ret_uint(ti_rpi, hf_catsniffer_rpi_protocol, tvb, offset, 1, ENC_NA, &protocol);
offset += 1;
// PHY
proto_tree_add_item(ti_rpi, hf_catsniffer_rpi_phy, tvb, offset, 1, ENC_NA);
offset += 1;
// Freq
proto_tree_add_item(ti_rpi, hf_catsniffer_rpi_freq, tvb, offset, 4, ENC_LITTLE_ENDIAN);
offset += 4;
// Channel
proto_tree_add_item(ti_rpi, hf_catsniffer_rpi_channel, tvb, offset, 2, ENC_LITTLE_ENDIAN);
offset += 2;
// RSSI
proto_tree_add_item(ti_rpi, hf_catsniffer_rpi_rssi, tvb, offset, 1, ENC_NA);
offset += 1;
// Status
proto_tree_add_item(ti_rpi, hf_catsniffer_rpi_fcs, tvb, offset, 1, ENC_NA);
offset += 1;
proto_item_set_len(ti_rpi, offset);
// Optional BLE header
if (protocol == 3)
{
tvbuff_t *tvb_blepi = tvb_new_subset_remaining(tvb, offset);
offset += dissect_catsniffer_blepi(tvb_blepi, pinfo, tree, data);
}
// Payload
int payload_offset = (protocol == 3) ? 0 : 4;
tvbuff_t *tvb_payload = tvb_new_subset_remaining(tvb, offset + payload_offset);
dissector_handle_t payload_dissector = get_protocol_dissector_handle(protocol);
offset += call_dissector_with_data(payload_dissector, tvb_payload, pinfo, tree, data);
// All done!
return offset;
}

void proto_register_catsniffer_rpi(void)
{
// Setup a list of header fields
static hf_register_info hf[] = {
{&hf_catsniffer_rpi_version, {"Version", "catsniffer.version", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL}},
{&hf_catsniffer_rpi_length, {"Packet Length", "catsniffer.length", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL}},
{&hf_catsniffer_rpi_interface_type, {"Interface Type", "catsniffer.interface_type", FT_UINT8, BASE_DEC, VALS(table_interface_type), 0x0, NULL, HFILL}},
{&hf_catsniffer_rpi_interface_id, {"Interface ID", "catsniffer.interface_id", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL}},
{&hf_catsniffer_rpi_protocol, {"Protocol", "catsniffer.protocol", FT_UINT8, BASE_DEC, VALS(table_protocol), 0x0, NULL, HFILL}},
{&hf_catsniffer_rpi_phy, {"PHY", "catsniffer.phy", FT_UINT8, BASE_DEC, VALS(table_phy), 0x0, NULL, HFILL}},
{&hf_catsniffer_rpi_freq, {"Frequency", "catsniffer.freq", FT_UINT32, BASE_DEC | BASE_UNIT_STRING, UNS(&table_units_khz), 0x0, NULL, HFILL}},
{&hf_catsniffer_rpi_channel, {"Channel", "catsniffer.channel", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL}},
{&hf_catsniffer_rpi_rssi, {"RSSI", "catsniffer.rssi", FT_INT8, BASE_DEC, NULL, 0x0, NULL, HFILL}},
{&hf_catsniffer_rpi_fcs, {"Frame Check Status", "catsniffer.fcs", FT_BOOLEAN, 8, TFS(&table_fcs), 0x80, NULL, HFILL}},
{&hf_catsniffer_blepi_conn_event, {"Connection Event", "catsniffer.conn_event", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL}},
};

// Protocol subtree arrays
static int *ett[] = {
&ett_rpi,
&ett_blepi};

// Register protocols
proto_catsniffer_rpi = proto_register_protocol("CatSniffer Radio Packet Info", "CatSniffer RPI", "catsniffer_rpi");
proto_catsniffer_blepi = proto_register_protocol("CatSniffer BLE Packet Info", "CatSniffer BLEPI", "catsniffer_blepi");

// Register dissectors
handle_catsniffer_rpi = register_dissector("catsniffer_rpi", dissect_catsniffer_rpi, proto_catsniffer_rpi);
handle_btle = find_dissector("btle");
handle_wpan = find_dissector("wpan");

// Register header fields
proto_register_field_array(proto_catsniffer_rpi, hf, array_length(hf));

// Register subtrees
proto_register_subtree_array(ett, array_length(ett));
}

void proto_reg_handoff_catsniffer_rpi(void)
{
dissector_add_uint("wtap_encap", WTAP_ENCAP_USER0, handle_catsniffer_rpi);
}

0 comments on commit 8467e0e

Please sign in to comment.