netcore/traits.rs
1//! Layer 4 — capability traits.
2//!
3//! Backends implement the subset they can. The CLI holds them as trait
4//! objects (`Box<dyn Trait>`) so NetworkManager, netlink, or shell-out
5//! backends can be selected at runtime based on what's available.
6//!
7//! All traits are object-safe: no generics on methods, no `Self` returns,
8//! no async (we stay sync for a sub-100ms CLI).
9
10use std::net::{IpAddr, SocketAddr};
11use std::time::Duration;
12
13use url::Url;
14
15use crate::Result;
16use crate::connection::{Connection, ConnectionId};
17use crate::diag::{
18 CheckScope, FirewallBackend, FirewallVerdict, Health, PingOpts, ProbeCapabilities, TraceOpts,
19};
20use crate::dns::DnsResolution;
21use crate::link::{Addr, L4Proto, Link, Neighbor, Route, Socket};
22use crate::path::{
23 Egress, Hop, HttpProbeResult, Path, PingResult, Target, TcpProbeResult, TlsProbeResult,
24};
25use crate::service::{Flow, Service};
26
27/// Raw kernel-primitive inventory. Backends implementing this expose
28/// unfiltered data for `jip raw *`.
29pub trait InventoryRaw: Send + Sync {
30 /// Return all kernel-visible network interfaces.
31 fn links(&self) -> Result<Vec<Link>>;
32 /// Return all addresses, each paired with the ifindex they belong to.
33 fn addrs(&self) -> Result<Vec<(u32, Addr)>>;
34 /// Return all routing table entries.
35 fn routes(&self) -> Result<Vec<Route>>;
36 /// Return all ARP/ND neighbor table entries.
37 fn neighbors(&self) -> Result<Vec<Neighbor>>;
38 /// Return all open sockets (TCP + UDP, IPv4 + IPv6).
39 fn sockets(&self) -> Result<Vec<Socket>>;
40}
41
42/// Domain-level inventory. Composes primitives into [`Connection`] etc.,
43/// applies smart filtering (IPv6 collapse, APIPA, metadata IPs).
44pub trait Inventory: Send + Sync {
45 /// Return all user-facing network connections.
46 fn connections(&self) -> Result<Vec<Connection>>;
47 /// Return all listening services.
48 fn services(&self) -> Result<Vec<Service>>;
49 /// Return all established flows.
50 fn flows(&self) -> Result<Vec<Flow>>;
51 /// Which [`Egress`] would carry traffic to `dst` — wraps `ip route get`.
52 fn egress_for(&self, dst: IpAddr) -> Result<Egress>;
53}
54
55/// DNS resolution, per-link resolver discovery.
56pub trait Resolver: Send + Sync {
57 /// Resolve a hostname or IP string, returning the full resolution record.
58 fn resolve(&self, name: &str) -> Result<DnsResolution>;
59 /// Per-link resolvers (as reported by `resolvectl`). Falls back to the
60 /// stub list when per-link info is unavailable.
61 fn servers_for(&self, conn: &ConnectionId) -> Result<Vec<IpAddr>>;
62 /// The local stub resolver, typically `127.0.0.53` on systemd-resolved hosts.
63 fn stub_server(&self) -> Result<Option<IpAddr>>;
64}
65
66/// Active probes: ICMP, TCP connect, TLS handshake, HTTP HEAD, traceroute.
67pub trait Reachability: Send + Sync {
68 /// Send ICMP echo requests to `ip` according to `opts`.
69 fn ping(&self, ip: IpAddr, opts: PingOpts) -> Result<PingResult>;
70 /// Attempt a TCP three-way handshake to `sa` within `timeout`.
71 fn tcp_connect(&self, sa: SocketAddr, timeout: Duration) -> Result<TcpProbeResult>;
72 /// Perform a TLS handshake to `sa` with the given SNI within `timeout`.
73 fn tls_handshake(&self, sa: SocketAddr, sni: &str, timeout: Duration)
74 -> Result<TlsProbeResult>;
75 /// Issue an HTTP HEAD request to `url` within `timeout`.
76 fn http_head(&self, url: &Url, timeout: Duration) -> Result<HttpProbeResult>;
77 /// Run a traceroute to `ip` using `opts`.
78 fn trace(&self, ip: IpAddr, opts: TraceOpts) -> Result<Vec<Hop>>;
79 /// What this backend can actually do on this system.
80 fn capabilities(&self) -> ProbeCapabilities;
81}
82
83/// Firewall posture.
84pub trait Firewall: Send + Sync {
85 /// Determine the inbound firewall verdict for a given (port, proto) pair.
86 fn verdict_for_inbound(&self, port: u16, proto: L4Proto) -> Result<FirewallVerdict>;
87 /// Return which firewall tool this backend read from.
88 fn backend(&self) -> FirewallBackend;
89}
90
91/// Write operations on connections (requires NetworkManager or similar).
92pub trait Actions: Send + Sync {
93 /// Activate the connection identified by `id`.
94 fn prefer(&self, id: &ConnectionId) -> Result<()>;
95 /// Delete the connection profile identified by `id`.
96 fn forget(&self, id: &ConnectionId) -> Result<()>;
97 /// Deactivate and then reactivate the connection identified by `id`.
98 fn reconnect(&self, id: &ConnectionId) -> Result<()>;
99 /// Enable or disable autoconnect for the connection identified by `id`.
100 fn set_autoconnect(&self, id: &ConnectionId, on: bool) -> Result<()>;
101}
102
103/// Orchestrates the others into end-to-end health checks and path probes.
104pub trait Diagnostician: Send + Sync {
105 /// Run a layered health check at the given scope. Returns an overall
106 /// [`Health`] value with any [`Finding`](crate::diag::Finding)s.
107 fn check(&self, scope: CheckScope) -> Result<Health>;
108 /// Resolve the target, select egress, run probes, and return the full
109 /// [`Path`].
110 fn trace_path(&self, target: Target) -> Result<Path>;
111}