use serde::{Deserialize, Serialize};
#[non_exhaustive]
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Network {
pub device: String,
pub ssid: String,
pub bssid: Option<String>,
pub strength: Option<u8>,
pub frequency: Option<u32>,
pub secured: bool,
pub is_psk: bool,
pub is_eap: bool,
pub is_hotspot: bool,
pub ip4_address: Option<String>,
pub ip6_address: Option<String>,
}
#[non_exhaustive]
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct NetworkInfo {
pub ssid: String,
pub bssid: String,
pub strength: u8,
pub freq: Option<u32>,
pub channel: Option<u16>,
pub mode: String,
pub rate_mbps: Option<u32>,
pub bars: String,
pub security: String,
pub status: String,
pub ip4_address: Option<String>,
pub ip6_address: Option<String>,
}
#[non_exhaustive]
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum EapMethod {
Peap,
Ttls,
}
#[non_exhaustive]
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Phase2 {
Mschapv2,
Pap,
}
#[non_exhaustive]
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct EapOptions {
pub identity: String,
pub password: String,
pub anonymous_identity: Option<String>,
pub domain_suffix_match: Option<String>,
pub ca_cert_path: Option<String>,
pub system_ca_certs: bool,
pub method: EapMethod,
pub phase2: Phase2,
}
impl Default for EapOptions {
fn default() -> Self {
Self {
identity: String::new(),
password: String::new(),
anonymous_identity: None,
domain_suffix_match: None,
ca_cert_path: None,
system_ca_certs: false,
method: EapMethod::Peap,
phase2: Phase2::Mschapv2,
}
}
}
impl EapOptions {
pub fn new(identity: impl Into<String>, password: impl Into<String>) -> Self {
Self {
identity: identity.into(),
password: password.into(),
..Default::default()
}
}
#[must_use]
pub fn builder() -> EapOptionsBuilder {
EapOptionsBuilder::default()
}
#[must_use]
pub fn with_anonymous_identity(mut self, anonymous_identity: impl Into<String>) -> Self {
self.anonymous_identity = Some(anonymous_identity.into());
self
}
#[must_use]
pub fn with_domain_suffix_match(mut self, domain: impl Into<String>) -> Self {
self.domain_suffix_match = Some(domain.into());
self
}
#[must_use]
pub fn with_ca_cert_path(mut self, path: impl Into<String>) -> Self {
self.ca_cert_path = Some(path.into());
self
}
#[must_use]
pub fn with_system_ca_certs(mut self, use_system: bool) -> Self {
self.system_ca_certs = use_system;
self
}
#[must_use]
pub fn with_method(mut self, method: EapMethod) -> Self {
self.method = method;
self
}
#[must_use]
pub fn with_phase2(mut self, phase2: Phase2) -> Self {
self.phase2 = phase2;
self
}
}
#[derive(Debug, Default)]
pub struct EapOptionsBuilder {
identity: Option<String>,
password: Option<String>,
anonymous_identity: Option<String>,
domain_suffix_match: Option<String>,
ca_cert_path: Option<String>,
system_ca_certs: bool,
method: Option<EapMethod>,
phase2: Option<Phase2>,
}
impl EapOptionsBuilder {
#[must_use]
pub fn identity(mut self, identity: impl Into<String>) -> Self {
self.identity = Some(identity.into());
self
}
#[must_use]
pub fn password(mut self, password: impl Into<String>) -> Self {
self.password = Some(password.into());
self
}
#[must_use]
pub fn anonymous_identity(mut self, anonymous_identity: impl Into<String>) -> Self {
self.anonymous_identity = Some(anonymous_identity.into());
self
}
#[must_use]
pub fn domain_suffix_match(mut self, domain: impl Into<String>) -> Self {
self.domain_suffix_match = Some(domain.into());
self
}
#[must_use]
pub fn ca_cert_path(mut self, path: impl Into<String>) -> Self {
self.ca_cert_path = Some(path.into());
self
}
#[must_use]
pub fn system_ca_certs(mut self, use_system: bool) -> Self {
self.system_ca_certs = use_system;
self
}
#[must_use]
pub fn method(mut self, method: EapMethod) -> Self {
self.method = Some(method);
self
}
#[must_use]
pub fn phase2(mut self, phase2: Phase2) -> Self {
self.phase2 = Some(phase2);
self
}
#[must_use]
pub fn build(self) -> EapOptions {
EapOptions {
identity: self
.identity
.expect("identity is required (use .identity())"),
password: self
.password
.expect("password is required (use .password())"),
anonymous_identity: self.anonymous_identity,
domain_suffix_match: self.domain_suffix_match,
ca_cert_path: self.ca_cert_path,
system_ca_certs: self.system_ca_certs,
method: self.method.expect("method is required (use .method())"),
phase2: self.phase2.expect("phase2 is required (use .phase2())"),
}
}
}
#[non_exhaustive]
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum WifiSecurity {
Open,
WpaPsk {
psk: String,
},
WpaEap {
opts: EapOptions,
},
}
impl WifiSecurity {
#[must_use]
pub fn secured(&self) -> bool {
!matches!(self, WifiSecurity::Open)
}
#[must_use]
pub fn is_psk(&self) -> bool {
matches!(self, WifiSecurity::WpaPsk { .. })
}
#[must_use]
pub fn is_eap(&self) -> bool {
matches!(self, WifiSecurity::WpaEap { .. })
}
}
impl Network {
pub fn merge_ap(&mut self, other: &Network) {
if other.strength.unwrap_or(0) > self.strength.unwrap_or(0) {
self.strength = other.strength;
self.frequency = other.frequency;
self.bssid = other.bssid.clone();
}
self.secured |= other.secured;
self.is_psk |= other.is_psk;
self.is_eap |= other.is_eap;
self.is_hotspot |= other.is_hotspot;
}
}