Merge remote-tracking branch 'gy/main' into improve-versionning

This commit is contained in:
GyulyVGC
2025-09-18 12:17:25 +02:00
14 changed files with 236 additions and 237 deletions

View File

@@ -3,6 +3,9 @@ # Changelog
All Sniffnet releases with the relative changes are documented in this file.
## [UNRELEASED]
- Fix AppImage error with `libpcap` dependency ([#971](https://github.com/GyulyVGC/sniffnet/pull/971))
## [1.4.1] - 2025-09-13
- Enhanced traffic filtering capabilities: Berkeley Packet Filter ([#937](https://github.com/GyulyVGC/sniffnet/pull/937) — fixes [#810](https://github.com/GyulyVGC/sniffnet/issues/810))
- Added support for `Linux SLL` link type, enabling to monitor the `any` interface on Linux ([#945](https://github.com/GyulyVGC/sniffnet/pull/945))
- Added _bits_ data representation ([#936](https://github.com/GyulyVGC/sniffnet/pull/936) — fixes [#506](https://github.com/GyulyVGC/sniffnet/issues/506))
@@ -20,6 +23,7 @@ ## [UNRELEASED]
- Romanian ([#890](https://github.com/GyulyVGC/sniffnet/pull/890))
- Traditional Chinese (Taiwan) ([#904](https://github.com/GyulyVGC/sniffnet/pull/904))
- Indonesian ([#909](https://github.com/GyulyVGC/sniffnet/pull/909))
- Fix live chart not being updated when packets aren't captured on Linux ([#957](https://github.com/GyulyVGC/sniffnet/pull/957) — fixes [#951](https://github.com/GyulyVGC/sniffnet/issues/951))
- Fix support for IPinfo's databases (the most recent version renamed the `country` field to `country_code`)
## [1.4.0] - 2025-06-27

398
Cargo.lock generated
View File

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
[package]
name = "sniffnet"
version = "1.4.0"
version = "1.4.1"
authors = ["Giuliano Bellini <gyulyvgc99@gmail.com>"]
edition = "2024"
description = "Application to comfortably monitor your network traffic"
@@ -39,7 +39,7 @@ strip = true
[dependencies]
pcap = "2.3.0"
etherparse = "0.19.0"
chrono = { version = "0.4.41", default-features = false, features = ["clock"] }
chrono = { version = "0.4.42", default-features = false, features = ["clock"] }
plotters = { version = "0.3.7", default-features = false, features = ["area_series", "line_series"] }
iced = { version = "0.13.1", features = ["tokio", "svg", "advanced", "lazy", "image"] }
plotters-iced = "0.11.0"
@@ -49,12 +49,12 @@ serde = { version = "1.0.219", default-features = false, features = ["derive"] }
rodio = { version = "0.21.1", default-features = false, features = ["mp3", "playback"] }
dns-lookup = "3.0.0"
toml = "0.9.5"
ctrlc = { version = "3.4.7", features = ["termination"] }
ctrlc = { version = "3.5.0", features = ["termination"] }
rfd = "0.15.4"
phf = "0.13.1"
phf_shared = "0.13.1"
splines = "5.0.0"
clap = { version = "4.5.46", features = ["derive"] }
clap = { version = "4.5.47", features = ["derive"] }
tokio = { version = "1.47.1", features = ["macros"] }
async-channel = "2.5.0"
semver = "1.0"

View File

@@ -12,7 +12,7 @@
Cross-platform. Intuitive. Reliable.
Translated in:<br>
🇨🇳 🇩🇪 🇫🇷 🇷🇺 🇵🇹 🇪🇦 🇮🇹 🇵🇱 [+&nbsp;14&nbsp;more&nbsp;languages](https://github.com/GyulyVGC/sniffnet/issues/60)
🇨🇳 🇩🇪 🇫🇷 🇷🇺 🇵🇹 🇪🇦 🇮🇹 🇵🇱 [+&nbsp;15&nbsp;more&nbsp;languages](https://github.com/GyulyVGC/sniffnet/issues/60)
</div>
<p>
@@ -81,6 +81,7 @@ ## Download
<picture><img alt="Linux" title="Linux" height="85px" src="https://raw.githubusercontent.com/GyulyVGC/sniffnet/main/resources/repository/badges/linux.svg"/></picture>
</td>
<td>
AppImage: <a href="https://github.com/GyulyVGC/sniffnet/releases/latest/download/Sniffnet_LinuxAppImage_amd64.AppImage">amd64</a> | <a href="https://github.com/GyulyVGC/sniffnet/releases/latest/download/Sniffnet_LinuxAppImage_arm64.AppImage">arm64</a> | <a href="https://github.com/GyulyVGC/sniffnet/releases/latest/download/Sniffnet_LinuxAppImage_i386.AppImage">i386</a> | <a href="https://github.com/GyulyVGC/sniffnet/releases/latest/download/Sniffnet_LinuxAppImage_armhf.AppImage">armhf</a> <br>
DEB: <a href="https://github.com/GyulyVGC/sniffnet/releases/latest/download/Sniffnet_LinuxDEB_amd64.deb">amd64</a> | <a href="https://github.com/GyulyVGC/sniffnet/releases/latest/download/Sniffnet_LinuxDEB_arm64.deb">arm64</a> | <a href="https://github.com/GyulyVGC/sniffnet/releases/latest/download/Sniffnet_LinuxDEB_i386.deb">i386</a> | <a href="https://github.com/GyulyVGC/sniffnet/releases/latest/download/Sniffnet_LinuxDEB_armhf.deb">armhf</a> <br>
RPM: <a href="https://github.com/GyulyVGC/sniffnet/releases/latest/download/Sniffnet_LinuxRPM_x86_64.rpm">x86_64</a> | <a href="https://github.com/GyulyVGC/sniffnet/releases/latest/download/Sniffnet_LinuxRPM_aarch64.rpm">aarch64</a>
</td>

View File

Binary file not shown.

View File

Binary file not shown.

View File

@@ -593,7 +593,6 @@ z

View File

Binary file not shown.

View File

Binary file not shown.

View File

@@ -1,9 +1,9 @@
app: Sniffnet
ingredients:
dist: bookworm
dist: buster
packages:
- libpcap0.8
sources:
- deb https://deb.debian.org/debian stable main
- deb https://archive.debian.org/debian buster main
debs:
- /target/REPLACE_TAG

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 157 KiB

After

Width:  |  Height:  |  Size: 205 KiB

View File

@@ -11,7 +11,7 @@
use crate::networking::types::address_port_pair::AddressPortPair;
use crate::networking::types::arp_type::ArpType;
use crate::networking::types::bogon::is_bogon;
use crate::networking::types::capture_context::{CaptureContext, CaptureSource};
use crate::networking::types::capture_context::{CaptureContext, CaptureSource, CaptureType};
use crate::networking::types::data_info::DataInfo;
use crate::networking::types::data_info_host::DataInfoHost;
use crate::networking::types::host::{Host, HostMessage};
@@ -26,7 +26,7 @@
use async_channel::Sender;
use dns_lookup::lookup_addr;
use etherparse::{EtherType, LaxPacketHeaders};
use pcap::{Address, Packet};
use pcap::{Address, Packet, PacketHeader};
use std::collections::HashMap;
use std::net::IpAddr;
use std::sync::{Arc, Mutex};
@@ -42,7 +42,7 @@ pub fn parse_packets(
tx: &Sender<BackendTrafficMessage>,
) {
let my_link_type = capture_context.my_link_type();
let (mut cap, mut savefile) = capture_context.consume();
let (cap, mut savefile) = capture_context.consume();
let mut info_traffic_msg = InfoTraffic::default();
let resolutions_state = Arc::new(Mutex::new(AddressesResolutionState::default()));
@@ -52,8 +52,16 @@ pub fn parse_packets(
// instant of the first parsed packet plus multiples of 1 second (only used in live captures)
let mut first_packet_ticks = None;
let (pcap_tx, pcap_rx) = std::sync::mpsc::sync_channel(10_000);
let _ = thread::Builder::new()
.name("thread_packet_stream".to_string())
.spawn(move || packet_stream(cap, &pcap_tx))
.log_err(location!());
loop {
let packet_res = cap.next_packet();
let (packet_res, cap_stats) = pcap_rx
.recv_timeout(Duration::from_millis(150))
.unwrap_or((Err(pcap::Error::TimeoutExpired), None));
if tx.is_closed() {
return;
@@ -93,7 +101,7 @@ pub fn parse_packets(
}
}
Ok(packet) => {
if let Some(headers) = get_sniffable_headers(&packet, my_link_type) {
if let Some(headers) = get_sniffable_headers(&packet.data, my_link_type) {
#[allow(clippy::useless_conversion)]
let secs = i64::from(packet.header.ts.tv_sec);
#[allow(clippy::useless_conversion)]
@@ -135,7 +143,10 @@ pub fn parse_packets(
// save this packet to PCAP file
if let Some(file) = savefile.as_mut() {
file.write(&packet);
file.write(&Packet {
header: &packet.header,
data: &packet.data,
});
}
// update the map
let (traffic_direction, service) = modify_or_insert_in_map(
@@ -267,7 +278,7 @@ pub fn parse_packets(
});
// update dropped packets number
if let Ok(stats) = cap.stats() {
if let Some(stats) = cap_stats {
info_traffic_msg.dropped_packets = stats.dropped;
}
}
@@ -276,10 +287,7 @@ pub fn parse_packets(
}
}
fn get_sniffable_headers<'a>(
packet: &'a Packet,
my_link_type: MyLinkType,
) -> Option<LaxPacketHeaders<'a>> {
fn get_sniffable_headers(packet: &[u8], my_link_type: MyLinkType) -> Option<LaxPacketHeaders<'_>> {
match my_link_type {
MyLinkType::Ethernet(_) | MyLinkType::Unsupported(_) | MyLinkType::NotYetAssigned => {
LaxPacketHeaders::from_ethernet(packet).ok()
@@ -474,3 +482,24 @@ fn maybe_send_tick_run_offline(
}
}
}
fn packet_stream(
mut cap: CaptureType,
tx: &std::sync::mpsc::SyncSender<(Result<PacketOwned, pcap::Error>, Option<pcap::Stat>)>,
) {
loop {
let packet_res = cap.next_packet();
let packet_owned = packet_res.map(|p| PacketOwned {
header: *p.header,
data: p.data.into(),
});
if tx.send((packet_owned, cap.stats().ok())).is_err() {
return;
}
}
}
struct PacketOwned {
pub header: PacketHeader,
pub data: Box<[u8]>,
}

View File

@@ -129,7 +129,7 @@ fn from_source(source: &CaptureSource, pcap_out_path: Option<&String>) -> Result
let inactive = Capture::from_device(device.to_pcap_device())?;
let cap = inactive
.promisc(true)
.buffer_size(2_000_000) // 2MB buffer
.buffer_size(2_000_000) // 2MB buffer -> 10k packets of 200 bytes
.snaplen(if pcap_out_path.is_some() {
i32::from(u16::MAX)
} else {

View File

@@ -165,6 +165,8 @@ fn test_data_info() {
assert_eq!(data_info_1.outgoing_data(DataRepr::Bytes), 1400);
assert_eq!(data_info_1.outgoing_data(DataRepr::Bits), 11200);
// sleep a little to have a different final_instant
std::thread::sleep(std::time::Duration::from_millis(10));
let mut data_info_2 = DataInfo::new_with_first_packet(100, TrafficDirection::Outgoing);
// 0, 1, 0, 100
data_info_2.add_packets(19, 300, TrafficDirection::Outgoing);