Repository: GyulyVGC/sniffnet (language: rust)

Issue:
Fails to capture traffic from most non-physical interfaces
**Describe the bug**

It works for `wlan0` or veth interfaces, but fails for non-Ethernet-like things like `any` or wireguard.

**To Reproduce**

1. Install sniffnet v1.0.0 using `cargo install sniffnet` on Linux Debian 11.
2. Start sniffnet.
3. Choose e.g. `any`.

**Expected behavior**

It considers the same packets as e.g. `tcpdump -i any`.

**Actual behavior**

"No traffic can be observed because the adapter you selected has no active addresses"

or

"No traffic has been observed yet. Waiting for network packets..."



Discussion / hints:
For the "No traffic has been observed yet. Waiting for network packets..." I can do nothing: it depends on what pcap is actually able to sniff in term of kind of interface.

Thank you for having reported the problem with the "any" interface though, I think I have the solution for that one.

In the meantime, you can observe the traffic by choosing the specific interface (wlan0 and other actually receiving packets)
Not sure if it's the same issue, but I get the same message for the `any`, `wg0` (wireguard), and `tailscaled0` interfaces. `wlan0` works though. 

For reference, i'm running Arch linux with the linux-hardened kernel and systemd-networkd for networking + wireguard. 

Are there specific flags for outputting debug logs via the cli? 
> Not sure if it's the same issue, but I get the same message for the `any`, `wg0` (wireguard), and `tailscaled0` interfaces. `wlan0` works though.
> 
> For reference, i'm running Arch linux with the linux-hardened kernel and systemd-networkd for networking + wireguard.
> 
> Are there specific flags for outputting debug logs via the cli?

I confirm that it's the same issue.
And no, currently no debug logs are available in stdout/stderr.
Similar issue but maybe not identical. I use wirguard on MacOS and tunnel everything through that interface. I am only able to observe updates when selecting the wlan interface but all that shows is that it is communicating with my wg-server endpoint. It does  not actually seperate out the different connections being made through wg. 

When I select any of the other interfaces in the list, it just says waiting for packets/data. 

Is it possible to use something like wg and see what is being sent through the tunnel itself in more detail?
If no packets are received through a given interface, the problem is not related to Sniffnet itself but to what [rust-pcap](https://github.com/rust-pcap/pcap) is actually able to sniffs.
Understood. Packets are captured as per the screenshot attached. The first entry there in the Network host list is my wireguard server (with the swiss flag). So what happens is every connection gets put under that host so I cannot see the individual connections being made and sent through the tunnel.  Its the other tunnel interfaces which seem not to capture any packets.
 I guess what my question is, is it possible to  unbundle the connections being made so that I can actually see whats being sent through the wireguard tunnel?


<img width="1677" alt="Screenshot 2023-05-22 at 21 11 41" src="https://github.com/GyulyVGC/sniffnet/assets/1034537/6019d018-e8f4-496b-83a3-cd2e1a2cb122">

If you click on the network host you are interested in, you will see a list of its connections. Isn't it?
Not really, I still get everything bundled as per the screenshot below. The two entries in that list are basically the UDP packets (that contain encrypted packets) between my local laptop and the wireguard server.  So I still cannot see the details of the connections being made. If I look at the detailed logs, similar results along with what look like ipv6 related entries which have very few packets associated with them. 

<img width="1199" alt="Screenshot 2023-05-22 at 21 28 26" src="https://github.com/GyulyVGC/sniffnet/assets/1034537/dc24d013-3c19-483f-9586-6d4e39292da3">

Sniffnet currently defines a "connection" by the network-5-tuple:
- Source IP
- Source port
- Destination IP
- Destination port
- Transport protocol

If you see only one connection it means that all the exchanged packets are from/to the same ports.
Yes, technically that is correct. Because. wireguard being a tunelling protocol, all connections that my laptop makes gets sent through this tunnel from my laptop to the server. The server then acts a forwarding proxy and makes the actual connection to the desired remote server. 

So currently sniffnet just sees that all packets are going from my laptop to my server.  I guess what I am hearing is that it is not possible for sniffnet to intercept the packets prior to them being encrypted and sent through the tunnel so as to see where the request is actually being made. 

Great project though. Thanks for your efforts
Sniffnet can see everything directly incoming/outgoing to/from your network card.

If it doesn't see some specific interfaces, it's a problem related to pcap which I'd like to better understand myself.
I think I've finally understood the nature of this problem: so far Sniffnet was only able to read interfaces whose "link_type" was Ethernet.

Today I've found out that I wasn't able to monitor the traffic on my OpenVPN TUN adapter because it uses Null/Loopback as link type (see the screenshot below made using Wireshark).

![image](https://github.com/GyulyVGC/sniffnet/assets/100347457/ea98ad6e-1cfe-4aec-bed7-4ceb33d324c8)

So, I'm considering to add support for the Null/Loopback with the hope to solve the problem you guys mentioned as well, which is strictly related.

Before proceeding I would like to know if even in your scenarios the link type is Null/Loopback.
You can easily verify it by using Wireshark on the desired adapter and clicking on a packet entry.

Thank you in advance for your cooperation @vi @muzzah @3lpsy 
Related issue: https://github.com/JulianSchmid/etherparse/issues/78

Fix patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 1e008d2a0..bf83a6a91 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -7,6 +7,7 @@ All Sniffnet releases with the relative changes are documented in this file.
 - Introduced new filtering capabilities to allow users specify custom values of ports and IP addresses ([#414](https://github.com/GyulyVGC/sniffnet/pull/414))
 - The size of text and widgets can now be customised by setting a proper zoom value (fixes [#202](https://github.com/GyulyVGC/sniffnet/issues/202) and [#344](https://github.com/GyulyVGC/sniffnet/issues/344))
 - Added possibility to totally customize the app's theme via styles defined in TOML files ([#286](https://github.com/GyulyVGC/sniffnet/pull/286) and [#419](https://github.com/GyulyVGC/sniffnet/pull/419))
+- Added support for more link types in addition to Ethernet: raw IP packets and null/loopback packets are now correctly parsed ([#421](https://github.com/GyulyVGC/sniffnet/pull/421))
 - IP addresses can now be copied to clipboard from the popup related to a given entry of the connections table, and a new search parameter has been introduced in Inspect page to allow users filter their connections based on IP address values ([#409](https://github.com/GyulyVGC/sniffnet/pull/409))
 - Added Japanese translation 🇯🇵 ([#343](https://github.com/GyulyVGC/sniffnet/pull/343))
 - Added Uzbek translation 🇺🇿 ([#385](https://github.com/GyulyVGC/sniffnet/pull/385))
diff --git a/Cargo.lock b/Cargo.lock
index c04f6e3fa..2c0b0b9f5 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -201,7 +201,7 @@ dependencies = [
  "regex",
  "rustc-hash",
  "shlex",
- "syn 2.0.43",
+ "syn 2.0.44",
 ]
 
 [[package]]
@@ -279,7 +279,7 @@ checksum = "965ab7eb5f8f97d2a083c799f3a1b994fc397b2fe2da5d1da1626ce15a39f2b1"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.43",
+ "syn 2.0.44",
 ]
 
 [[package]]
@@ -353,13 +353,13 @@ dependencies = [
 
 [[package]]
 name = "clang-sys"
-version = "1.6.1"
+version = "1.7.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c688fc74432808e3eb684cae8830a86be1d66a2bd58e1f248ed0960a590baf6f"
+checksum = "67523a3b4be3ce1989d607a828d036249522dd9c1c8de7f4dd2dae43a37369d1"
 dependencies = [
  "glob",
  "libc",
- "libloading 0.7.4",
+ "libloading 0.8.1",
 ]
 
 [[package]]
@@ -942,7 +942,7 @@ checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.43",
+ "syn 2.0.44",
 ]
 
 [[package]]
@@ -2118,7 +2118,7 @@ dependencies = [
  "proc-macro-crate",
  "proc-macro2",
  "quote",
- "syn 2.0.43",
+ "syn 2.0.44",
 ]
 
 [[package]]
@@ -2247,7 +2247,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.43",
+ "syn 2.0.44",
 ]
 
 [[package]]
@@ -2298,7 +2298,7 @@ dependencies = [
  "proc-macro-error",
  "proc-macro2",
  "quote",
- "syn 2.0.43",
+ "syn 2.0.44",
 ]
 
 [[package]]
@@ -2330,7 +2330,7 @@ checksum = "b7db010ec5ff3d4385e4f133916faacd9dad0f6a09394c92d825b3aed310fa0a"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.43",
+ "syn 2.0.44",
 ]
 
 [[package]]
@@ -2438,7 +2438,7 @@ dependencies = [
  "phf_shared",
  "proc-macro2",
  "quote",
- "syn 2.0.43",
+ "syn 2.0.44",
 ]
 
 [[package]]
@@ -2560,9 +2560,9 @@ dependencies = [
 
 [[package]]
 name = "proc-macro2"
-version = "1.0.71"
+version = "1.0.73"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "75cb1540fadbd5b8fbccc4dddad2734eba435053f725621c070711a14bb5f4b8"
+checksum = "2dd5e8a1f1029c43224ad5898e50140c2aebb1705f19e67c918ebf5b9e797fe1"
 dependencies = [
  "unicode-ident",
 ]
@@ -2584,9 +2584,9 @@ dependencies = [
 
 [[package]]
 name = "quote"
-version = "1.0.33"
+version = "1.0.34"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae"
+checksum = "22a37c9326af5ed140c86a46655b5278de879853be5573c01df185b6f49a580a"
 dependencies = [
  "proc-macro2",
 ]
@@ -2851,7 +2851,7 @@ dependencies = [
  "regex",
  "relative-path",
  "rustc_version",
- "syn 2.0.43",
+ "syn 2.0.44",
  "unicode-ident",
 ]
 
@@ -3058,14 +3058,14 @@ checksum = "43576ca501357b9b071ac53cdc7da8ef0cbd9493d8df094cd821777ea6e894d3"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.43",
+ "syn 2.0.44",
 ]
 
 [[package]]
 name = "serde_json"
-version = "1.0.108"
+version = "1.0.109"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3d1c7e3eac408d115102c4c24ad393e0821bb3a5df4d506a80f85f7a742a526b"
+checksum = "cb0652c533506ad7a2e353cce269330d6afd8bdfb6d75e0ace5b35aacbd7b9e9"
 dependencies = [
  "itoa",
  "ryu",
@@ -3122,7 +3122,7 @@ checksum = "91d129178576168c589c9ec973feedf7d3126c01ac2bf08795109aa35b69fb8f"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.43",
+ "syn 2.0.44",
 ]
 
 [[package]]
@@ -3394,9 +3394,9 @@ dependencies = [
 
 [[package]]
 name = "syn"
-version = "2.0.43"
+version = "2.0.44"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ee659fb5f3d355364e1f3e5bc10fb82068efbf824a1e9d1c9504244a6469ad53"
+checksum = "92d27c2c202598d05175a6dd3af46824b7f747f8d8e9b14c623f19fa5069735d"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -3457,22 +3457,22 @@ dependencies = [
 
 [[package]]
 name = "thiserror"
-version = "1.0.52"
+version = "1.0.53"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "83a48fd946b02c0a526b2e9481c8e2a17755e47039164a86c4070446e3a4614d"
+checksum = "b2cd5904763bad08ad5513ddbb12cf2ae273ca53fa9f68e843e236ec6dfccc09"
 dependencies = [
  "thiserror-impl",
 ]
 
 [[package]]
 name = "thiserror-impl"
-version = "1.0.52"
+version = "1.0.53"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e7fbe9b594d6568a6a1443250a7e67d80b74e1e96f6d1715e1e21cc1888291d3"
+checksum = "3dcf4a824cce0aeacd6f38ae6f24234c8e80d68632338ebaa1443b5df9e29e19"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.43",
+ "syn 2.0.44",
 ]
 
 [[package]]
@@ -3922,7 +3922,7 @@ dependencies = [
  "once_cell",
  "proc-macro2",
  "quote",
- "syn 2.0.43",
+ "syn 2.0.44",
  "wasm-bindgen-shared",
 ]
 
@@ -3956,7 +3956,7 @@ checksum = "f0eb82fcb7930ae6219a7ecfd55b217f5f0893484b7a13022ebb2b2bf20b5283"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.43",
+ "syn 2.0.44",
  "wasm-bindgen-backend",
  "wasm-bindgen-shared",
 ]
@@ -4719,5 +4719,5 @@ checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.43",
+ "syn 2.0.44",
 ]
diff --git a/src/configs/types/config_device.rs b/src/configs/types/config_device.rs
index 3e89852bd..a01f891a8 100644
--- a/src/configs/types/config_device.rs
+++ b/src/configs/types/config_device.rs
@@ -7,6 +7,7 @@ use pcap::{Device, DeviceFlags};
 use serde::{Deserialize, Serialize};
 
 use crate::networking::types::my_device::MyDevice;
+use crate::networking::types::my_link_type::MyLinkType;
 #[cfg(not(test))]
 use crate::SNIFFNET_LOWERCASE;
 
@@ -57,6 +58,7 @@ impl ConfigDevice {
                     name: device.name,
                     desc: device.desc,
                     addresses: Arc::new(Mutex::new(device.addresses)),
+                    link_type: MyLinkType::NotYetAssigned,
                 };
             }
         }
@@ -70,6 +72,7 @@ impl ConfigDevice {
             name: standard_device.name,
             desc: standard_device.desc,
             addresses: Arc::new(Mutex::new(standard_device.addresses)),
+            link_type: MyLinkType::NotYetAssigned,
         }
     }
 }
diff --git a/src/countries/country_utils.rs b/src/countries/country_utils.rs
index 87e359f6f..49e8990c7 100644
--- a/src/countries/country_utils.rs
+++ b/src/countries/country_utils.rs
@@ -21,6 +21,7 @@ use crate::countries::types::country::Country;
 use crate::gui::styles::container::ContainerType;
 use crate::gui::styles::svg::SvgType;
 use crate::gui::types::message::Message;
+use crate::networking::types::data_info_host::DataInfoHost;
 use crate::networking::types::traffic_type::TrafficType;
 use crate::translations::translations_2::{
     local_translation, unknown_translation, your_network_adapter_translation,
@@ -31,6 +32,7 @@ fn get_flag_from_country(
     country: Country,
     width: f32,
     is_local: bool,
+    is_loopback: bool,
     traffic_type: TrafficType,
     language: Language,
 ) -> (Svg<Renderer<StyleType>>, String) {
@@ -284,7 +286,11 @@ fn get_flag_from_country(
         Country::ZM => ZM,
         Country::ZW => ZW,
         Country::ZZ => {
-            if is_local {
+            if is_loopback {
+                tooltip = your_network_adapter_translation(language);
+                svg_style = SvgType::AdaptColor;
+                COMPUTER
+            } else if is_local {
                 tooltip = local_translation(language);
                 svg_style = SvgType::AdaptColor;
                 HOME
@@ -313,13 +319,21 @@ fn get_flag_from_country(
 pub fn get_flag_tooltip(
     country: Country,
     width: f32,
-    is_local: bool,
-    traffic_type: TrafficType,
+    host_info: &DataInfoHost,
     language: Language,
     font: Font,
 ) -> Tooltip<'static, Message, Renderer<StyleType>> {
-    let (content, tooltip) =
-        get_flag_from_country(country, width, is_local, traffic_type, language);
+    let is_local = host_info.is_local;
+    let is_loopback = host_info.is_loopback;
+    let traffic_type = host_info.traffic_type;
+    let (content, tooltip) = get_flag_from_country(
+        country,
+        width,
+        is_local,
+        is_loopback,
+        traffic_type,
+        language,
+    );
 
     let mut tooltip = Tooltip::new(content, tooltip, Position::FollowCursor)
         .font(font)
@@ -335,27 +349,30 @@ pub fn get_flag_tooltip(
 
 pub fn get_computer_tooltip(
     is_my_address: bool,
+    is_local: bool,
     traffic_type: TrafficType,
     language: Language,
     font: Font,
 ) -> Tooltip<'static, Message, Renderer<StyleType>> {
     let content = Svg::new(Handle::from_memory(Vec::from(
-        match (is_my_address, traffic_type) {
-            (true, _) => COMPUTER,
-            (false, TrafficType::Multicast) => MULTICAST,
-            (false, TrafficType::Broadcast) => BROADCAST,
-            (false, TrafficType::Unicast) => UNKNOWN,
+        match (is_my_address, is_local, traffic_type) {
+            (true, _, _) => COMPUTER,
+            (false, true, _) => HOME,
+            (false, false, TrafficType::Multicast) => MULTICAST,
+            (false, false, TrafficType::Broadcast) => BROADCAST,
+            (false, false, TrafficType::Unicast) => UNKNOWN,
         },
     )))
     .style(SvgType::AdaptColor)
     .width(Length::Fixed(FLAGS_WIDTH_BIG))
     .height(Length::Fixed(FLAGS_WIDTH_BIG * 0.75));
 
-    let tooltip = match (is_my_address, traffic_type) {
-        (true, _) => your_network_adapter_translation(language),
-        (false, TrafficType::Multicast) => "Multicast".to_string(),
-        (false, TrafficType::Broadcast) => "Broadcast".to_string(),
-        (false, TrafficType::Unicast) => unknown_translation(language),
+    let tooltip = match (is_my_address, is_local, traffic_type) {
+        (true, _, _) => your_network_adapter_translation(language),
+        (false, true, _) => local_translation(language),
+        (false, false, TrafficType::Multicast) => "Multicast".to_string(),
+        (false, false, TrafficType::Broadcast) => "Broadcast".to_string(),
+        (false, false, TrafficType::Unicast) => unknown_translation(language),
     };
 
     Tooltip::new(content, tooltip, Position::FollowCursor)
diff --git a/src/gui/pages/connection_details_page.rs b/src/gui/pages/connection_details_page.rs
index b4066b119..0d9d9e7e6 100644
--- a/src/gui/pages/connection_details_page.rs
+++ b/src/gui/pages/connection_details_page.rs
@@ -18,7 +18,9 @@ use crate::gui::styles::text::TextType;
 use crate::gui::styles::types::gradient_type::GradientType;
 use crate::gui::types::message::Message;
 use crate::gui::types::timing_events::TimingEvents;
-use crate::networking::manage_packets::{get_address_to_lookup, get_traffic_type, is_my_address};
+use crate::networking::manage_packets::{
+    get_address_to_lookup, get_traffic_type, is_local_connection, is_my_address,
+};
 use crate::networking::types::address_port_pair::AddressPortPair;
 use crate::networking::types::host::Host;
 use crate::networking::types::icmp_type::IcmpType;
@@ -105,14 +107,7 @@ fn page_content(
     if let Some((r_dns, host)) = host_option {
         host_info_col = get_host_info_col(&r_dns, &host, font, language);
         let host_info = host_info_option.unwrap_or_default();
-        let flag = get_flag_tooltip(
-            host.country,
-            FLAGS_WIDTH_BIG,
-            host_info.is_local,
-            host_info.traffic_type,
-            language,
-            font,
-        );
+        let flag = get_flag_tooltip(host.country, FLAGS_WIDTH_BIG, &host_info, language, font);
         let computer = get_local_tooltip(sniffer, &address_to_lookup, key);
         if address_to_lookup.eq(&key.address1) {
             source_caption = source_caption.push(flag);
@@ -310,16 +305,15 @@ fn get_local_tooltip(
         style, language, ..
     } = sniffer.configs.lock().unwrap().settings;
 
+    let local_address = if address_to_lookup.eq(&key.address1) {
+        &key.address2
+    } else {
+        &key.address1
+    };
     let my_interface_addresses = &*sniffer.device.addresses.lock().unwrap();
     get_computer_tooltip(
-        is_my_address(
-            if address_to_lookup.eq(&key.address1) {
-                &key.address2
-            } else {
-                &key.address1
-            },
-            my_interface_addresses,
-        ),
+        is_my_address(local_address, my_interface_addresses),
+        is_local_connection(local_address, my_interface_addresses),
         get_traffic_type(
             if address_to_lookup.eq(&key.address1) {
                 &key.address2
@@ -338,7 +332,7 @@ fn get_src_or_dest_col(
     caption: Row<'static, Message, Renderer<StyleType>>,
     ip: &String,
     port: Option<u16>,
-    mac: &str,
+    mac: &Option<String>,
     font: Font,
     language: Language,
     timing_events: &TimingEvents,
@@ -348,6 +342,9 @@ fn get_src_or_dest_col(
     } else {
         address_translation(language)
     };
+
+    let mac_str = if let Some(val) = mac { val } else { "-" };
+
     Column::new()
         .spacing(4)
         .push(
@@ -369,7 +366,7 @@ fn get_src_or_dest_col(
         )
         .push(TextType::highlighted_subtitle_with_desc(
             mac_address_translation(language),
-            mac,
+            mac_str,
             font,
         ))
 }
diff --git a/src/gui/pages/notifications_page.rs b/src/gui/pages/notifications_page.rs
index 0a6ec414d..74a5963e2 100644
--- a/src/gui/pages/notifications_page.rs
+++ b/src/gui/pages/notifications_page.rs
@@ -312,11 +312,10 @@ fn favorite_notification_log(
     language: Language,
     font: Font,
 ) -> Container<'static, Message, Renderer<StyleType>> {
-    let domain = logged_notification.host.domain;
     let country = logged_notification.host.country;
-    let asn = logged_notification.host.asn;
+    let asn = &logged_notification.host.asn;
 
-    let mut domain_asn_str = domain;
+    let mut domain_asn_str = logged_notification.host.domain;
     if !asn.name.is_empty() {
         domain_asn_str.push_str(&format!(" - {}", asn.name));
     }
@@ -327,8 +326,7 @@ fn favorite_notification_log(
         .push(get_flag_tooltip(
             country,
             FLAGS_WIDTH_BIG,
-            logged_notification.data_info_host.is_local,
-            logged_notification.data_info_host.traffic_type,
+            &logged_notification.data_info_host,
             language,
             font,
         ))
diff --git a/src/gui/pages/overview_page.rs b/src/gui/pages/overview_page.rs
index 5d35f6753..ae6064c9f 100644
--- a/src/gui/pages/overview_page.rs
+++ b/src/gui/pages/overview_page.rs
@@ -41,6 +41,7 @@ use crate::translations::translations_2::{
     data_representation_translation, dropped_packets_translation, host_translation,
     only_top_30_hosts_translation,
 };
+use crate::translations::translations_3::unsupported_link_type_translation;
 use crate::utils::formatted_strings::{
     get_active_filters_string, get_formatted_bytes_string_with_b, get_percentage_string,
 };
@@ -140,18 +141,27 @@ fn body_no_packets(
     language: Language,
     waiting: &str,
 ) -> Column<'static, Message, Renderer<StyleType>> {
-    let adapter_name = device.name.clone();
-    let (icon_text, nothing_to_see_text) = if device.addresses.lock().unwrap().is_empty() {
+    let link_type = device.link_type;
+    let mut adapter_info = device.name.clone();
+    adapter_info.push_str(&format!("\n{}", link_type.full_print_on_one_line(language)));
+    let (icon_text, nothing_to_see_text) = if !link_type.is_supported() {
         (
             Icon::Warning.to_text().size(60),
-            no_addresses_translation(language, &adapter_name)
+            unsupported_link_type_translation(language, &adapter_info)
+                .horizontal_alignment(Horizontal::Center)
+                .font(font),
+        )
+    } else if device.addresses.lock().unwrap().is_empty() {
+        (
+            Icon::Warning.to_text().size(60),
+            no_addresses_translation(language, &adapter_info)
                 .horizontal_alignment(Horizontal::Center)
                 .font(font),
         )
     } else {
         (
             Icon::get_hourglass(waiting.len()).size(60),
-            waiting_translation(language, &adapter_name)
+            waiting_translation(language, &adapter_info)
                 .horizontal_alignment(Horizontal::Center)
                 .font(font),
         )
@@ -295,8 +305,7 @@ fn col_host(width: f32, sniffer: &Sniffer) -> Column<'static, Message, Renderer<
             .push(get_flag_tooltip(
                 host.country,
                 FLAGS_WIDTH_BIG,
-                data_info_host.is_local,
-                data_info_host.traffic_type,
+                data_info_host,
                 language,
                 font,
             ))
@@ -419,24 +428,13 @@ fn lazy_col_info(
         style, language, ..
     } = sniffer.configs.lock().unwrap().settings;
     let font = style.get_extension().font;
-    let filtered_bytes =
-        sniffer.runtime_data.tot_sent_bytes + sniffer.runtime_data.tot_received_bytes;
-    let all_bytes = sniffer.runtime_data.all_bytes;
 
-    let col_device_filters = col_device_filters(language, font, &sniffer.filters, &sniffer.device);
+    let col_device = col_device(language, font, &sniffer.device);
 
     let col_data_representation =
         col_data_representation(language, font, sniffer.traffic_chart.chart_type);
 
-    let col_bytes_packets = col_bytes_packets(
-        language,
-        dropped,
-        total,
-        filtered,
-        all_bytes,
-        filtered_bytes,
-        font,
-    );
+    let col_bytes_packets = col_bytes_packets(language, dropped, total, filtered, font, sniffer);
 
     let content = Column::new()
         .align_items(Alignment::Center)
@@ -445,14 +443,14 @@ fn lazy_col_info(
             Row::new()
                 .height(Length::Fixed(120.0))
                 .push(
-                    Scrollable::new(col_device_filters)
-                        .width(Length::Fill)
-                        .direction(Direction::Vertical(ScrollbarType::properties())),
+                    Scrollable::new(col_device)
+                        .width(Length::FillPortion(1))
+                        .direction(Direction::Horizontal(ScrollbarType::properties())),
                 )
                 .push(Rule::vertical(25))
-                .push(col_data_representation),
+                .push(col_data_representation.width(Length::FillPortion(1))),
         )
-        .push(Rule::horizontal(25))
+        .push(Rule::horizontal(15))
         .push(
             Scrollable::new(col_bytes_packets)
                 .width(Length::Fill)
@@ -507,28 +505,25 @@ fn container_chart(sniffer: &Sniffer, font: Font) -> Container<Message, Renderer
     .style(ContainerType::BorderedRound)
 }
 
-fn col_device_filters(
+fn col_device(
     language: Language,
     font: Font,
-    filters: &Filters,
     device: &MyDevice,
 ) -> Column<'static, Message, Renderer<StyleType>> {
+    let link_type = device.link_type;
     #[cfg(not(target_os = "windows"))]
     let adapter_info = &device.name;
     #[cfg(target_os = "windows")]
-    let adapter_name = &device.name;
-    #[cfg(target_os = "windows")]
-    let adapter_info = device.desc.as_ref().unwrap_or(adapter_name);
+    let adapter_info = device.desc.as_ref().unwrap_or(&device.name);
 
     Column::new()
-        .width(Length::FillPortion(1))
+        .spacing(10)
         .push(TextType::highlighted_subtitle_with_desc(
             network_adapter_translation(language),
             adapter_info,
             font,
         ))
-        .push(vertical_space(15))
-        .push(get_active_filters_col(filters, language, font, false))
+        .push(link_type.link_type_col(language, font))
 }
 
 fn col_data_representation(
@@ -536,7 +531,7 @@ fn col_data_representation(
     font: Font,
     chart_type: ChartType,
 ) -> Column<'static, Message, Renderer<StyleType>> {
-    let mut ret_val = Column::new().spacing(5).width(Length::FillPortion(1)).push(
+    let mut ret_val = Column::new().spacing(5).push(
         Text::new(format!("{}:", data_representation_translation(language)))
             .style(TextType::Subtitle)
             .font(font),
@@ -570,10 +565,14 @@ fn col_bytes_packets(
     dropped: u32,
     total: u128,
     filtered: u128,
-    all_bytes: u128,
-    filtered_bytes: u128,
     font: Font,
+    sniffer: &Sniffer,
 ) -> Column<'static, Message, Renderer<StyleType>> {
+    let filtered_bytes =
+        sniffer.runtime_data.tot_sent_bytes + sniffer.runtime_data.tot_received_bytes;
+    let all_bytes = sniffer.runtime_data.all_bytes;
+    let filters = &sniffer.filters;
+
     let dropped_val = if dropped > 0 {
         format!(
             "{} {}",
@@ -594,7 +593,8 @@ fn col_bytes_packets(
     };
 
     Column::new()
-        .spacing(15)
+        .spacing(10)
+        .push(get_active_filters_col(filters, language, font, false))
         .push(TextType::highlighted_subtitle_with_desc(
             filtered_bytes_translation(language),
             &bytes_value,
diff --git a/src/gui/types/runtime_data.rs b/src/gui/types/runtime_data.rs
index 6390e48df..ddd1426b5 100644
--- a/src/gui/types/runtime_data.rs
+++ b/src/gui/types/runtime_data.rs
@@ -1,5 +1,5 @@
 //! Module defining the `RunTimeData` struct, useful to to generate chart and to display statistics about network traffic
-//!
+
 use std::collections::VecDeque;
 
 use crate::notifications::types::logged_notification::LoggedNotification;
diff --git a/src/gui/types/sniffer.rs b/src/gui/types/sniffer.rs
index 6300f2323..7465108a6 100644
--- a/src/gui/types/sniffer.rs
+++ b/src/gui/types/sniffer.rs
@@ -24,6 +24,7 @@ use crate::networking::types::filters::Filters;
 use crate::networking::types::host::Host;
 use crate::networking::types::ip_collection::AddressCollection;
 use crate::networking::types::my_device::MyDevice;
+use crate::networking::types::my_link_type::MyLinkType;
 use crate::networking::types::port_collection::PortCollection;
 use crate::networking::types::search_parameters::SearchParameters;
 use crate::notifications::notify_and_log::notify_and_log;
@@ -351,7 +352,7 @@ impl Sniffer {
         let current_device_name = &*self.device.name.clone();
         self.set_adapter(current_device_name);
         let device = self.device.clone();
-        let (pcap_error, cap) = get_capture_result(&device);
+        let (pcap_error, cap_result) = get_capture_result(&device);
         self.pcap_error = pcap_error.clone();
         let info_traffic_mutex = self.info_traffic.clone();
         *info_traffic_mutex.lock().unwrap() = InfoTraffic::new();
@@ -364,17 +365,19 @@ impl Sniffer {
 
         if pcap_error.is_none() {
             // no pcap error
+            let cap = cap_result.unwrap();
             let current_capture_id = self.current_capture_id.clone();
             let filters = self.filters.clone();
             let country_mmdb_reader = self.country_mmdb_reader.clone();
             let asn_mmdb_reader = self.asn_mmdb_reader.clone();
+            self.device.link_type = MyLinkType::from_pcap_link_type(cap.get_datalink());
             thread::Builder::new()
                 .name("thread_parse_packets".to_string())
                 .spawn(move || {
                     parse_packets(
                         &current_capture_id,
                         &device,
-                        cap.unwrap(),
+                        cap,
                         &filters,
                         &info_traffic_mutex,
                         &country_mmdb_reader,
@@ -406,6 +409,7 @@ impl Sniffer {
                     name: dev.name,
                     desc: dev.desc,
                     addresses: self.device.addresses.clone(),
+                    link_type: MyLinkType::NotYetAssigned,
                 };
                 break;
             }
diff --git a/src/networking/manage_packets.rs b/src/networking/manage_packets.rs
index 694ae554d..2aa958463 100644
--- a/src/networking/manage_packets.rs
+++ b/src/networking/manage_packets.rs
@@ -1,5 +1,6 @@
 use std::collections::HashMap;
 use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
+use std::str::FromStr;
 use std::sync::{Arc, Mutex};
 
 use chrono::Local;
@@ -28,14 +29,12 @@ use crate::{AppProtocol, InfoTraffic, IpVersion, Protocol};
 /// Returns the relevant collected information.
 pub fn analyze_headers(
     headers: PacketHeaders,
-    mac_addresses: &mut (String, String),
+    mac_addresses: &mut (Option<String>, Option<String>),
     exchanged_bytes: &mut u128,
     icmp_type: &mut IcmpType,
     packet_filters_fields: &mut PacketFiltersFields,
 ) -> Option<AddressPortPair> {
-    if !analyze_link_header(headers.link, &mut mac_addresses.0, &mut mac_addresses.1) {
-        return None;
-    }
+    analyze_link_header(headers.link, &mut mac_addresses.0, &mut mac_addresses.1);
 
     if !analyze_network_header(
         headers.ip,
@@ -71,16 +70,15 @@ pub fn analyze_headers(
 /// Returns false if packet has to be skipped.
 fn analyze_link_header(
     link_header: Option<Ethernet2Header>,
-    mac_address1: &mut String,
-    mac_address2: &mut String,
-) -> bool {
-    match link_header {
-        Some(header) => {
-            *mac_address1 = mac_from_dec_to_hex(header.source);
-            *mac_address2 = mac_from_dec_to_hex(header.destination);
-            true
-        }
-        _ => false,
+    mac_address1: &mut Option<String>,
+    mac_address2: &mut Option<String>,
+) {
+    if let Some(header) = link_header {
+        *mac_address1 = Some(mac_from_dec_to_hex(header.source));
+        *mac_address2 = Some(mac_from_dec_to_hex(header.destination));
+    } else {
+        *mac_address1 = None;
+        *mac_address2 = None;
     }
 }
 
@@ -167,7 +165,7 @@ pub fn modify_or_insert_in_map(
     info_traffic_mutex: &Arc<Mutex<InfoTraffic>>,
     key: &AddressPortPair,
     my_device: &MyDevice,
-    mac_addresses: (String, String),
+    mac_addresses: (Option<String>, Option<String>),
     icmp_type: IcmpType,
     exchanged_bytes: u128,
     application_protocol: AppProtocol,
@@ -192,8 +190,13 @@ pub fn modify_or_insert_in_map(
         // determine traffic direction
         let source_ip = &key.address1;
         let destination_ip = &key.address2;
-        traffic_direction =
-            get_traffic_direction(source_ip, destination_ip, &my_interface_addresses);
+        traffic_direction = get_traffic_direction(
+            source_ip,
+            destination_ip,
+            key.port1,
+            key.port2,
+            &my_interface_addresses,
+        );
     };
 
     let mut info_traffic = info_traffic_mutex
@@ -264,6 +267,7 @@ pub fn reverse_dns_lookup(
         &my_interface_addresses,
         traffic_direction,
     );
+    let is_loopback = is_loopback(&address_to_lookup);
     let is_local = is_local_connection(&address_to_lookup, &my_interface_addresses);
     let country = get_country(&address_to_lookup, country_db_reader);
     let asn = get_asn(&address_to_lookup, asn_db_reader);
@@ -301,6 +305,7 @@ pub fn reverse_dns_lookup(
         .or_insert(DataInfoHost {
             data_info: other_data,
             is_favorite: false,
+            is_loopback,
             is_local,
             traffic_type,
         });
@@ -316,6 +321,8 @@ pub fn reverse_dns_lookup(
 fn get_traffic_direction(
     source_ip: &String,
     destination_ip: &String,
+    source_port: Option<u16>,
+    dest_port: Option<u16>,
     my_interface_addresses: &[Address],
 ) -> TrafficDirection {
     let my_interface_addresses_string: Vec<String> = my_interface_addresses
@@ -323,6 +330,17 @@ fn get_traffic_direction(
         .map(|address| address.addr.to_string())
         .collect();
 
+    // first let's handle TCP and UDP loopback
+    if is_loopback(source_ip) && is_loopback(destination_ip) {
+        if let (Some(sport), Some(dport)) = (source_port, dest_port) {
+            return if sport > dport {
+                TrafficDirection::Outgoing
+            } else {
+                TrafficDirection::Incoming
+            };
+        }
+    }
+
     if my_interface_addresses_string.contains(source_ip) {
         // source is local
         TrafficDirection::Outgoing
@@ -410,8 +428,14 @@ fn is_broadcast_address(address: &str, my_interface_addresses: &[Address]) -> bo
     false
 }
 
+fn is_loopback(address_to_lookup: &str) -> bool {
+    IpAddr::from_str(address_to_lookup)
+        .unwrap_or(IpAddr::V4(Ipv4Addr::UNSPECIFIED))
+        .is_loopback()
+}
+
 /// Determines if the connection is local
-fn is_local_connection(address_to_lookup: &str, my_interface_addresses: &Vec<Address>) -> bool {
+pub fn is_local_connection(address_to_lookup: &str, my_interface_addresses: &Vec<Address>) -> bool {
     let mut ret_val = false;
 
     let address_to_lookup_type = if address_to_lookup.contains(':') {
@@ -478,22 +502,18 @@ fn is_local_connection(address_to_lookup: &str, my_interface_addresses: &Vec<Add
 }
 
 /// Determines if the address passed as parameter belong to the chosen adapter
-pub fn is_my_address(address_to_lookup: &String, my_interface_addresses: &Vec<Address>) -> bool {
-    let mut ret_val = false;
-
+pub fn is_my_address(local_address: &String, my_interface_addresses: &Vec<Address>) -> bool {
     for address in my_interface_addresses {
-        if address.addr.to_string().eq(address_to_lookup) {
-            ret_val = true;
-            break;
+        if address.addr.to_string().eq(local_address) {
+            return true;
         }
     }
-
-    ret_val
+    is_loopback(local_address)
 }
 
 /// Determines if the capture opening resolves into an Error
 pub fn get_capture_result(device: &MyDevice) -> (Option<String>, Option<Capture<Active>>) {
-    let cap_result = Capture::from_device(&*device.name)
+    let cap_result = Capture::from_device(device.to_pcap_device())
         .expect("Capture initialization error\n\r")
         .promisc(true)
         .snaplen(256) //limit stored packets slice dimension (to keep more in the buffer)
@@ -662,30 +682,40 @@ mod tests {
         let result1 = get_traffic_direction(
             &"172.20.10.9".to_string(),
             &"99.88.77.00".to_string(),
+            Some(99),
+            Some(99),
             &address_vec,
         );
         assert_eq!(result1, TrafficDirection::Outgoing);
         let result2 = get_traffic_direction(
             &"172.20.10.10".to_string(),
             &"172.20.10.9".to_string(),
+            Some(99),
+            Some(99),
             &address_vec,
         );
         assert_eq!(result2, TrafficDirection::Incoming);
         let result3 = get_traffic_direction(
             &"172.20.10.9".to_string(),
             &"0.0.0.0".to_string(),
+            Some(99),
+            Some(99),
             &address_vec,
         );
         assert_eq!(result3, TrafficDirection::Outgoing);
         let result4 = get_traffic_direction(
             &"0.0.0.0".to_string(),
             &"172.20.10.9".to_string(),
+            Some(99),
+            Some(99),
             &address_vec,
         );
         assert_eq!(result4, TrafficDirection::Incoming);
         let result4 = get_traffic_direction(
             &"0.0.0.0".to_string(),
             &"172.20.10.10".to_string(),
+            Some(99),
+            Some(99),
             &address_vec,
         );
         assert_eq!(result4, TrafficDirection::Outgoing);
diff --git a/src/networking/types/data_info_host.rs b/src/networking/types/data_info_host.rs
index b129978fa..68b54d042 100644
--- a/src/networking/types/data_info_host.rs
+++ b/src/networking/types/data_info_host.rs
@@ -10,6 +10,8 @@ pub struct DataInfoHost {
     pub data_info: DataInfo,
     /// Determine if this host is one of the favorites
     pub is_favorite: bool,
+    /// Determine if the connection is loopback (the "remote" is loopback)
+    pub is_loopback: bool,
     /// Determine if the connection with this host is local
     pub is_local: bool,
     /// Determine if the connection with this host is unicast, multicast, or broadcast
diff --git a/src/networking/types/info_address_port_pair.rs b/src/networking/types/info_address_port_pair.rs
index 2ede47a8c..9c16e517b 100644
--- a/src/networking/types/info_address_port_pair.rs
+++ b/src/networking/types/info_address_port_pair.rs
@@ -17,9 +17,9 @@ use crate::AppProtocol;
 #[derive(Clone, Default)]
 pub struct InfoAddressPortPair {
     /// Source MAC address
-    pub mac_address1: String,
+    pub mac_address1: Option<String>,
     /// Destination MAC address
-    pub mac_address2: String,
+    pub mac_address2: Option<String>,
     /// Amount of bytes transmitted between the pair.
     pub transmitted_bytes: u128,
     /// Amount of packets transmitted between the pair.
diff --git a/src/networking/types/mod.rs b/src/networking/types/mod.rs
index 2134f3284..8bc652c19 100644
--- a/src/networking/types/mod.rs
+++ b/src/networking/types/mod.rs
@@ -12,6 +12,7 @@ pub mod info_traffic;
 pub mod ip_collection;
 pub mod ip_version;
 pub mod my_device;
+pub mod my_link_type;
 pub mod packet_filters_fields;
 pub mod port_collection;
 pub mod protocol;
diff --git a/src/networking/types/my_device.rs b/src/networking/types/my_device.rs
index f267a8115..3e347d15b 100644
--- a/src/networking/types/my_device.rs
+++ b/src/networking/types/my_device.rs
@@ -1,6 +1,8 @@
 use std::sync::{Arc, Mutex};
 
-use pcap::Address;
+use pcap::{Address, Device, DeviceFlags};
+
+use crate::networking::types::my_link_type::MyLinkType;
 
 /// Represents the current inspected device.
 /// Used to keep in sync the device addresses in case of changes
@@ -10,4 +12,21 @@ pub struct MyDevice {
     pub name: String,
     pub desc: Option<String>,
     pub addresses: Arc<Mutex<Vec<Address>>>,
+    pub link_type: MyLinkType,
+}
+
+impl MyDevice {
+    pub fn to_pcap_device(&self) -> Device {
+        for device in Device::list().unwrap_or_default() {
+            if device.name.eq(&self.name) {
+                return device;
+            }
+        }
+        Device::lookup().unwrap_or(None).unwrap_or(Device {
+            name: String::new(),
+            desc: None,
+            addresses: vec![],
+            flags: DeviceFlags::empty(),
+        })
+    }
 }
diff --git a/src/networking/types/my_link_type.rs b/src/networking/types/my_link_type.rs
new file mode 100644
index 000000000..24d2750cc
--- /dev/null
+++ b/src/networking/types/my_link_type.rs
@@ -0,0 +1,87 @@
+use iced::widget::Column;
+use iced::{Font, Renderer};
+use pcap::Linktype;
+
+use crate::gui::styles::text::TextType;
+use crate::gui::types::message::Message;
+use crate::translations::translations_3::link_type_translation;
+use crate::{Language, StyleType};
+
+/// Currently supported link types
+#[derive(Copy, Clone)]
+pub enum MyLinkType {
+    Null(Linktype),
+    Ethernet(Linktype),
+    RawIp(Linktype),
+    Loop(Linktype),
+    IPv4(Linktype),
+    IPv6(Linktype),
+    Unsupported(Linktype),
+    NotYetAssigned,
+}
+
+impl MyLinkType {
+    pub fn is_supported(self) -> bool {
+        !matches!(self, Self::Unsupported(_) | Self::NotYetAssigned)
+    }
+
+    pub fn from_pcap_link_type(link_type: Linktype) -> Self {
+        match link_type {
+            Linktype::NULL => Self::Null(link_type),
+            Linktype::ETHERNET => Self::Ethernet(link_type),
+            Linktype(12) => Self::RawIp(link_type),
+            Linktype::LOOP => Self::Loop(link_type),
+            Linktype::IPV4 => Self::IPv4(link_type),
+            Linktype::IPV6 => Self::IPv6(link_type),
+            _ => Self::Unsupported(link_type),
+        }
+    }
+
+    pub fn full_print_on_one_line(self, language: Language) -> String {
+        match self {
+            Self::Null(l)
+            | Self::Ethernet(l)
+            | Self::RawIp(l)
+            | Self::Loop(l)
+            | Self::IPv4(l)
+            | Self::IPv6(l)
+            | Self::Unsupported(l) => {
+                format!(
+                    "{}: {} ({})",
+                    link_type_translation(language),
+                    l.get_name().unwrap_or(l.0.to_string()),
+                    l.get_description().unwrap_or(String::new())
+                )
+            }
+            Self::NotYetAssigned => String::new(),
+        }
+    }
+
+    pub fn link_type_col(
+        self,
+        language: Language,
+        font: Font,
+    ) -> Column<'static, Message, Renderer<StyleType>> {
+        match self {
+            Self::Null(l)
+            | Self::Ethernet(l)
+            | Self::RawIp(l)
+            | Self::Loop(l)
+            | Self::IPv4(l)
+            | Self::IPv6(l)
+            | Self::Unsupported(l) => {
+                let link_info = format!(
+                    "{} ({})",
+                    l.get_name().unwrap_or(l.0.to_string()),
+                    l.get_description().unwrap_or(String::new())
+                );
+                TextType::highlighted_subtitle_with_desc(
+                    link_type_translation(language),
+                    &link_info,
+                    font,
+                )
+            }
+            Self::NotYetAssigned => Column::new().height(0),
+        }
+    }
+}
diff --git a/src/report/get_report_entries.rs b/src/report/get_report_entries.rs
index aa0f2480e..0010df1ad 100644
--- a/src/report/get_report_entries.rs
+++ b/src/report/get_report_entries.rs
@@ -120,8 +120,7 @@ pub fn get_searched_entries(sniffer: &Sniffer) -> (Vec<ReportEntry>, usize) {
                 let flag = get_flag_tooltip(
                     host.country,
                     FLAGS_WIDTH_SMALL,
-                    host_info.is_local,
-                    host_info.traffic_type,
+                    host_info,
                     language,
                     style.get_extension().font,
                 );
diff --git a/src/secondary_threads/parse_packets.rs b/src/secondary_threads/parse_packets.rs
index 33ac999e5..338ca49e2 100644
--- a/src/secondary_threads/parse_packets.rs
+++ b/src/secondary_threads/parse_packets.rs
@@ -1,11 +1,12 @@
 //! Module containing functions executed by the thread in charge of parsing sniffed packets and
 //! inserting them in the shared map.
 
+use std::io::ErrorKind;
 use std::sync::{Arc, Mutex};
 use std::thread;
 
-use etherparse::PacketHeaders;
-use pcap::{Active, Capture};
+use etherparse::{PacketHeaders, ReadError};
+use pcap::{Active, Capture, Packet};
 
 use crate::mmdb::types::mmdb_reader::MmdbReader;
 use crate::networking::manage_packets::{
@@ -17,6 +18,7 @@ use crate::networking::types::filters::Filters;
 use crate::networking::types::icmp_type::IcmpType;
 use crate::networking::types::info_address_port_pair::InfoAddressPortPair;
 use crate::networking::types::my_device::MyDevice;
+use crate::networking::types::my_link_type::MyLinkType;
 use crate::networking::types::packet_filters_fields::PacketFiltersFields;
 use crate::InfoTraffic;
 
@@ -33,6 +35,8 @@ pub fn parse_packets(
 ) {
     let capture_id = *current_capture_id.lock().unwrap();
 
+    let my_link_type = MyLinkType::from_pcap_link_type(cap.get_datalink());
+
     loop {
         match cap.next_packet() {
             Err(_) => {
@@ -45,152 +49,193 @@ pub fn parse_packets(
                 if *current_capture_id.lock().unwrap() != capture_id {
                     return;
                 }
-                match PacketHeaders::from_ethernet_slice(&packet) {
-                    Err(_) => {
+                if let Ok(headers) = get_sniffable_headers(&packet, my_link_type) {
+                    let mut exchanged_bytes = 0;
+                    let mut mac_addresses = (None, None);
+                    let mut icmp_type = IcmpType::default();
+                    let mut packet_filters_fields = PacketFiltersFields::default();
+
+                    let key_option = analyze_headers(
+                        headers,
+                        &mut mac_addresses,
+                        &mut exchanged_bytes,
+                        &mut icmp_type,
+                        &mut packet_filters_fields,
+                    );
+                    if key_option.is_none() {
                         continue;
                     }
-                    Ok(headers) => {
-                        let mut exchanged_bytes = 0;
-                        let mut mac_addresses = (String::new(), String::new());
-                        let mut icmp_type = IcmpType::default();
-                        let mut packet_filters_fields = PacketFiltersFields::default();
-
-                        let key_option = analyze_headers(
-                            headers,
-                            &mut mac_addresses,
-                            &mut exchanged_bytes,
-                            &mut icmp_type,
-                            &mut packet_filters_fields,
-                        );
-                        if key_option.is_none() {
-                            continue;
-                        }
 
-                        let key = key_option.unwrap();
-                        let application_protocol = get_app_protocol(key.port1, key.port2);
-                        let mut new_info = InfoAddressPortPair::default();
-
-                        let passed_filters = filters.matches(&packet_filters_fields);
-                        if passed_filters {
-                            new_info = modify_or_insert_in_map(
-                                info_traffic_mutex,
-                                &key,
-                                device,
-                                mac_addresses,
-                                icmp_type,
-                                exchanged_bytes,
-                                application_protocol,
-                            );
-                        }
+                    let key = key_option.unwrap();
+                    let application_protocol = get_app_protocol(key.port1, key.port2);
+                    let mut new_info = InfoAddressPortPair::default();
 
-                        let mut info_traffic = info_traffic_mutex
-                            .lock()
-                            .expect("Error acquiring mutex\n\r");
-                        //increment number of sniffed packets and bytes
-                        info_traffic.all_packets += 1;
-                        info_traffic.all_bytes += exchanged_bytes;
-                        // update dropped packets number
-                        if let Ok(stats) = cap.stats() {
-                            info_traffic.dropped_packets = stats.dropped;
-                        }
+                    let passed_filters = filters.matches(&packet_filters_fields);
+                    if passed_filters {
+                        new_info = modify_or_insert_in_map(
+                            info_traffic_mutex,
+                            &key,
+                            device,
+                            mac_addresses,
+                            icmp_type,
+                            exchanged_bytes,
+                            application_protocol,
+                        );
+                    }
 
-                        if passed_filters {
-                            info_traffic.add_packet(exchanged_bytes, new_info.traffic_direction);
+                    let mut info_traffic = info_traffic_mutex
+                        .lock()
+                        .expect("Error acquiring mutex\n\r");
+                    //increment number of sniffed packets and bytes
+                    info_traffic.all_packets += 1;
+                    info_traffic.all_bytes += exchanged_bytes;
+                    // update dropped packets number
+                    if let Ok(stats) = cap.stats() {
+                        info_traffic.dropped_packets = stats.dropped;
+                    }
+
+                    if passed_filters {
+                        info_traffic.add_packet(exchanged_bytes, new_info.traffic_direction);
 
-                            // check the rDNS status of this address and act accordingly
-                            let address_to_lookup =
-                                get_address_to_lookup(&key, new_info.traffic_direction);
-                            let r_dns_already_resolved = info_traffic
-                                .addresses_resolved
+                        // check the rDNS status of this address and act accordingly
+                        let address_to_lookup =
+                            get_address_to_lookup(&key, new_info.traffic_direction);
+                        let r_dns_already_resolved = info_traffic
+                            .addresses_resolved
+                            .contains_key(&address_to_lookup);
+                        let mut r_dns_waiting_resolution = false;
+                        if !r_dns_already_resolved {
+                            r_dns_waiting_resolution = info_traffic
+                                .addresses_waiting_resolution
                                 .contains_key(&address_to_lookup);
-                            let mut r_dns_waiting_resolution = false;
-                            if !r_dns_already_resolved {
-                                r_dns_waiting_resolution = info_traffic
-                                    .addresses_waiting_resolution
-                                    .contains_key(&address_to_lookup);
-                            }
+                        }
 
-                            match (r_dns_waiting_resolution, r_dns_already_resolved) {
-                                (false, false) => {
-                                    // rDNS not requested yet (first occurrence of this address to lookup)
+                        match (r_dns_waiting_resolution, r_dns_already_resolved) {
+                            (false, false) => {
+                                // rDNS not requested yet (first occurrence of this address to lookup)
 
-                                    // Add this address to the map of addresses waiting for a resolution
-                                    // Useful to NOT perform again a rDNS lookup for this entry
-                                    info_traffic.addresses_waiting_resolution.insert(
-                                        address_to_lookup,
-                                        DataInfo::new_with_first_packet(
-                                            exchanged_bytes,
+                                // Add this address to the map of addresses waiting for a resolution
+                                // Useful to NOT perform again a rDNS lookup for this entry
+                                info_traffic.addresses_waiting_resolution.insert(
+                                    address_to_lookup,
+                                    DataInfo::new_with_first_packet(
+                                        exchanged_bytes,
+                                        new_info.traffic_direction,
+                                    ),
+                                );
+
+                                // launch new thread to resolve host name
+                                let key2 = key.clone();
+                                let info_traffic2 = info_traffic_mutex.clone();
+                                let device2 = device.clone();
+                                let country_db_reader_2 = country_mmdb_reader.clone();
+                                let asn_db_reader_2 = asn_mmdb_reader.clone();
+                                thread::Builder::new()
+                                    .name("thread_reverse_dns_lookup".to_string())
+                                    .spawn(move || {
+                                        reverse_dns_lookup(
+                                            &info_traffic2,
+                                            &key2,
                                             new_info.traffic_direction,
-                                        ),
-                                    );
-
-                                    // launch new thread to resolve host name
-                                    let key2 = key.clone();
-                                    let info_traffic2 = info_traffic_mutex.clone();
-                                    let device2 = device.clone();
-                                    let country_db_reader_2 = country_mmdb_reader.clone();
-                                    let asn_db_reader_2 = asn_mmdb_reader.clone();
-                                    thread::Builder::new()
-                                        .name("thread_reverse_dns_lookup".to_string())
-                                        .spawn(move || {
-                                            reverse_dns_lookup(
-                                                &info_traffic2,
-                                                &key2,
-                                                new_info.traffic_direction,
-                                                &device2,
-                                                &country_db_reader_2,
-                                                &asn_db_reader_2,
-                                            );
-                                        })
-                                        .unwrap();
-                                }
-                                (true, false) => {
-                                    // waiting for a previously requested rDNS resolution
-                                    // update the corresponding waiting address data
-                                    info_traffic
-                                        .addresses_waiting_resolution
-                                        .entry(address_to_lookup)
-                                        .and_modify(|data_info| {
-                                            data_info.add_packet(
-                                                exchanged_bytes,
-                                                new_info.traffic_direction,
-                                            );
-                                        });
-                                }
-                                (_, true) => {
-                                    // rDNS already resolved
-                                    // update the corresponding host's data info
-                                    let host = info_traffic
-                                        .addresses_resolved
-                                        .get(&address_to_lookup)
-                                        .unwrap()
-                                        .1
-                                        .clone();
-                                    info_traffic.hosts.entry(host).and_modify(|data_info_host| {
-                                        data_info_host.data_info.add_packet(
+                                            &device2,
+                                            &country_db_reader_2,
+                                            &asn_db_reader_2,
+                                        );
+                                    })
+                                    .unwrap();
+                            }
+                            (true, false) => {
+                                // waiting for a previously requested rDNS resolution
+                                // update the corresponding waiting address data
+                                info_traffic
+                                    .addresses_waiting_resolution
+                                    .entry(address_to_lookup)
+                                    .and_modify(|data_info| {
+                                        data_info.add_packet(
                                             exchanged_bytes,
                                             new_info.traffic_direction,
                                         );
                                     });
-                                }
                             }
-
-                            //increment the packet count for the sniffed app protocol
-                            info_traffic
-                                .app_protocols
-                                .entry(application_protocol)
-                                .and_modify(|data_info| {
-                                    data_info
+                            (_, true) => {
+                                // rDNS already resolved
+                                // update the corresponding host's data info
+                                let host = info_traffic
+                                    .addresses_resolved
+                                    .get(&address_to_lookup)
+                                    .unwrap()
+                                    .1
+                                    .clone();
+                                info_traffic.hosts.entry(host).and_modify(|data_info_host| {
+                                    data_info_host
+                                        .data_info
                                         .add_packet(exchanged_bytes, new_info.traffic_direction);
-                                })
-                                .or_insert(DataInfo::new_with_first_packet(
-                                    exchanged_bytes,
-                                    new_info.traffic_direction,
-                                ));
+                                });
+                            }
                         }
+
+                        //increment the packet count for the sniffed app protocol
+                        info_traffic
+                            .app_protocols
+                            .entry(application_protocol)
+                            .and_modify(|data_info| {
+                                data_info.add_packet(exchanged_bytes, new_info.traffic_direction);
+                            })
+                            .or_insert(DataInfo::new_with_first_packet(
+                                exchanged_bytes,
+                                new_info.traffic_direction,
+                            ));
                     }
                 }
             }
         }
     }
 }
+
+fn get_sniffable_headers<'a>(
+    packet: &'a Packet,
+    my_link_type: MyLinkType,
+) -> Result<PacketHeaders<'a>, ReadError> {
+    match my_link_type {
+        MyLinkType::Ethernet(_) => PacketHeaders::from_ethernet_slice(packet),
+        MyLinkType::RawIp(_) | MyLinkType::IPv4(_) | MyLinkType::IPv6(_) => {
+            PacketHeaders::from_ip_slice(packet)
+        }
+        MyLinkType::Null(_) | MyLinkType::Loop(_) => from_null_slice(packet),
+        MyLinkType::Unsupported(_) | MyLinkType::NotYetAssigned => {
+            PacketHeaders::from_ethernet_slice(packet)
+        }
+    }
+}
+
+fn from_null_slice(packet: &[u8]) -> Result<PacketHeaders, ReadError> {
+    if packet.len() <= 4 {
+        return Err(ReadError::UnexpectedEndOfSlice(packet.len()));
+    }
+
+    let is_valid_af_inet = {
+        // based on https://wiki.wireshark.org/NullLoopback.md (2023-12-31)
+        fn matches(value: u32) -> bool {
+            match value {
+                // 2 = IPv4 on all platforms
+                // 24, 28, or 30 = IPv6 depending on platform
+                2 | 24 | 28 | 30 => true,
+                _ => false,
+            }
+        }
+        let h = &packet[..4];
+        let b = [h[0], h[1], h[2], h[3]];
+        // check both big endian and little endian representations
+        // as some OS'es use native endianess and others use big endian
+        matches(u32::from_le_bytes(b)) || matches(u32::from_be_bytes(b))
+    };
+
+    if is_valid_af_inet {
+        PacketHeaders::from_ip_slice(&packet[4..])
+    } else {
+        Err(ReadError::IoError(std::io::Error::new(
+            ErrorKind::InvalidData,
+            "Invalid AF_INET / AF_INET6 value",
+        )))
+    }
+}
diff --git a/src/translations/translations.rs b/src/translations/translations.rs
index 31d0a3ba4..361047d2f 100644
--- a/src/translations/translations.rs
+++ b/src/translations/translations.rs
@@ -451,63 +451,64 @@ pub fn no_addresses_translation(
     language: Language,
     adapter: &str,
 ) -> Text<'static, Renderer<StyleType>> {
+    let network_adapter_translation = network_adapter_translation(language);
     Text::new(match language {
         Language::EN => format!("No traffic can be observed because the adapter you selected has no active addresses...\n\n\
-                                 Network adapter: {adapter}\n\n\
+                                 {network_adapter_translation}: {adapter}\n\n\
                                  If you are sure you are connected to the internet, try choosing a different adapter."),
         Language::IT => format!("Non è osservabile alcun traffico perché l'adattatore di rete selezionato non ha indirizzi attivi...\n\n\
-                                Adattatore di rete: {adapter}\n\n\
+                                {network_adapter_translation}: {adapter}\n\n\
                                 Se sei sicuro di essere connesso ad internet, prova a scegliere un adattatore diverso."),
         Language::FR => format!("Aucun trafic ne peut être observé, car la carte réseau que vous avez saisie n'a pas d'adresse...\n\n\
-                                Carte réseau : {adapter}\n\n\
+                                {network_adapter_translation} : {adapter}\n\n\
                                 Si vous êtes sûr d'être connecté à internet, essayez une autre carte."),
         Language::ES => format!("No se puede observar ningún tráfico porque el adaptador seleccionado no tiene direcciones activas...\n\n\
-                                 Adaptador de red : {adapter}\n\n\
+                                 {network_adapter_translation} : {adapter}\n\n\
                                  Si estás seguro de que estás conectado a Internet, prueba a elegir otro adaptador."),
         Language::PL => format!("Nie można zaobserwować żadnego ruchu, ponieważ wybrany adapter nie ma aktywnych adresów...\n\n\
-                                 Adapter sieciowy: {adapter}\n\n\
+                                 {network_adapter_translation}: {adapter}\n\n\
                                  Jeśli jesteś pewien, że jesteś podłączony do internetu, spróbuj wybrać inny adapter."),
         Language::DE => format!("Es kann kein Netzwerkverkehr beobachtet werden, weil der Adapter keine aktiven Adressen hat...\n\n\
-                                 Netzwerkadapter: {adapter}\n\n\
+                                 {network_adapter_translation}: {adapter}\n\n\
                                  Wenn du dir sicher bist, dass du mit dem Internet verbunden bist, probier einen anderen Adapter auszuwählen."),
         Language::UK => format!("Не зафіксовано жодного мережевого трафіку тому що вибраний адаптер немає активних адрес... \n\n\
-                                 Мережквий адаптер: {adapter}\n\n\
+                                 {network_adapter_translation}: {adapter}\n\n\
                                  Якщо Ти впевнений, що підключений до інтернету, спробуй вибрати інший адаптер."),
         Language::ZH => format!("您选择的网络适配器当前无活动网络...\n\n\
-                                网络适配器: {adapter}\n\n\
+                                {network_adapter_translation}: {adapter}\n\n\
                                 如果您确信您已成功连接互联网, 请尝试选择其他网络适配器."),
         Language::RO => format!("Niciun trafic nu poate fi observat deoarece adaptorul selectat nu are adrese active...\n\n\
-                                Adaptor de rețea: {adapter}\n\n\
+                                {network_adapter_translation}: {adapter}\n\n\
                                 Dacă sunteți sigur că sunteți conectat la internet, încercați să alegeți un alt adaptor."),
         Language::KO => format!("선택한 어댑터에 유효한 주소가 없기 때문에 트래픽을 확인할 수 없습니다...\n\n\
-                                네트워크 어뎁터: {adapter}\n\n\
+                                {network_adapter_translation}: {adapter}\n\n\
                                 인터넷이 연결되어있다면 다른 어댑터로 시도해보세요."),
         Language::TR => format!("Seçtiğiniz adaptör aktif bir adrese sahip olmadığı için hiç bir trafik izlenemez...\n\n\
-                                 Ağ adaptörü: {adapter}\n\n\
+                                 {network_adapter_translation}: {adapter}\n\n\
                                  Eğer gerçekten internete bağlı olduğunuza eminseniz, başka bir adaptör seçmeyi deneyiniz."),
         Language::RU => format!("Наблюдение за трафиком не возможно, потому что Вы выбрали интерфейс без активного адреса...\n\n\
-                                 Сетевой интерфейс: {adapter}\n\n\
+                                 {network_adapter_translation}: {adapter}\n\n\
                                  Если Вы уверены, что подключены к Интернету, попробуйте выбрать другой интерфейс."),
         Language::PT => format!("Não é possível observar tráfego porque o adaptador que selecionou não tem endereços ativos...\n\n\
-                                Adaptador de rede: {adapter}\n\n\
+                                {network_adapter_translation}: {adapter}\n\n\
                                 Se tiver a certeza que está ligado à internet, tente escolher um adaptador diferente."),
         Language::EL => format!("Δεν μπορεί να ανιχνευθεί κίνηση επειδή ο προσαρμογέας που επέλεξες δεν έχει ενεργές διευθύνσεις...\n\n\
-                                 Προσαρμογέας δικτύου: {adapter}\n\n\
+                                 {network_adapter_translation}: {adapter}\n\n\
                                  Αν είσαι σίγουρος ότι είσαι συνδεδεμένος στο διαδίκτυο, δοκίμασε αν επιλέξεις έναν διαφορετικό προσαρμογέα."),
         // Language::FA => format!("هیچ آمد و شدی قابل مشاهده نیست چون مبدلی که انتخاب کرده اید هیچ نشانی فعالی ندارد...\n\n\
         //                         مبدل شبکه: {adapter}\n\n\
         //                         اگر مطمئن هستید به اینترنت وصل هستید، سعی کنید مبدل متفاوتی را انتخاب کنید."),
         Language::SV => format!("Det går inte att observa någon trafik eftersom den valda adaptern inte har några aktiva adresser ...\n\n\
-                                 Nätverksadapter: {adapter}\n\n\
+                                 {network_adapter_translation}: {adapter}\n\n\
                                  Om du är säker att du är ansluten till internet, testa att välja en annan adapter."),
         Language::FI => format!("Liikennettä ei voitu havainnoida, koska valitulla sovittimella ei ole aktiivista osoitetta...\n\n\
-                                 Verkkosovitin: {adapter}\n\n\
+                                 {network_adapter_translation}: {adapter}\n\n\
                                  Jos olet varma että sinulla on internet-yhteys, kokeile valita toinen verkkosovitin."),
         Language::JA => format!("選択されたアダプターが有効なアドレスを持っていないため、トラフィックを観測できていません...\n\n\
-                                ネットワーク アダプター: {adapter}\n\n\
+                                {network_adapter_translation}: {adapter}\n\n\
                                 インターネットに接続しているか確認し、別のネットワーク アダプターを試してください。"),
         Language::UZ => format!("Trafik kuzatilmaydi, chunki siz tanlagan adapterda faol manzillar yo'q...\n\n\
-                                Tarmoq adapteri: {adapter}\n\n\
+                                {network_adapter_translation}: {adapter}\n\n\
                                 Internetga ulanganingizga ishonchingiz komil bo'lsa, boshqa adapterni tanlashga harakat qiling"),
     })
 }
@@ -516,64 +517,65 @@ pub fn waiting_translation(
     language: Language,
     adapter: &str,
 ) -> Text<'static, Renderer<StyleType>> {
+    let network_adapter_translation = network_adapter_translation(language);
     Text::new(match language {
         Language::EN => format!("No traffic has been observed yet. Waiting for network packets...\n\n\
-                                 Network adapter: {adapter}\n\n\
+                                 {network_adapter_translation}: {adapter}\n\n\
                                  Are you sure you are connected to the internet and you have selected the correct adapter?"),
         Language::IT => format!("Nessun tipo di traffico è stato osservato finora. Attendo pacchetti di rete...\n\n\
-                                Adattatore di rete: {adapter}\n\n\
+                                {network_adapter_translation}: {adapter}\n\n\
                                 Sei sicuro di esser connesso ad internet e di aver selezionato l'adattatore corretto?"),
         Language::FR => format!("Aucun trafic n'a été capturé pour le moment. En attente de paquets...\n\n\
-                                Carte réseau : {adapter}\n\n\
+                                {network_adapter_translation} : {adapter}\n\n\
                                 Êtes-vous sûr d'être connecté à internet et d'avoir selectionné la bonne carte réseau ?"),
         Language::ES => format!("Aún no se ha captado tráfico. Esperando paquetes...\n\n\
-                                 Adaptador de red : {adapter}\n\n\
+                                 {network_adapter_translation} : {adapter}\n\n\
                                  ¿Está seguro de que está conectado a Internet y ha seleccionado la tarjeta de red correcta?"),
         Language::PL => format!("Nie zaobserowano żadnego ruchu sieciowego. Oczekiwanie na pakiety...\n\n\
-                                 Adapter sieciowy: {adapter}\n\n\
+                                 {network_adapter_translation}: {adapter}\n\n\
                                  Czy na pewno jesteś podłączony do internetu i wybrałeś właściwy adapter?"),
         Language::DE => format!("Noch kein Netzwerkverkehr beobachtet. Warte auf Pakete...\n\n\
-                                 Netzwerkadapter: {adapter}\n\n\
+                                 {network_adapter_translation}: {adapter}\n\n\
                                  Bist du sicher, dass du mit dem Internet verbunden bist und den richtigen Adapter ausgewählt hast?"),
         Language::UK => format!("Не зафіксовано жодного мережевого трафіку. Очікування на пакети...\n\n\
-                                 Мережквий адаптер: {adapter}\n\n\
+                                 {network_adapter_translation}: {adapter}\n\n\
                                  Чи Ти дійсно підключений до інтернету і вибрав відповідний мережевий адаптер?"),
         Language::ZH => format!("暂无流量数据. 等待网络活动中......\n\n\
-                                 网络适配器: {adapter}\n\n\
+                                 {network_adapter_translation}: {adapter}\n\n\
                                  您确信您已成功连接到互联网, 并选择了当前正在使用的的网络适配器吗?"),
         Language::RO => format!("Nu a fost observat încă trafic. Se așteaptă pachetele de rețea...\n\n\
-                                Adaptor de rețea: {adapter}\n\n\
+                                {network_adapter_translation}: {adapter}\n\n\
                                 Ești sigur că ești conectat la internet și ai selectat adaptorul corect?"),
         Language::KO => format!("아직 트래픽이 관찰되지 않았습니다. 네트워크 패킷 대기 중...\n\n\
-                                네트워크 어뎁터: {adapter}\n\n\
+                                {network_adapter_translation}: {adapter}\n\n\
                                 인터넷에 연결되어 있고 올바른 어댑터를 선택하셨습니까?"),
         Language::TR => format!("Henüz bir trafik algılanamadı. Ağ paketleri için bekleniyor...\n\n\
-                                 Ağ adaptörü: {adapter}\n\n\
+                                 {network_adapter_translation}: {adapter}\n\n\
                                  İnternete bağlı olduğunuza ve doğru adaptörü seçtiğinize emin misiniz?"),
         Language::RU => format!("Трафик не обнаружен. Ожидаем сетевые пакеты...\n\n\
-                                 Сетевой интерфейс: {adapter}\n\n\
+                                 {network_adapter_translation}: {adapter}\n\n\
                                  Вы уверены, что подключены к Интернету и выбрали правильный интерфейс?"),
         Language::PT => format!("Ainda não foi observado tráfego. Aguardando por pacotes...\n\n\
-                                Adaptador de rede: {adapter}\n\n\
+                                {network_adapter_translation}: {adapter}\n\n\
                                 Tem a certeza de que está ligado à internet e selecionou o adaptador correto?"),
         Language::EL => format!("Δεν έχει παρατηρηθεί κίνηση μέχρι στιγμής. Ανέμενε για πακέτα δικτύου...\n\n\
-                                 Προσαρμογέας δικτύου: {adapter}\n\n\
+                                 {network_adapter_translation}: {adapter}\n\n\
                                  Είσαι σίγουρος ότι είσαι συνδεδεμένος στο διαδίκτυο και ότι έχεις επιλέξει τον σωστό προσαρμογέα;"),
         // Language::FA => format!("هنوز هیچ آمد و شدی مشاهده نشده است. در حال انتظار برای بسته های شبکه...\n\n
         //                         مبدل شبکه: {adapter}\n\n
         //                         آیا مطمئن هستید به اینترنت وصل هستید و مبدل درست را انتخاب کرده اید؟"),
         Language::SV => format!("Ingen trafik har observerats ännu. Väntar på paket ...\n\n\
-                                 Nätverksadapter: {adapter}\n\n\
+                                 {network_adapter_translation}: {adapter}\n\n\
                                  Är du säker på att du är ansluten till internet och att du har valt rätt adapter?"),
         Language::FI => format!("Ei vielä havaittua liikennettä. Odotetaan verkkopaketteja...\n\n\
-                                 Verkkosovitin: {adapter}\n\n\
+                                 {network_adapter_translation}: {adapter}\n\n\
                                  Onhan sinulla varmasti internet-yhteys ja olet valinnut oikean verkkosovittimen."),
         Language::JA => format!("トラフィックがまだ観測できていません。ネットワーク パケットを待っています...\n\n\
-                                 ネットワーク アダプター: {adapter}\n\n\
+                                 {network_adapter_translation}: {adapter}\n\n\
                                  インターネットに接続していて、正しいアダプターを選択していますか?"),
         Language::UZ => format!(
             "Hali hech qanday trafik aniqlanmadi. Tarmoq paketlari kutilmoqda...\n\n\
-            Tarmoq adapteri: {adapter}\n\n\
+            {network_adapter_translation}: {adapter}\n\n\
             Internetga ulanganingizga va to'g'ri adapterni tanlaganingizga ishonchingiz komilmi?"),
     })
 }
diff --git a/src/translations/translations_3.rs b/src/translations/translations_3.rs
index 77d6041e4..163af584f 100644
--- a/src/translations/translations_3.rs
+++ b/src/translations/translations_3.rs
@@ -1,6 +1,10 @@
 #![allow(clippy::match_same_arms)]
 
-use crate::Language;
+use iced::widget::Text;
+use iced::Renderer;
+
+use crate::translations::translations::network_adapter_translation;
+use crate::{Language, StyleType};
 
 // This is referred to settings (General settings)
 pub fn general_translation(language: Language) -> &'static str {
@@ -81,3 +85,26 @@ pub fn messages_translation(language: Language) -> &'static str {
         _ => "Messages",
     }
 }
+
+pub fn link_type_translation(language: Language) -> &'static str {
+    match language {
+        Language::EN => "Link type",
+        Language::IT => "Tipo di collegamento",
+        _ => "Link type",
+    }
+}
+
+pub fn unsupported_link_type_translation(
+    language: Language,
+    adapter: &str,
+) -> Text<'static, Renderer<StyleType>> {
+    let mut string = match language {
+        Language::EN => "The link type associated with this adapter is not supported by Sniffnet yet...",
+        Language::IT => "Il tipo di collegamento associato a questo adattatore di rete non è ancora supportato da Sniffnet...",
+        _ => "The link type associated with this adapter is not supported by Sniffnet yet...",
+    }.to_string();
+
+    let network_adapter_translation = network_adapter_translation(language);
+    string.push_str(&format!("\n\n{network_adapter_translation}: {adapter}"));
+    Text::new(string)
+}


Test patch: