Skip to main content

zond_engine/system/interface/
resolve.rs

1use crate::{info, warn};
2// Copyright (c) 2026 Erik Lening (hollowpointer) and Contributors
3//
4// This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
5// If a copy of the MPL was not distributed with this file, You can obtain one at
6// https://mozilla.org/MPL/2.0/.
7
8use std::{net::Ipv4Addr, sync::atomic::Ordering};
9
10use crate::core::models::ip::range::IpRange;
11use crate::core::{
12    models::ip::{
13        range::{IpError, Ipv4Range},
14        set::IpSet,
15    },
16    parse::{IS_LAN_SCAN, IpParseError, ip::Keyword},
17};
18use crate::system::interface;
19
20pub fn resolve(keyword: Keyword, ip_set: &mut IpSet) -> Result<(), IpParseError> {
21    match keyword {
22        Keyword::Lan => resolve_lan(ip_set),
23        Keyword::Vpn => Err(IpParseError::LanError(
24            "VPN resolution not implemented".into(),
25        )),
26    }
27}
28
29/// Dynamically resolves the host's primary LAN interface into an inclusive range.
30fn resolve_lan(set: &mut IpSet) -> Result<(), IpParseError> {
31    let net = interface::get_lan_network()
32        .map_err(|e| IpParseError::LanError(e.to_string()))?
33        .ok_or_else(|| IpParseError::LanError("No active network interface found".into()))?;
34
35    let start_u32 = u32::from(net.network()).saturating_add(1);
36    let end_u32 = u32::from(net.broadcast()).saturating_sub(1);
37
38    if start_u32 <= end_u32 {
39        IS_LAN_SCAN.store(true, Ordering::Relaxed);
40        let range = Ipv4Range::new(Ipv4Addr::from(start_u32), Ipv4Addr::from(end_u32)).map_err(
41            |e| match e {
42                IpError::InvalidRange(s, e) => IpParseError::InvalidRange(s, e),
43                _ => IpParseError::LanError("Invalid LAN range".into()),
44            },
45        )?;
46
47        info!(
48            verbosity = 1,
49            "Resolved LAN: {} - {}", range.start_addr, range.end_addr
50        );
51        set.insert_range(IpRange::V4(range));
52    } else {
53        warn!("Small subnet; scanning full network range.");
54        let range = Ipv4Range::new(net.network(), net.broadcast()).unwrap();
55        set.insert_range(IpRange::V4(range));
56    }
57
58    Ok(())
59}