diff --git a/easytier/src/dns/node_mgr.rs b/easytier/src/dns/node_mgr.rs index 3136cdbd..699e8fcf 100644 --- a/easytier/src/dns/node_mgr.rs +++ b/easytier/src/dns/node_mgr.rs @@ -1,12 +1,12 @@ use crate::dns::config::DNS_NODE_TTI; use crate::dns::utils::addr::NameServerAddr; -use crate::utils::dirty::DirtyFlag; use crate::dns::zone::{Zone, ZoneGroup}; use crate::proto::dns::DnsNodeMgrRpc; use crate::proto::dns::{DnsSnapshot, HeartbeatRequest, HeartbeatResponse}; use crate::proto::rpc_types; use crate::proto::rpc_types::controller::BaseController; use crate::proto::utils::TransientDigest; +use crate::utils::dirty::DirtyFlag; use anyhow::Error; use hickory_server::zone_handler::Catalog; use itertools::Itertools; @@ -91,9 +91,11 @@ impl DnsNodeMgr { zones.push(Zone::system()); for forward in zones.iter_mut().flat_map(|z| &mut z.forward) { - forward - .name_servers - .retain(|ns| !local.contains(&ns.into())); + forward.name_servers.retain_mut(|ns| { + ns.connections + .retain(|c| !local.contains(&(ns.ip, c).into())); + !ns.connections.is_empty() + }); } zones.into() diff --git a/easytier/src/dns/peer_mgr.rs b/easytier/src/dns/peer_mgr.rs index e69b3d53..f33a94f3 100644 --- a/easytier/src/dns/peer_mgr.rs +++ b/easytier/src/dns/peer_mgr.rs @@ -1,7 +1,6 @@ use crate::common::PeerId; use crate::common::global_ctx::ArcGlobalCtx; use crate::dns::config::{DNS_PEER_TTI, DnsExportConfig, DnsGlobalCtxExt}; -use crate::utils::dirty::DirtyFlag; use crate::dns::zone::ZoneGroup; use crate::peer_center::instance::PeerCenterPeerManagerTrait; use crate::peers::peer_manager::PeerManager; @@ -13,6 +12,7 @@ use crate::proto::dns::{ use crate::proto::rpc_types; use crate::proto::rpc_types::controller::BaseController; use crate::proto::utils::TransientDigest; +use crate::utils::dirty::DirtyFlag; use anyhow::Context; use moka::future::Cache; use std::ops::Deref; diff --git a/easytier/src/dns/utils/addr.rs b/easytier/src/dns/utils/addr.rs index 5e938a15..77f744b0 100644 --- a/easytier/src/dns/utils/addr.rs +++ b/easytier/src/dns/utils/addr.rs @@ -2,14 +2,14 @@ use crate::proto; use crate::proto::utils::RepeatedMessageModel; use anyhow::{Error, anyhow}; use hickory_net::xfer::Protocol; -use hickory_resolver::config::{ConnectionConfig, NameServerConfig}; +use hickory_resolver::config::{ConnectionConfig, NameServerConfig, ProtocolConfig}; use serde::de::IntoDeserializer; use serde::{Deserialize, de}; use serde_with::{DeserializeFromStr, SerializeDisplay}; use std::fmt::{Display, Formatter}; use std::net::{IpAddr, SocketAddr}; use std::str::FromStr; -use url::{Host, Url}; +use url::Url; #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, SerializeDisplay, DeserializeFromStr)] pub struct NameServerAddr { @@ -29,22 +29,16 @@ impl From for NameServerConfig { } } -impl From<&NameServerConfig> for NameServerAddr { - fn from(value: &NameServerConfig) -> Self { - let connection = value.connections.first().unwrap(); +impl From<(IpAddr, &ConnectionConfig)> for NameServerAddr { + fn from(value: (IpAddr, &ConnectionConfig)) -> Self { + let (ip, config) = value; Self { - protocol: connection.protocol.to_protocol(), - addr: SocketAddr::new(value.ip, connection.port), + protocol: config.protocol.to_protocol(), + addr: SocketAddr::new(ip, config.port), } } } -impl From for NameServerAddr { - fn from(value: NameServerConfig) -> Self { - (&value).into() - } -} - impl From for NameServerAddr { fn from(value: SocketAddr) -> Self { Self { @@ -70,23 +64,23 @@ impl TryFrom<&Url> for NameServerAddr { type Error = Error; fn try_from(value: &Url) -> Result { - let protocol = Protocol::deserialize(value.scheme().into_deserializer()).map_err( + let protocol = match Protocol::deserialize(value.scheme().into_deserializer()).map_err( |e: de::value::Error| anyhow!("invalid protocol '{}': {}", value.scheme(), e), - )?; - let port = value - .port() - .or_else(|| matches!(protocol, Protocol::Udp | Protocol::Tcp).then_some(53)) - .ok_or_else(|| anyhow!("port not found"))?; - let ip = match value.host().ok_or(anyhow!("host not found"))? { - Host::Domain(_) => { - return Err(anyhow!("unsupported host: {}", value.host_str().unwrap())); - } - Host::Ipv4(ip) => ip.into(), - Host::Ipv6(ip) => ip.into(), + )? { + Protocol::Udp => ProtocolConfig::Udp, + Protocol::Tcp => ProtocolConfig::Tcp, + p => return Err(anyhow!("unsupported protocol: {}", p)), + }; + let host = value.host_str().ok_or(anyhow!("host not found"))?; + let port = value.port().unwrap_or(protocol.default_port()); + let addr = if let Ok(addr) = IpAddr::from_str(host) { + SocketAddr::new(addr, port) + } else { + return Err(anyhow!("invalid address: {}", host)); }; Ok(Self { - protocol, - addr: SocketAddr::new(ip, port), + protocol: protocol.to_protocol(), + addr, }) } } @@ -127,3 +121,13 @@ impl Display for NameServerAddr { } pub type NameServerAddrGroup = RepeatedMessageModel; + +impl From<&NameServerConfig> for NameServerAddrGroup { + fn from(value: &NameServerConfig) -> Self { + value + .connections + .iter() + .map(|c| (value.ip, c).into()) + .collect() + } +} diff --git a/easytier/src/dns/zone.rs b/easytier/src/dns/zone.rs index ac8c05aa..be3287c6 100644 --- a/easytier/src/dns/zone.rs +++ b/easytier/src/dns/zone.rs @@ -1,5 +1,5 @@ use crate::common::dns::get_default_resolver_config; -use crate::dns::utils::addr::NameServerAddr; +use crate::dns::utils::addr::{NameServerAddr, NameServerAddrGroup}; use crate::dns::utils::zone_handler::ArcZoneHandler; use crate::proto; use crate::proto::utils::RepeatedMessageModel; @@ -128,7 +128,8 @@ impl From for proto::dns::ZoneData { .forward .into_iter() .flat_map(|f| f.name_servers.into_iter()) - .map(Into::::into) + .map(|ns| (&ns).into()) + .flat_map(NameServerAddrGroup::into_iter) .map(Into::into) .collect(); diff --git a/easytier/src/utils/mod.rs b/easytier/src/utils/mod.rs index bf674887..1b7c07c7 100644 --- a/easytier/src/utils/mod.rs +++ b/easytier/src/utils/mod.rs @@ -1,7 +1,7 @@ +pub mod dirty; pub mod panic; pub mod string; pub mod task; -pub mod dirty; use std::net::{IpAddr, Ipv4Addr, SocketAddr, TcpListener}; use std::sync::{Arc, Weak};