diff --git a/protocols/mdns/CHANGELOG.md b/protocols/mdns/CHANGELOG.md index 33f9816ec0c..b75746c62b9 100644 --- a/protocols/mdns/CHANGELOG.md +++ b/protocols/mdns/CHANGELOG.md @@ -4,6 +4,10 @@ - Update to `libp2p-swarm` `v0.41.0`. +- Use `trust-dns-proto` to parse DNS messages. See [PR 3102]. + +[PR 3102]: https://github.com/libp2p/rust-libp2p/pull/3102 + # 0.41.0 - Remove default features. If you previously depended on `async-io` you need to enable this explicitly now. See [PR 2918]. diff --git a/protocols/mdns/Cargo.toml b/protocols/mdns/Cargo.toml index 5729043514e..78b3a26d67f 100644 --- a/protocols/mdns/Cargo.toml +++ b/protocols/mdns/Cargo.toml @@ -11,8 +11,8 @@ keywords = ["peer-to-peer", "libp2p", "networking"] categories = ["network-programming", "asynchronous"] [dependencies] +async-io = { version = "1.3.1", optional = true } data-encoding = "2.3.2" -dns-parser = "0.8.0" futures = "0.3.13" if-watch = "2.0.0" libp2p-core = { version = "0.38.0", path = "../../core" } @@ -21,10 +21,9 @@ log = "0.4.14" rand = "0.8.3" smallvec = "1.6.1" socket2 = { version = "0.4.0", features = ["all"] } -void = "1.0.2" - -async-io = { version = "1.3.1", optional = true } tokio = { version = "1.19", default-features = false, features = ["net", "time"], optional = true} +trust-dns-proto = { version = "0.22.0", default-features = false, features = ["mdns"] } +void = "1.0.2" [features] tokio = ["dep:tokio"] diff --git a/protocols/mdns/src/behaviour/iface/dns.rs b/protocols/mdns/src/behaviour/iface/dns.rs index 4590e1e266e..1f0825727a2 100644 --- a/protocols/mdns/src/behaviour/iface/dns.rs +++ b/protocols/mdns/src/behaviour/iface/dns.rs @@ -395,14 +395,14 @@ impl error::Error for MdnsResponseError {} #[cfg(test)] mod tests { use super::*; - use dns_parser::Packet; use libp2p_core::identity; use std::time::Duration; + use trust_dns_proto::op::Message; #[test] fn build_query_correct() { let query = build_query(); - assert!(Packet::parse(&query).is_ok()); + assert!(Message::from_vec(&query).is_ok()); } #[test] @@ -417,14 +417,14 @@ mod tests { Duration::from_secs(60), ); for packet in packets { - assert!(Packet::parse(&packet).is_ok()); + assert!(Message::from_vec(&packet).is_ok()); } } #[test] fn build_service_discovery_response_correct() { let query = build_service_discovery_response(0x1234, Duration::from_secs(120)); - assert!(Packet::parse(&query).is_ok()); + assert!(Message::from_vec(&query).is_ok()); } #[test] diff --git a/protocols/mdns/src/behaviour/iface/query.rs b/protocols/mdns/src/behaviour/iface/query.rs index 70e38016849..50b86bd888f 100644 --- a/protocols/mdns/src/behaviour/iface/query.rs +++ b/protocols/mdns/src/behaviour/iface/query.rs @@ -19,8 +19,7 @@ // DEALINGS IN THE SOFTWARE. use super::dns; -use crate::{META_QUERY_SERVICE, SERVICE_NAME}; -use dns_parser::{Packet, RData}; +use crate::{META_QUERY_SERVICE_FQDN, SERVICE_NAME_FQDN}; use libp2p_core::{ address_translation, multiaddr::{Multiaddr, Protocol}, @@ -28,6 +27,10 @@ use libp2p_core::{ }; use std::time::Instant; use std::{convert::TryFrom, fmt, net::SocketAddr, str, time::Duration}; +use trust_dns_proto::{ + op::Message, + rr::{Name, RData}, +}; /// A valid mDNS packet received by the service. #[derive(Debug)] @@ -44,33 +47,33 @@ impl MdnsPacket { pub fn new_from_bytes( buf: &[u8], from: SocketAddr, - ) -> Result, dns_parser::Error> { - let packet = Packet::parse(buf)?; + ) -> Result, trust_dns_proto::error::ProtoError> { + let packet = Message::from_vec(buf)?; - if !packet.header.query { - return Ok(Some(MdnsPacket::Response(MdnsResponse::new(packet, from)))); + if packet.query().is_none() { + return Ok(Some(MdnsPacket::Response(MdnsResponse::new(&packet, from)))); } if packet - .questions + .queries() .iter() - .any(|q| q.qname.to_string().as_bytes() == SERVICE_NAME) + .any(|q| q.name().to_utf8() == SERVICE_NAME_FQDN) { return Ok(Some(MdnsPacket::Query(MdnsQuery { from, - query_id: packet.header.id, + query_id: packet.header().id(), }))); } if packet - .questions + .queries() .iter() - .any(|q| q.qname.to_string().as_bytes() == META_QUERY_SERVICE) + .any(|q| q.name().to_utf8() == META_QUERY_SERVICE_FQDN) { // TODO: what if multiple questions, one with SERVICE_NAME and one with META_QUERY_SERVICE? return Ok(Some(MdnsPacket::ServiceDiscovery(MdnsServiceDiscovery { from, - query_id: packet.header.id, + query_id: packet.header().id(), }))); } @@ -144,21 +147,21 @@ pub struct MdnsResponse { impl MdnsResponse { /// Creates a new `MdnsResponse` based on the provided `Packet`. - pub fn new(packet: Packet<'_>, from: SocketAddr) -> MdnsResponse { + pub fn new(packet: &Message, from: SocketAddr) -> MdnsResponse { let peers = packet - .answers + .answers() .iter() .filter_map(|record| { - if record.name.to_string().as_bytes() != SERVICE_NAME { + if record.name().to_string() != SERVICE_NAME_FQDN { return None; } - let record_value = match record.data { - RData::PTR(record) => record.0.to_string(), + let record_value = match record.data() { + Some(RData::PTR(record)) => record, _ => return None, }; - MdnsPeer::new(&packet, record_value, record.ttl) + MdnsPeer::new(packet, record_value, record.ttl()) }) .collect(); @@ -225,17 +228,17 @@ pub struct MdnsPeer { impl MdnsPeer { /// Creates a new `MdnsPeer` based on the provided `Packet`. - pub fn new(packet: &Packet<'_>, record_value: String, ttl: u32) -> Option { + pub fn new(packet: &Message, record_value: &Name, ttl: u32) -> Option { let mut my_peer_id: Option = None; let addrs = packet - .additional + .additionals() .iter() .filter_map(|add_record| { - if add_record.name.to_string() != record_value { + if add_record.name() != record_value { return None; } - if let RData::TXT(ref txt) = add_record.data { + if let Some(RData::TXT(ref txt)) = add_record.data() { Some(txt) } else { None @@ -337,16 +340,16 @@ mod tests { ); for bytes in packets { - let packet = Packet::parse(&bytes).expect("unable to parse packet"); + let packet = Message::from_vec(&bytes).expect("unable to parse packet"); let record_value = packet - .answers + .answers() .iter() .filter_map(|record| { - if record.name.to_string().as_bytes() != SERVICE_NAME { + if record.name().to_utf8() != SERVICE_NAME_FQDN { return None; } - let record_value = match record.data { - RData::PTR(record) => record.0.to_string(), + let record_value = match record.data() { + Some(RData::PTR(record)) => record, _ => return None, }; Some(record_value) diff --git a/protocols/mdns/src/lib.rs b/protocols/mdns/src/lib.rs index 298f48ea975..368582ecb7b 100644 --- a/protocols/mdns/src/lib.rs +++ b/protocols/mdns/src/lib.rs @@ -49,8 +49,12 @@ pub use crate::behaviour::TokioMdns; /// The DNS service name for all libp2p peers used to query for addresses. const SERVICE_NAME: &[u8] = b"_p2p._udp.local"; +/// `SERVICE_NAME` as a Fully Qualified Domain Name. +const SERVICE_NAME_FQDN: &str = "_p2p._udp.local."; /// The meta query for looking up the `SERVICE_NAME`. const META_QUERY_SERVICE: &[u8] = b"_services._dns-sd._udp.local"; +/// `META_QUERY_SERVICE` as a Fully Qualified Domain Name. +const META_QUERY_SERVICE_FQDN: &str = "_services._dns-sd._udp.local."; pub const IPV4_MDNS_MULTICAST_ADDRESS: Ipv4Addr = Ipv4Addr::new(224, 0, 0, 251); pub const IPV6_MDNS_MULTICAST_ADDRESS: Ipv6Addr = Ipv6Addr::new(0xFF02, 0, 0, 0, 0, 0, 0, 0xFB);