Repository: GyulyVGC/sniffnet (language: rust)

Issue:
Bogon tag (and detailed address type identification)
### Discussed in https://github.com/GyulyVGC/sniffnet/discussions/208

<div type='discussions-op-text'>

<sup>Originally posted by **nitefood** May 21, 2023</sup>
Just like for multicast addresses (which you already identify and tag accordingly), I'd like to suggest a _bogon_ tag, along with more detailed address type identification (e.g. RFC1918 private space, or RFC6598 CGN space), to get rid of many unnecessary "unknown location" occurrances.

For example, [these](https://github.com/nitefood/asn/blob/a19482aab9a024c7baa425fdd0b899fbd0bfcb09/asn#L556-L567) are some regex patterns I used for a similar purpose.</div>


Discussion / hints:
@nitefood I gave a more in depth look to your `asn` project and it does really cool stuff.
I'm looking forward to integrate in Sniffnet next major release some other features, such as IP reputation.
Thank you for such an inspiring resource 🙏 
@GyulyVGC you're welcome, I'm glad you like it! Keep up the great work :-)
@all-contributors please add @nitefood for ideas.
@GyulyVGC 

I've put up [a pull request](https://github.com/GyulyVGC/sniffnet/pull/222) to add @nitefood! :tada:
Hey @nitefood I'm about to implement this feature in Sniffnet.
It seems that your code is tagging bogon IPv4 addresses but not IPv6 ones. 
Any reason for this?

For reference, [here](https://ipinfo.io/bogon) I've found a list of the relevant bogon ranges, both IP v4 & v6.

Fix patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 0a73cf7b6..78c323b83 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,6 +2,9 @@
 
 All Sniffnet releases with the relative changes are documented in this file.
 
+## [UNRELEASED]
+- Identify and tag unassigned/reserved "bogon" IP addresses ([#678](https://github.com/GyulyVGC/sniffnet/pull/678) — fixes [#209](https://github.com/GyulyVGC/sniffnet/issues/209))
+
 ## [1.3.2] - 2025-01-06
 - Dropdown menus for network host filters ([#659](https://github.com/GyulyVGC/sniffnet/pull/659) — fixes [#354](https://github.com/GyulyVGC/sniffnet/issues/354))
 - Added CLI argument `--adapter [<NAME>]` to allow immediately starting the capture from a given network interface ([#643](https://github.com/GyulyVGC/sniffnet/pull/643) — fixes [#636](https://github.com/GyulyVGC/sniffnet/issues/636))
diff --git a/resources/countries_flags/4x3/zz-bogon.svg b/resources/countries_flags/4x3/zz-bogon.svg
new file mode 100644
index 000000000..65c95a2ab
--- /dev/null
+++ b/resources/countries_flags/4x3/zz-bogon.svg
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
+
+<svg
+        fill="#000000"
+        height="855"
+        width="1140"
+        version="1.1"
+        id="Layer_1"
+        viewBox="0 0 470.24995 352.6875"
+        xml:space="preserve"
+        xmlns="http://www.w3.org/2000/svg"
+        xmlns:svg="http://www.w3.org/2000/svg"><defs
+   id="defs1" />
+    <g
+            id="XMLID_509_"
+            transform="translate(70.124961,11.343741)">
+	<path
+            id="XMLID_510_"
+            d="m 65,330 h 200 c 8.284,0 15,-6.716 15,-15 V 145 c 0,-8.284 -6.716,-15 -15,-15 H 250 V 85 C 250,38.131 211.869,0 165,0 118.131,0 80,38.131 80,85 v 45 H 65 c -8.284,0 -15,6.716 -15,15 v 170 c 0,8.284 6.716,15 15,15 z M 180,234.986 V 255 c 0,8.284 -6.716,15 -15,15 -8.284,0 -15,-6.716 -15,-15 v -20.014 c -6.068,-4.565 -10,-11.824 -10,-19.986 0,-13.785 11.215,-25 25,-25 13.785,0 25,11.215 25,25 0,8.162 -3.932,15.421 -10,19.986 z M 110,85 c 0,-30.327 24.673,-55 55,-55 30.327,0 55,24.673 55,55 v 45 H 110 Z"/>
+</g>
+    <rect
+            style="font-variation-settings:'wght' 680;fill:#a0e8f0;fill-opacity:0;stroke:#000000;stroke-width:2.18086;stroke-opacity:0"
+            id="rect1"
+            width="468.06906"
+            height="350.50662"
+            x="1.09043"
+            y="1.09043"/></svg>
diff --git a/src/countries/country_utils.rs b/src/countries/country_utils.rs
index 39ac6ee8a..593947d87 100644
--- a/src/countries/country_utils.rs
+++ b/src/countries/country_utils.rs
@@ -6,16 +6,16 @@ use iced::Font;
 
 use crate::countries::flags_pictures::{
     AD, AE, AF, AG, AI, AL, AM, AO, AQ, AR, AS, AT, AU, AW, AX, AZ, BA, BB, BD, BE, BF, BG, BH, BI,
-    BJ, BM, BN, BO, BR, BROADCAST, BS, BT, BV, BW, BY, BZ, CA, CC, CD, CF, CG, CH, CI, CK, CL, CM,
-    CN, CO, COMPUTER, CR, CU, CV, CW, CX, CY, CZ, DE, DJ, DK, DM, DO, DZ, EC, EE, EG, EH, ER, ES,
-    ET, FI, FJ, FK, FLAGS_WIDTH_BIG, FLAGS_WIDTH_SMALL, FM, FO, FR, GA, GB, GD, GE, GG, GH, GI, GL,
-    GM, GN, GQ, GR, GS, GT, GU, GW, GY, HK, HN, HOME, HR, HT, HU, ID, IE, IL, IM, IN, IO, IQ, IR,
-    IS, IT, JE, JM, JO, JP, KE, KG, KH, KI, KM, KN, KP, KR, KW, KY, KZ, LA, LB, LC, LI, LK, LR, LS,
-    LT, LU, LV, LY, MA, MC, MD, ME, MG, MH, MK, ML, MM, MN, MO, MP, MR, MS, MT, MU, MULTICAST, MV,
-    MW, MX, MY, MZ, NA, NC, NE, NF, NG, NI, NL, NO, NP, NR, NU, NZ, OM, PA, PE, PF, PG, PH, PK, PL,
-    PN, PR, PS, PT, PW, PY, QA, RO, RS, RU, RW, SA, SB, SC, SD, SE, SG, SH, SI, SK, SL, SM, SN, SO,
-    SR, SS, ST, SV, SX, SY, SZ, TC, TD, TF, TG, TH, TJ, TK, TL, TM, TN, TO, TR, TT, TV, TW, TZ, UA,
-    UG, UNKNOWN, US, UY, UZ, VA, VC, VE, VG, VI, VN, VU, WS, YE, ZA, ZM, ZW,
+    BJ, BM, BN, BO, BOGON, BR, BROADCAST, BS, BT, BV, BW, BY, BZ, CA, CC, CD, CF, CG, CH, CI, CK,
+    CL, CM, CN, CO, COMPUTER, CR, CU, CV, CW, CX, CY, CZ, DE, DJ, DK, DM, DO, DZ, EC, EE, EG, EH,
+    ER, ES, ET, FI, FJ, FK, FLAGS_WIDTH_BIG, FLAGS_WIDTH_SMALL, FM, FO, FR, GA, GB, GD, GE, GG, GH,
+    GI, GL, GM, GN, GQ, GR, GS, GT, GU, GW, GY, HK, HN, HOME, HR, HT, HU, ID, IE, IL, IM, IN, IO,
+    IQ, IR, IS, IT, JE, JM, JO, JP, KE, KG, KH, KI, KM, KN, KP, KR, KW, KY, KZ, LA, LB, LC, LI, LK,
+    LR, LS, LT, LU, LV, LY, MA, MC, MD, ME, MG, MH, MK, ML, MM, MN, MO, MP, MR, MS, MT, MU,
+    MULTICAST, MV, MW, MX, MY, MZ, NA, NC, NE, NF, NG, NI, NL, NO, NP, NR, NU, NZ, OM, PA, PE, PF,
+    PG, PH, PK, PL, PN, PR, PS, PT, PW, PY, QA, RO, RS, RU, RW, SA, SB, SC, SD, SE, SG, SH, SI, SK,
+    SL, SM, SN, SO, SR, SS, ST, SV, SX, SY, SZ, TC, TD, TF, TG, TH, TJ, TK, TL, TM, TN, TO, TR, TT,
+    TV, TW, TZ, UA, UG, UNKNOWN, US, UY, UZ, VA, VC, VE, VG, VI, VN, VU, WS, YE, ZA, ZM, ZW,
 };
 use crate::countries::types::country::Country;
 use crate::gui::styles::container::ContainerType;
@@ -26,6 +26,7 @@ use crate::networking::types::traffic_type::TrafficType;
 use crate::translations::translations_2::{
     local_translation, unknown_translation, your_network_adapter_translation,
 };
+use crate::translations::translations_4::reserved_address_translation;
 use crate::{Language, StyleType};
 
 fn get_flag_from_country<'a>(
@@ -33,6 +34,7 @@ fn get_flag_from_country<'a>(
     width: f32,
     is_local: bool,
     is_loopback: bool,
+    is_bogon: Option<&str>,
     traffic_type: TrafficType,
     language: Language,
 ) -> (Svg<'a, StyleType>, String) {
@@ -287,19 +289,24 @@ fn get_flag_from_country<'a>(
         Country::ZW => ZW,
         Country::ZZ => {
             let (flag, new_tooltip) = if is_loopback {
-                (COMPUTER, your_network_adapter_translation(language))
+                (
+                    COMPUTER,
+                    your_network_adapter_translation(language).to_string(),
+                )
             } else if traffic_type.eq(&TrafficType::Multicast) {
-                (MULTICAST, "Multicast")
+                (MULTICAST, "Multicast".to_string())
             } else if traffic_type.eq(&TrafficType::Broadcast) {
-                (BROADCAST, "Broadcast")
+                (BROADCAST, "Broadcast".to_string())
             } else if is_local {
-                (HOME, local_translation(language))
+                (HOME, local_translation(language).to_string())
+            } else if let Some(bogon) = is_bogon {
+                (BOGON, reserved_address_translation(language, bogon))
             } else {
-                (UNKNOWN, unknown_translation(language))
+                (UNKNOWN, unknown_translation(language).to_string())
             };
 
             svg_style = SvgType::AdaptColor;
-            tooltip = new_tooltip.to_string();
+            tooltip = new_tooltip;
             flag
         }
     })))
@@ -324,12 +331,14 @@ pub fn get_flag_tooltip<'a>(
     };
     let is_local = host_info.is_local;
     let is_loopback = host_info.is_loopback;
+    let is_bogon = host_info.is_bogon;
     let traffic_type = host_info.traffic_type;
     let (content, tooltip) = get_flag_from_country(
         country,
         width,
         is_local,
         is_loopback,
+        is_bogon,
         traffic_type,
         language,
     );
@@ -358,31 +367,33 @@ pub fn get_flag_tooltip<'a>(
 pub fn get_computer_tooltip<'a>(
     is_my_address: bool,
     is_local: bool,
+    is_bogon: Option<&str>,
     traffic_type: TrafficType,
     language: Language,
     font: Font,
 ) -> Tooltip<'a, Message, StyleType> {
     let content = Svg::new(Handle::from_memory(Vec::from(
-        match (is_my_address, is_local, traffic_type) {
-            (true, _, _) => COMPUTER,
-            (false, _, TrafficType::Multicast) => MULTICAST,
-            (false, _, TrafficType::Broadcast) => BROADCAST,
-            (false, true, _) => HOME,
-            (false, false, TrafficType::Unicast) => UNKNOWN,
+        match (is_my_address, is_local, is_bogon, traffic_type) {
+            (true, _, _, _) => COMPUTER,
+            (false, _, _, TrafficType::Multicast) => MULTICAST,
+            (false, _, _, TrafficType::Broadcast) => BROADCAST,
+            (false, true, _, _) => HOME,
+            (false, false, Some(_), _) => BOGON,
+            (false, false, None, TrafficType::Unicast) => UNKNOWN,
         },
     )))
     .class(SvgType::AdaptColor)
     .width(FLAGS_WIDTH_BIG)
     .height(FLAGS_WIDTH_BIG * 0.75);
 
-    let tooltip = match (is_my_address, is_local, traffic_type) {
-        (true, _, _) => your_network_adapter_translation(language),
-        (false, _, TrafficType::Multicast) => "Multicast",
-        (false, _, TrafficType::Broadcast) => "Broadcast",
-        (false, true, _) => local_translation(language),
-        (false, false, TrafficType::Unicast) => unknown_translation(language),
-    }
-    .to_string();
+    let tooltip = match (is_my_address, is_local, is_bogon, traffic_type) {
+        (true, _, _, _) => your_network_adapter_translation(language).to_string(),
+        (false, _, _, TrafficType::Multicast) => "Multicast".to_string(),
+        (false, _, _, TrafficType::Broadcast) => "Broadcast".to_string(),
+        (false, true, _, _) => local_translation(language).to_string(),
+        (false, false, Some(t), _) => reserved_address_translation(language, t),
+        (false, false, None, TrafficType::Unicast) => unknown_translation(language).to_string(),
+    };
 
     Tooltip::new(
         content,
diff --git a/src/countries/flags_pictures.rs b/src/countries/flags_pictures.rs
index a1c579837..f13feced8 100644
--- a/src/countries/flags_pictures.rs
+++ b/src/countries/flags_pictures.rs
@@ -255,3 +255,4 @@ pub const MULTICAST: &[u8] = include_bytes!("../../resources/countries_flags/4x3
 pub const BROADCAST: &[u8] = include_bytes!("../../resources/countries_flags/4x3/zz-broadcast.svg");
 pub const UNKNOWN: &[u8] = include_bytes!("../../resources/countries_flags/4x3/zz-unknown.svg");
 pub const COMPUTER: &[u8] = include_bytes!("../../resources/countries_flags/4x3/zz-computer.svg");
+pub const BOGON: &[u8] = include_bytes!("../../resources/countries_flags/4x3/zz-bogon.svg");
diff --git a/src/gui/pages/connection_details_page.rs b/src/gui/pages/connection_details_page.rs
index d293bb5bb..840011dda 100644
--- a/src/gui/pages/connection_details_page.rs
+++ b/src/gui/pages/connection_details_page.rs
@@ -19,6 +19,7 @@ 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::bogon::is_bogon;
 use crate::networking::types::host::Host;
 use crate::networking::types::icmp_type::IcmpType;
 use crate::networking::types::info_address_port_pair::InfoAddressPortPair;
@@ -304,6 +305,7 @@ fn get_local_tooltip<'a>(
     get_computer_tooltip(
         is_my_address(local_address, my_interface_addresses),
         is_local_connection(local_address, my_interface_addresses),
+        is_bogon(local_address),
         get_traffic_type(
             if address_to_lookup.eq(&key.address1) {
                 &key.address2
diff --git a/src/networking/manage_packets.rs b/src/networking/manage_packets.rs
index 7f4576bd8..7f2a35f45 100644
--- a/src/networking/manage_packets.rs
+++ b/src/networking/manage_packets.rs
@@ -12,6 +12,7 @@ use crate::mmdb::asn::get_asn;
 use crate::mmdb::country::get_country;
 use crate::mmdb::types::mmdb_reader::MmdbReaders;
 use crate::networking::types::address_port_pair::AddressPortPair;
+use crate::networking::types::bogon::is_bogon;
 use crate::networking::types::data_info_host::DataInfoHost;
 use crate::networking::types::host::Host;
 use crate::networking::types::host_data_states::HostData;
@@ -320,6 +321,7 @@ pub fn reverse_dns_lookup(
     );
     let is_loopback = is_loopback(&address_to_lookup);
     let is_local = is_local_connection(&address_to_lookup, &my_interface_addresses);
+    let is_bogon = is_bogon(&address_to_lookup);
     let country = get_country(&address_to_lookup, &mmdb_readers.country);
     let asn = get_asn(&address_to_lookup, &mmdb_readers.asn);
     let r_dns = if let Ok(result) = lookup_result {
@@ -358,6 +360,7 @@ pub fn reverse_dns_lookup(
             is_favorite: false,
             is_loopback,
             is_local,
+            is_bogon,
             traffic_type,
         });
 
diff --git a/src/networking/types/bogon.rs b/src/networking/types/bogon.rs
new file mode 100644
index 000000000..a546ecbe8
--- /dev/null
+++ b/src/networking/types/bogon.rs
@@ -0,0 +1,284 @@
+use crate::networking::types::ip_collection::AddressCollection;
+use once_cell::sync::Lazy;
+use std::net::IpAddr;
+use std::str::FromStr;
+
+pub struct Bogon {
+    pub range: AddressCollection,
+    pub description: &'static str,
+}
+
+// IPv4 bogons
+
+static THIS_NETWORK: Lazy<Bogon> = Lazy::new(|| Bogon {
+    range: AddressCollection::new("0.0.0.0-0.255.255.255").unwrap(),
+    description: "\"this\" network",
+});
+
+static PRIVATE_USE: Lazy<Bogon> = Lazy::new(|| Bogon {
+    range: AddressCollection::new(
+        "10.0.0.0-10.255.255.255, 172.16.0.0-172.31.255.255, 192.168.0.0-192.168.255.255",
+    )
+    .unwrap(),
+    description: "private-use",
+});
+
+static CARRIER_GRADE: Lazy<Bogon> = Lazy::new(|| Bogon {
+    range: AddressCollection::new("100.64.0.0-100.127.255.255").unwrap(),
+    description: "carrier-grade NAT",
+});
+
+static LOOPBACK: Lazy<Bogon> = Lazy::new(|| Bogon {
+    range: AddressCollection::new("127.0.0.0-127.255.255.255").unwrap(),
+    description: "loopback",
+});
+
+static LINK_LOCAL: Lazy<Bogon> = Lazy::new(|| Bogon {
+    range: AddressCollection::new("169.254.0.0-169.254.255.255").unwrap(),
+    description: "link local",
+});
+
+static IETF_PROTOCOL: Lazy<Bogon> = Lazy::new(|| Bogon {
+    range: AddressCollection::new("192.0.0.0-192.0.0.255").unwrap(),
+    description: "IETF protocol assignments",
+});
+
+static TEST_NET_1: Lazy<Bogon> = Lazy::new(|| Bogon {
+    range: AddressCollection::new("192.0.2.0-192.0.2.255").unwrap(),
+    description: "TEST-NET-1",
+});
+
+static NETWORK_INTERCONNECT: Lazy<Bogon> = Lazy::new(|| Bogon {
+    range: AddressCollection::new("198.18.0.0-198.19.255.255").unwrap(),
+    description: "network interconnect device benchmark testing",
+});
+
+static TEST_NET_2: Lazy<Bogon> = Lazy::new(|| Bogon {
+    range: AddressCollection::new("198.51.100.0-198.51.100.255").unwrap(),
+    description: "TEST-NET-2",
+});
+
+static TEST_NET_3: Lazy<Bogon> = Lazy::new(|| Bogon {
+    range: AddressCollection::new("203.0.113.0-203.0.113.255").unwrap(),
+    description: "TEST-NET-3",
+});
+
+static FUTURE_USE: Lazy<Bogon> = Lazy::new(|| Bogon {
+    range: AddressCollection::new("240.0.0.0-255.255.255.255").unwrap(),
+    description: "future use",
+});
+
+// IPv6 bogons
+
+static NODE_SCOPE_UNSPECIFIED: Lazy<Bogon> = Lazy::new(|| Bogon {
+    range: AddressCollection::new("::").unwrap(),
+    description: "node-scope unicast unspecified",
+});
+
+static NODE_SCOPE_LOOPBACK: Lazy<Bogon> = Lazy::new(|| Bogon {
+    range: AddressCollection::new("::1").unwrap(),
+    description: "node-scope unicast loopback",
+});
+
+static IPV4_MAPPED: Lazy<Bogon> = Lazy::new(|| Bogon {
+    range: AddressCollection::new("::ffff:0.0.0.0-::ffff:255.255.255.255").unwrap(),
+    description: "IPv4-mapped",
+});
+
+static IPV4_COMPATIBLE: Lazy<Bogon> = Lazy::new(|| Bogon {
+    range: AddressCollection::new("::-::255.255.255.255").unwrap(),
+    description: "IPv4-compatible",
+});
+
+static REMOTELY_TRIGGERED: Lazy<Bogon> = Lazy::new(|| Bogon {
+    range: AddressCollection::new("100::-100::ffff:ffff:ffff:ffff").unwrap(),
+    description: "remotely triggered black hole",
+});
+
+static ORCHID: Lazy<Bogon> = Lazy::new(|| Bogon {
+    range: AddressCollection::new("2001:10::-2001:1f:ffff:ffff:ffff:ffff:ffff:ffff").unwrap(),
+    description: "ORCHID",
+});
+
+static DOCUMENTATION_PREFIX: Lazy<Bogon> = Lazy::new(|| {
+    Bogon {
+    range: AddressCollection::new("2001:db8::-2001:db8:ffff:ffff:ffff:ffff:ffff:ffff, 3fff::-3fff:fff:ffff:ffff:ffff:ffff:ffff:ffff")
+        .unwrap(),
+    description: "documentation prefix",
+}
+});
+
+static ULA: Lazy<Bogon> = Lazy::new(|| Bogon {
+    range: AddressCollection::new("fc00::-fdff:ffff:ffff:ffff:ffff:ffff:ffff:ffff").unwrap(),
+    description: "ULA",
+});
+
+static LINK_LOCAL_UNICAST: Lazy<Bogon> = Lazy::new(|| Bogon {
+    range: AddressCollection::new("fe80::-febf:ffff:ffff:ffff:ffff:ffff:ffff:ffff").unwrap(),
+    description: "link-local unicast",
+});
+
+static SITE_LOCAL_UNICAST: Lazy<Bogon> = Lazy::new(|| Bogon {
+    range: AddressCollection::new("fec0::-feff:ffff:ffff:ffff:ffff:ffff:ffff:ffff").unwrap(),
+    description: "site-local unicast",
+});
+
+// all bogons
+
+static BOGONS: Lazy<Vec<&'static Bogon>> = Lazy::new(|| {
+    vec![
+        &THIS_NETWORK,
+        &PRIVATE_USE,
+        &CARRIER_GRADE,
+        &LOOPBACK,
+        &LINK_LOCAL,
+        &IETF_PROTOCOL,
+        &TEST_NET_1,
+        &NETWORK_INTERCONNECT,
+        &TEST_NET_2,
+        &TEST_NET_3,
+        &FUTURE_USE,
+        &NODE_SCOPE_UNSPECIFIED,
+        &NODE_SCOPE_LOOPBACK,
+        &IPV4_MAPPED,
+        &IPV4_COMPATIBLE,
+        &REMOTELY_TRIGGERED,
+        &ORCHID,
+        &DOCUMENTATION_PREFIX,
+        &ULA,
+        &LINK_LOCAL_UNICAST,
+        &SITE_LOCAL_UNICAST,
+    ]
+});
+
+pub fn is_bogon(address: &str) -> Option<&'static str> {
+    let ip = IpAddr::from_str(address).ok()?;
+    for bogon in BOGONS.iter() {
+        if bogon.range.contains(&ip) {
+            return Some(bogon.description);
+        }
+    }
+    None
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+
+    #[test]
+    fn test_is_bogon_no() {
+        assert_eq!(is_bogon("8.8.8.8"), None);
+        assert_eq!(is_bogon("2001:4860:4860::8888"), None);
+    }
+
+    #[test]
+    fn test_is_bogon_this_network() {
+        assert_eq!(is_bogon("0.1.2.3"), Some("\"this\" network"));
+    }
+
+    #[test]
+    fn test_is_bogon_private_use_networks() {
+        assert_eq!(is_bogon("10.1.2.3"), Some("private-use"));
+        assert_eq!(is_bogon("172.22.2.3"), Some("private-use"));
+        assert_eq!(is_bogon("192.168.255.3"), Some("private-use"));
+    }
+
+    #[test]
+    fn test_is_bogon_carrier_grade() {
+        assert_eq!(is_bogon("100.99.2.1"), Some("carrier-grade NAT"));
+    }
+
+    #[test]
+    fn test_is_bogon_loopback() {
+        assert_eq!(is_bogon("127.99.2.1"), Some("loopback"));
+    }
+
+    #[test]
+    fn test_is_bogon_link_local() {
+        assert_eq!(is_bogon("169.254.0.0"), Some("link local"));
+    }
+
+    #[test]
+    fn test_is_bogon_ietf() {
+        assert_eq!(is_bogon("192.0.0.255"), Some("IETF protocol assignments"));
+    }
+
+    #[test]
+    fn test_is_bogon_test_net_1() {
+        assert_eq!(is_bogon("192.0.2.128"), Some("TEST-NET-1"));
+    }
+
+    #[test]
+    fn test_is_bogon_network_interconnect() {
+        assert_eq!(
+            is_bogon("198.18.2.128"),
+            Some("network interconnect device benchmark testing")
+        );
+    }
+
+    #[test]
+    fn test_is_bogon_test_net_2() {
+        assert_eq!(is_bogon("198.51.100.128"), Some("TEST-NET-2"));
+    }
+
+    #[test]
+    fn test_is_bogon_test_net_3() {
+        assert_eq!(is_bogon("203.0.113.128"), Some("TEST-NET-3"));
+    }
+
+    #[test]
+    fn test_is_bogon_future_use() {
+        assert_eq!(is_bogon("240.0.0.0"), Some("future use"));
+    }
+
+    #[test]
+    fn test_node_scope_unspecified() {
+        assert_eq!(is_bogon("::"), Some("node-scope unicast unspecified"));
+    }
+
+    #[test]
+    fn test_node_scope_loopback() {
+        assert_eq!(is_bogon("::1"), Some("node-scope unicast loopback"));
+    }
+
+    #[test]
+    fn test_ipv4_mapped() {
+        assert_eq!(is_bogon("::ffff:8.8.8.8"), Some("IPv4-mapped"));
+    }
+
+    #[test]
+    fn test_ipv4_compatible() {
+        assert_eq!(is_bogon("::8.8.8.8"), Some("IPv4-compatible"));
+    }
+
+    #[test]
+    fn test_remotely_triggered() {
+        assert_eq!(is_bogon("100::beef"), Some("remotely triggered black hole"));
+    }
+
+    #[test]
+    fn test_orchid() {
+        assert_eq!(is_bogon("2001:10::feed"), Some("ORCHID"));
+    }
+
+    #[test]
+    fn test_documentation_prefix() {
+        assert_eq!(is_bogon("2001:db8::fe90"), Some("documentation prefix"));
+        assert_eq!(is_bogon("3fff::"), Some("documentation prefix"));
+    }
+
+    #[test]
+    fn test_ula() {
+        assert_eq!(is_bogon("fdff::"), Some("ULA"));
+    }
+
+    #[test]
+    fn test_link_local_unicast() {
+        assert_eq!(is_bogon("feaf::"), Some("link-local unicast"));
+    }
+
+    #[test]
+    fn test_site_local_unicast() {
+        assert_eq!(is_bogon("feea::1"), Some("site-local unicast"));
+    }
+}
diff --git a/src/networking/types/data_info_host.rs b/src/networking/types/data_info_host.rs
index 5c052ac96..a8459b951 100644
--- a/src/networking/types/data_info_host.rs
+++ b/src/networking/types/data_info_host.rs
@@ -14,6 +14,8 @@ pub struct DataInfoHost {
     pub is_loopback: bool,
     /// Determine if the connection with this host is local
     pub is_local: bool,
+    /// Determine if the connection is with a bogon address
+    pub is_bogon: Option<&'static str>,
     /// Determine if the connection with this host is unicast, multicast, or broadcast
     pub traffic_type: TrafficType,
 }
diff --git a/src/networking/types/ip_collection.rs b/src/networking/types/ip_collection.rs
index e2dcfba33..687c47fe1 100644
--- a/src/networking/types/ip_collection.rs
+++ b/src/networking/types/ip_collection.rs
@@ -4,8 +4,8 @@ use std::str::FromStr;
 
 #[derive(Debug, Eq, PartialEq, Clone)]
 pub(crate) struct AddressCollection {
-    pub(crate) ips: Vec<IpAddr>,
-    pub(crate) ranges: Vec<RangeInclusive<IpAddr>>,
+    ips: Vec<IpAddr>,
+    ranges: Vec<RangeInclusive<IpAddr>>,
 }
 
 impl AddressCollection {
diff --git a/src/networking/types/mod.rs b/src/networking/types/mod.rs
index fe7dec598..93c87318a 100644
--- a/src/networking/types/mod.rs
+++ b/src/networking/types/mod.rs
@@ -1,5 +1,6 @@
 pub mod address_port_pair;
 pub mod asn;
+pub mod bogon;
 pub mod byte_multiple;
 pub mod capture_context;
 pub mod data_info;
diff --git a/src/translations/mod.rs b/src/translations/mod.rs
index 342693ceb..b55b49080 100644
--- a/src/translations/mod.rs
+++ b/src/translations/mod.rs
@@ -2,4 +2,5 @@
 pub mod translations;
 pub mod translations_2;
 pub mod translations_3;
+pub mod translations_4;
 pub mod types;
diff --git a/src/translations/translations_4.rs b/src/translations/translations_4.rs
new file mode 100644
index 000000000..8a1e7ac45
--- /dev/null
+++ b/src/translations/translations_4.rs
@@ -0,0 +1,11 @@
+#![allow(clippy::match_same_arms)]
+
+use crate::translations::types::language::Language;
+
+pub fn reserved_address_translation(language: Language, info: &str) -> String {
+    match language {
+        Language::EN => format!("Reserved address ({info})"),
+        Language::IT => format!("Indirizzo riservato ({info})"),
+        _ => format!("Reserved address ({info})"),
+    }
+}


Test patch: