diff --git a/src/dns_cache.rs b/src/dns_cache.rs index 83ac731..a2359aa 100644 --- a/src/dns_cache.rs +++ b/src/dns_cache.rs @@ -6,8 +6,7 @@ use crate::log::debug; use crate::{ dns_parser::{ - current_time_millis, split_sub_domain, DnsAddress, DnsPointer, DnsRecordBox, DnsSrv, - RR_TYPE_A, RR_TYPE_AAAA, RR_TYPE_NSEC, RR_TYPE_PTR, RR_TYPE_SRV, RR_TYPE_TXT, + current_time_millis, split_sub_domain, DnsAddress, DnsPointer, DnsRecordBox, DnsSrv, RRType, }, service_info::valid_two_addrs_on_intf, }; @@ -116,12 +115,12 @@ impl DnsCache { &mut self, instance: &str, expire_at: Option, - ) -> Vec<(String, u16)> { + ) -> Vec<(String, RRType)> { let Some(srv_vec) = self.srv.get_mut(instance) else { return Vec::new(); }; - let mut query_vec = vec![(instance.to_string(), RR_TYPE_SRV)]; + let mut query_vec = vec![(instance.to_string(), RRType::SRV)]; for srv in srv_vec { if let Some(new_expire) = expire_at { @@ -133,8 +132,8 @@ impl DnsCache { }; // Will verify addresses for the hostname. - query_vec.push((srv_record.host.clone(), RR_TYPE_A)); - query_vec.push((srv_record.host.clone(), RR_TYPE_AAAA)); + query_vec.push((srv_record.host.clone(), RRType::A)); + query_vec.push((srv_record.host.clone(), RRType::AAAA)); if let Some(new_expire) = expire_at { if let Some(addrs) = self.addr.get_mut(&srv_record.host) { @@ -164,7 +163,7 @@ impl DnsCache { // If it is PTR with subtype, store a mapping from the instance fullname // to the subtype in this cache. - if incoming.get_type() == RR_TYPE_PTR { + if incoming.get_type() == RRType::PTR { let (_, subtype_opt) = split_sub_domain(&entry_name); if let Some(subtype) = subtype_opt { if let Some(ptr) = incoming.any().downcast_ref::() { @@ -177,11 +176,11 @@ impl DnsCache { // get the existing records for the type. let record_vec = match incoming.get_type() { - RR_TYPE_PTR => self.ptr.entry(entry_name).or_default(), - RR_TYPE_SRV => self.srv.entry(entry_name).or_default(), - RR_TYPE_TXT => self.txt.entry(entry_name).or_default(), - RR_TYPE_A | RR_TYPE_AAAA => self.addr.entry(entry_name).or_default(), - RR_TYPE_NSEC => self.nsec.entry(entry_name).or_default(), + RRType::PTR => self.ptr.entry(entry_name).or_default(), + RRType::SRV => self.srv.entry(entry_name).or_default(), + RRType::TXT => self.txt.entry(entry_name).or_default(), + RRType::A | RRType::AAAA => self.addr.entry(entry_name).or_default(), + RRType::NSEC => self.nsec.entry(entry_name).or_default(), _ => return None, }; @@ -208,7 +207,7 @@ impl DnsCache { should_flush = true; // additional checks for address records. - if rtype == RR_TYPE_A || rtype == RR_TYPE_AAAA { + if rtype == RRType::A || rtype == RRType::AAAA { if let Some(addr) = r.any().downcast_ref::() { if let Some(addr_b) = incoming.any().downcast_ref::() { should_flush = @@ -255,10 +254,10 @@ impl DnsCache { let mut found = false; let record_name = record.get_name(); let record_vec = match record.get_type() { - RR_TYPE_PTR => self.ptr.get_mut(record_name), - RR_TYPE_SRV => self.srv.get_mut(record_name), - RR_TYPE_TXT => self.txt.get_mut(record_name), - RR_TYPE_A | RR_TYPE_AAAA => self.addr.get_mut(record_name), + RRType::PTR => self.ptr.get_mut(record_name), + RRType::SRV => self.srv.get_mut(record_name), + RRType::TXT => self.txt.get_mut(record_name), + RRType::A | RRType::AAAA => self.addr.get_mut(record_name), _ => return found, }; if let Some(record_vec) = record_vec { @@ -497,14 +496,14 @@ impl DnsCache { pub(crate) fn get_known_answers<'a>( &'a self, name: &str, - qtype: u16, + qtype: RRType, now: u64, ) -> Vec<&'a DnsRecordBox> { let records_opt = match qtype { - RR_TYPE_PTR => self.get_ptr(name), - RR_TYPE_SRV => self.get_srv(name), - RR_TYPE_A | RR_TYPE_AAAA => self.get_addr(name), - RR_TYPE_TXT => self.get_txt(name), + RRType::PTR => self.get_ptr(name), + RRType::SRV => self.get_srv(name), + RRType::A | RRType::AAAA => self.get_addr(name), + RRType::TXT => self.get_txt(name), _ => None, }; diff --git a/src/dns_parser.rs b/src/dns_parser.rs index 6a2c9c6..906d885 100644 --- a/src/dns_parser.rs +++ b/src/dns_parser.rs @@ -22,46 +22,70 @@ use std::{ time::SystemTime, }; -/// DNS record type for IPv4 address -pub const RR_TYPE_A: u16 = 1; +/// DNS resource record types +/// See [RFC 1035 section 3.2.2](https://datatracker.ietf.org/doc/html/rfc1035#section-3.2.2) +#[derive(Debug, PartialEq, Eq, Clone, Copy, PartialOrd, Ord)] +#[non_exhaustive] +#[repr(u16)] +pub enum RRType { + /// DNS record type for IPv4 address + A = 1, -/// DNS record type for Canonical Name -pub const RR_TYPE_CNAME: u16 = 5; + /// DNS record type for Canonical Name + CNAME = 5, -/// DNS record type for Pointer -pub const RR_TYPE_PTR: u16 = 12; + /// DNS record type for Pointer + PTR = 12, -/// DNS record type for Host Info -pub const RR_TYPE_HINFO: u16 = 13; + /// DNS record type for Host Info + HINFO = 13, -/// DNS record type for Text (properties) -pub const RR_TYPE_TXT: u16 = 16; + /// DNS record type for Text (properties) + TXT = 16, -/// DNS record type for IPv6 address -pub const RR_TYPE_AAAA: u16 = 28; + /// DNS record type for IPv6 address + AAAA = 28, -/// DNS record type for Service -pub const RR_TYPE_SRV: u16 = 33; + /// DNS record type for Service + SRV = 33, -/// DNS record type for Negative Responses -pub const RR_TYPE_NSEC: u16 = 47; + /// DNS record type for Negative Responses + NSEC = 47, -/// DNS record type for any records (wildcard) -pub const RR_TYPE_ANY: u16 = 255; + /// DNS record type for any records (wildcard) + ANY = 255, +} + +impl RRType { + pub const fn from_u16(value: u16) -> Option { + match value { + 1 => Some(RRType::A), + 5 => Some(RRType::CNAME), + 12 => Some(RRType::PTR), + 13 => Some(RRType::HINFO), + 16 => Some(RRType::TXT), + 28 => Some(RRType::AAAA), + 33 => Some(RRType::SRV), + 47 => Some(RRType::NSEC), + 255 => Some(RRType::ANY), + _ => None, + } + } +} -/// Returns the name string of a `rr_type`. -pub(crate) const fn rr_type_name(rr_type: u16) -> &'static str { - match rr_type { - RR_TYPE_A => "TYPE_A", - RR_TYPE_CNAME => "TYPE_CNAME", - RR_TYPE_PTR => "TYPE_PTR", - RR_TYPE_HINFO => "TYPE_HINFO", - RR_TYPE_TXT => "TYPE_TXT", - RR_TYPE_AAAA => "TYPE_AAAA", - RR_TYPE_SRV => "TYPE_SRV", - RR_TYPE_NSEC => "TYPE_NSEC", - RR_TYPE_ANY => "TYPE_ANY", - _ => "unknown", +impl fmt::Display for RRType { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + RRType::A => write!(f, "TYPE_A"), + RRType::CNAME => write!(f, "TYPE_CNAME"), + RRType::PTR => write!(f, "TYPE_PTR"), + RRType::HINFO => write!(f, "TYPE_HINFO"), + RRType::TXT => write!(f, "TYPE_TXT"), + RRType::AAAA => write!(f, "TYPE_AAAA"), + RRType::SRV => write!(f, "TYPE_SRV"), + RRType::NSEC => write!(f, "TYPE_NSEC"), + RRType::ANY => write!(f, "TYPE_ANY"), + } } } @@ -113,23 +137,23 @@ impl Clone for DnsRecordBox { const U16_SIZE: usize = 2; #[inline] -pub const fn ip_address_to_type(address: &IpAddr) -> u16 { +pub const fn ip_address_to_type(address: &IpAddr) -> RRType { match address { - IpAddr::V4(_) => RR_TYPE_A, - IpAddr::V6(_) => RR_TYPE_AAAA, + IpAddr::V4(_) => RRType::A, + IpAddr::V6(_) => RRType::AAAA, } } #[derive(Eq, PartialEq, Debug, Clone)] pub struct DnsEntry { pub(crate) name: String, // always lower case. - pub(crate) ty: u16, + pub(crate) ty: RRType, class: u16, cache_flush: bool, } impl DnsEntry { - const fn new(name: String, ty: u16, class: u16) -> Self { + const fn new(name: String, ty: RRType, class: u16) -> Self { Self { name, ty, @@ -164,7 +188,7 @@ pub struct DnsRecord { } impl DnsRecord { - fn new(name: &str, ty: u16, class: u16, ttl: u32) -> Self { + fn new(name: &str, ty: RRType, class: u16, ttl: u32) -> Self { let created = current_time_millis(); // From RFC 6762 section 5.2: @@ -362,7 +386,7 @@ pub(crate) trait DnsRecordExt: fmt::Debug { self.get_record().get_name() } - fn get_type(&self) -> u16 { + fn get_type(&self) -> RRType { self.get_record().entry.ty } @@ -427,7 +451,7 @@ pub struct DnsAddress { } impl DnsAddress { - pub(crate) fn new(name: &str, ty: u16, class: u16, ttl: u32, address: IpAddr) -> Self { + pub(crate) fn new(name: &str, ty: RRType, class: u16, ttl: u32, address: IpAddr) -> Self { let record = DnsRecord::new(name, ty, class, ttl); Self { record, address } } @@ -497,7 +521,7 @@ pub struct DnsPointer { } impl DnsPointer { - pub(crate) fn new(name: &str, ty: u16, class: u16, ttl: u32, alias: String) -> Self { + pub(crate) fn new(name: &str, ty: RRType, class: u16, ttl: u32, alias: String) -> Self { let record = DnsRecord::new(name, ty, class, ttl); Self { record, alias } } @@ -573,7 +597,7 @@ impl DnsSrv { port: u16, host: String, ) -> Self { - let record = DnsRecord::new(name, RR_TYPE_SRV, class, ttl); + let record = DnsRecord::new(name, RRType::SRV, class, ttl); Self { record, priority, @@ -689,7 +713,7 @@ pub struct DnsTxt { impl DnsTxt { pub(crate) fn new(name: &str, class: u16, ttl: u32, text: Vec) -> Self { - let record = DnsRecord::new(name, RR_TYPE_TXT, class, ttl); + let record = DnsRecord::new(name, RRType::TXT, class, ttl); Self { record, text } } } @@ -762,7 +786,7 @@ struct DnsHostInfo { } impl DnsHostInfo { - fn new(name: &str, ty: u16, class: u16, ttl: u32, cpu: String, os: String) -> Self { + fn new(name: &str, ty: RRType, class: u16, ttl: u32, cpu: String, os: String) -> Self { let record = DnsRecord::new(name, ty, class, ttl); Self { record, cpu, os } } @@ -837,7 +861,7 @@ pub struct DnsNSec { impl DnsNSec { fn new(name: &str, class: u16, ttl: u32, next_domain: String, type_bitmap: Vec) -> Self { - let record = DnsRecord::new(name, RR_TYPE_NSEC, class, ttl); + let record = DnsRecord::new(name, RRType::NSEC, class, ttl); Self { record, next_domain, @@ -966,7 +990,7 @@ impl DnsOutPacket { fn write_question(&mut self, question: &DnsQuestion) { self.write_name(&question.entry.name); - self.write_short(question.entry.ty); + self.write_short(question.entry.ty as u16); self.write_short(question.entry.class); } @@ -979,7 +1003,7 @@ impl DnsOutPacket { let record = record_ext.get_record(); self.write_name(record.get_name()); - self.write_short(record.entry.ty); + self.write_short(record.entry.ty as u16); if record.entry.cache_flush { // check "multicast" self.write_short(record.entry.class | CLASS_CACHE_FLUSH); @@ -1306,7 +1330,7 @@ impl DnsOutgoing { msg, DnsPointer::new( service.get_type(), - RR_TYPE_PTR, + RRType::PTR, CLASS_IN, service.get_other_ttl(), service_fullname.to_string(), @@ -1322,7 +1346,7 @@ impl DnsOutgoing { debug!("Adding subdomain {}", sub); self.add_additional_answer(DnsPointer::new( sub, - RR_TYPE_PTR, + RRType::PTR, CLASS_IN, service.get_other_ttl(), service_fullname.to_string(), @@ -1359,7 +1383,7 @@ impl DnsOutgoing { } } - pub(crate) fn add_question(&mut self, name: &str, qtype: u16) { + pub(crate) fn add_question(&mut self, name: &str, qtype: RRType) { let q = DnsQuestion { entry: DnsEntry::new(name.to_string(), qtype, CLASS_IN), }; @@ -1562,8 +1586,15 @@ impl DnsIncoming { let class = u16_from_be_slice(&data[2..4]); self.offset += 4; + let Some(rr_type) = RRType::from_u16(ty) else { + return Err(Error::Msg(format!( + "DNS incoming: question idx {} qtype unknown: {}", + i, ty + ))); + }; + self.questions.push(DnsQuestion { - entry: DnsEntry::new(name, ty, class), + entry: DnsEntry::new(name, rr_type, class), }); } Ok(()) @@ -1653,77 +1684,80 @@ impl DnsIncoming { } // decode RDATA based on the record type. - let rec: Option = match ty { - RR_TYPE_CNAME | RR_TYPE_PTR => Some(Box::new(DnsPointer::new( - &name, - ty, - class, - ttl, - self.read_name()?, - ))), - RR_TYPE_TXT => Some(Box::new(DnsTxt::new( - &name, - class, - ttl, - self.read_vec(rdata_len), - ))), - RR_TYPE_SRV => Some(Box::new(DnsSrv::new( - &name, - class, - ttl, - self.read_u16()?, - self.read_u16()?, - self.read_u16()?, - self.read_name()?, - ))), - RR_TYPE_HINFO => Some(Box::new(DnsHostInfo::new( - &name, - ty, - class, - ttl, - self.read_char_string(), - self.read_char_string(), - ))), - RR_TYPE_A => Some(Box::new(DnsAddress::new( - &name, - ty, - class, - ttl, - self.read_ipv4().into(), - ))), - RR_TYPE_AAAA => Some(Box::new(DnsAddress::new( - &name, - ty, - class, - ttl, - self.read_ipv6().into(), - ))), - RR_TYPE_NSEC => Some(Box::new(DnsNSec::new( - &name, - class, - ttl, - self.read_name()?, - self.read_type_bitmap()?, - ))), - x => { - debug!("Unknown DNS record type: {} name: {}", x, &name); - self.offset += rdata_len; - None - } + let rec: Option = match RRType::from_u16(ty) { + None => None, + + Some(rr_type) => match rr_type { + RRType::CNAME | RRType::PTR => Some(Box::new(DnsPointer::new( + &name, + rr_type, + class, + ttl, + self.read_name()?, + ))), + RRType::TXT => Some(Box::new(DnsTxt::new( + &name, + class, + ttl, + self.read_vec(rdata_len), + ))), + RRType::SRV => Some(Box::new(DnsSrv::new( + &name, + class, + ttl, + self.read_u16()?, + self.read_u16()?, + self.read_u16()?, + self.read_name()?, + ))), + RRType::HINFO => Some(Box::new(DnsHostInfo::new( + &name, + rr_type, + class, + ttl, + self.read_char_string(), + self.read_char_string(), + ))), + RRType::A => Some(Box::new(DnsAddress::new( + &name, + rr_type, + class, + ttl, + self.read_ipv4().into(), + ))), + RRType::AAAA => Some(Box::new(DnsAddress::new( + &name, + rr_type, + class, + ttl, + self.read_ipv6().into(), + ))), + RRType::NSEC => Some(Box::new(DnsNSec::new( + &name, + class, + ttl, + self.read_name()?, + self.read_type_bitmap()?, + ))), + _ => None, + }, }; + if let Some(record) = rec { + debug!("read_rr_records: {:?}", &record); + rr_records.push(record); + } else { + debug!("Unsupported DNS record type: {} name: {}", ty, &name); + self.offset += rdata_len; + } + // sanity check. if self.offset != next_offset { return Err(Error::Msg(format!( - "read_rr_records: decode offset error for RData type {} record: {:?} offset: {} expected offset: {}", - ty, &rec, self.offset, next_offset, + "read_rr_records: decode offset error for RData type {} offset: {} expected offset: {}", + ty, self.offset, next_offset, ))); } - - if let Some(record) = rec { - debug!("read_rr_records: {:?}", &record); - rr_records.push(record); - } } Ok(rr_records) @@ -1961,15 +1995,15 @@ mod tests { use super::{ current_time_millis, get_expiration_time, DnsIncoming, DnsNSec, DnsOutgoing, DnsPointer, - DnsRecordExt, DnsSrv, DnsTxt, CLASS_CACHE_FLUSH, CLASS_IN, FLAGS_QR_QUERY, - FLAGS_QR_RESPONSE, MSG_HEADER_LEN, RR_TYPE_A, RR_TYPE_AAAA, RR_TYPE_PTR, + DnsRecordExt, DnsSrv, DnsTxt, RRType, CLASS_CACHE_FLUSH, CLASS_IN, FLAGS_QR_QUERY, + FLAGS_QR_RESPONSE, MSG_HEADER_LEN, }; #[test] fn test_read_name_invalid_length() { let name = "test_read"; let mut out = DnsOutgoing::new(FLAGS_QR_QUERY); - out.add_question(name, RR_TYPE_PTR); + out.add_question(name, RRType::PTR); let data = out.to_data_on_wire().remove(0); // construct invalid data. @@ -2008,7 +2042,7 @@ mod tests { fn test_read_name_compression_loop() { let name = "test_loop"; let mut out = DnsOutgoing::new(FLAGS_QR_QUERY); - out.add_question(name, RR_TYPE_PTR); + out.add_question(name, RRType::PTR); let mut data = out.to_data_on_wire().remove(0); let name_length_offset = 12; // start of the name in the message. @@ -2157,8 +2191,8 @@ mod tests { ); let absent_types = nsec._types(); assert_eq!(absent_types.len(), 2); - assert_eq!(absent_types[0], RR_TYPE_A); - assert_eq!(absent_types[1], RR_TYPE_AAAA); + assert_eq!(absent_types[0], RRType::A as u16); + assert_eq!(absent_types[1], RRType::AAAA as u16); } #[test] @@ -2191,7 +2225,7 @@ mod tests { #[test] fn test_packet_size() { let mut outgoing = DnsOutgoing::new(FLAGS_QR_QUERY); - outgoing.add_question("test_packet_size", RR_TYPE_PTR); + outgoing.add_question("test_packet_size", RRType::PTR); let packet = outgoing.to_packets().remove(0); println!("packet size: {}", packet.size); @@ -2205,12 +2239,12 @@ mod tests { fn test_querier_known_answer_multi_packet() { let mut query = DnsOutgoing::new(FLAGS_QR_QUERY); let name = "test_multi_packet._udp.local."; - query.add_question(name, RR_TYPE_PTR); + query.add_question(name, RRType::PTR); let known_answer_count = 400; for i in 0..known_answer_count { let alias = format!("instance{}.{}", i, name); - let answer = DnsPointer::new(name, RR_TYPE_PTR, CLASS_IN, 0, alias); + let answer = DnsPointer::new(name, RRType::PTR, CLASS_IN, 0, alias); query.add_additional_answer(answer); } diff --git a/src/lib.rs b/src/lib.rs index a027aae..1f7164e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -151,10 +151,7 @@ mod error; mod service_daemon; mod service_info; -pub use dns_parser::{ - RR_TYPE_A, RR_TYPE_AAAA, RR_TYPE_ANY, RR_TYPE_CNAME, RR_TYPE_HINFO, RR_TYPE_NSEC, RR_TYPE_PTR, - RR_TYPE_SRV, RR_TYPE_TXT, -}; +pub use dns_parser::RRType; pub use error::{Error, Result}; pub use service_daemon::{ DaemonEvent, DaemonStatus, DnsNameChange, HostnameResolutionEvent, IfKind, Metrics, diff --git a/src/service_daemon.rs b/src/service_daemon.rs index a9aef9b..93de2b5 100644 --- a/src/service_daemon.rs +++ b/src/service_daemon.rs @@ -33,10 +33,9 @@ use crate::log::{debug, error, info, warn}; use crate::{ dns_cache::DnsCache, dns_parser::{ - current_time_millis, ip_address_to_type, rr_type_name, split_sub_domain, DnsAddress, - DnsIncoming, DnsOutgoing, DnsPointer, DnsRecordBox, DnsRecordExt, DnsSrv, DnsTxt, + current_time_millis, ip_address_to_type, split_sub_domain, DnsAddress, DnsIncoming, + DnsOutgoing, DnsPointer, DnsRecordBox, DnsRecordExt, DnsSrv, DnsTxt, RRType, CLASS_CACHE_FLUSH, CLASS_IN, FLAGS_AA, FLAGS_QR_QUERY, FLAGS_QR_RESPONSE, MAX_MSG_ABSOLUTE, - RR_TYPE_A, RR_TYPE_AAAA, RR_TYPE_ANY, RR_TYPE_PTR, RR_TYPE_SRV, RR_TYPE_TXT, }, error::{Error, Result}, service_info::{DnsRegistry, Probe, ServiceInfo, ServiceStatus}, @@ -1303,7 +1302,7 @@ impl Zeroconf { // move the record to active expired_probe_names.push(name.clone()); } else { - out.add_question(name, RR_TYPE_ANY); + out.add_question(name, RRType::ANY); /* RFC 6762 section 8.2: https://datatracker.ietf.org/doc/html/rfc6762#section-8.2 @@ -1423,7 +1422,7 @@ impl Zeroconf { out.add_answer_at_time( DnsPointer::new( info.get_type(), - RR_TYPE_PTR, + RRType::PTR, CLASS_IN, 0, info.get_fullname().to_string(), @@ -1436,7 +1435,7 @@ impl Zeroconf { out.add_answer_at_time( DnsPointer::new( sub, - RR_TYPE_PTR, + RRType::PTR, CLASS_IN, 0, info.get_fullname().to_string(), @@ -1502,12 +1501,12 @@ impl Zeroconf { } /// Sends a multicast query for `name` with `qtype`. - fn send_query(&self, name: &str, qtype: u16) { + fn send_query(&self, name: &str, qtype: RRType) { self.send_query_vec(&[(name, qtype)]); } /// Sends out a list of `questions` (i.e. DNS questions) via multicast. - fn send_query_vec(&self, questions: &[(&str, u16)]) { + fn send_query_vec(&self, questions: &[(&str, RRType)]) { debug!("Sending query questions: {:?}", questions); let mut out = DnsOutgoing::new(FLAGS_QR_QUERY); let now = current_time_millis(); @@ -1619,13 +1618,13 @@ impl Zeroconf { for record in records { if let Some(srv) = record.any().downcast_ref::() { if self.cache.get_addr(&srv.host).is_none() { - self.send_query_vec(&[(&srv.host, RR_TYPE_A), (&srv.host, RR_TYPE_AAAA)]); + self.send_query_vec(&[(&srv.host, RRType::A), (&srv.host, RRType::AAAA)]); return true; } } } } else { - self.send_query(instance, RR_TYPE_ANY); + self.send_query(instance, RRType::ANY); return true; } @@ -1811,7 +1810,7 @@ impl Zeroconf { /// Represents a DNS record change that involves one service instance. struct InstanceChange { - ty: u16, // The type of DNS record for the instance. + ty: RRType, // The type of DNS record for the instance. name: String, // The name of the record. } @@ -1837,7 +1836,7 @@ impl Zeroconf { let ty = dns_record.get_type(); let name = dns_record.get_name(); - if ty == RR_TYPE_PTR { + if ty == RRType::PTR { if self.service_queriers.contains_key(name) { timers.push(dns_record.get_record().get_refresh_time()); } @@ -1877,7 +1876,7 @@ impl Zeroconf { // Go through remaining changes to see if any hostname resolutions were found or updated. changes .iter() - .filter(|change| change.ty == RR_TYPE_A || change.ty == RR_TYPE_AAAA) + .filter(|change| change.ty == RRType::A || change.ty == RRType::AAAA) .map(|change| change.name.clone()) .collect::>() .iter() @@ -1894,10 +1893,10 @@ impl Zeroconf { let mut updated_instances = HashSet::new(); for update in changes { match update.ty { - RR_TYPE_PTR | RR_TYPE_SRV | RR_TYPE_TXT => { + RRType::PTR | RRType::SRV | RRType::TXT => { updated_instances.insert(update.name); } - RR_TYPE_A | RR_TYPE_AAAA => { + RRType::A | RRType::AAAA => { let instances = self.cache.get_instances_on_host(&update.name); updated_instances.extend(instances); } @@ -1922,7 +1921,7 @@ impl Zeroconf { }; // check against possible multicast forwarding - if answer.get_type() == RR_TYPE_A || answer.get_type() == RR_TYPE_AAAA { + if answer.get_type() == RRType::A || answer.get_type() == RRType::AAAA { if let Some(answer_addr) = answer.any().downcast_ref::() { if !answer_addr.in_subnet(intf) { info!( @@ -1941,7 +1940,7 @@ impl Zeroconf { { info!( "found conflict name: '{name}' record: {}: {} PEER: {}", - rr_type_name(record.get_type()), + record.get_type(), record.rdata_print(), answer.rdata_print() ); @@ -1950,8 +1949,8 @@ impl Zeroconf { // then remove the old record in probing. let mut new_record = record.clone(); let new_name = match record.get_type() { - RR_TYPE_A => hostname_change(name), - RR_TYPE_AAAA => hostname_change(name), + RRType::A => hostname_change(name), + RRType::AAAA => hostname_change(name), _ => name_change(name), }; new_record.get_record_mut().set_new_name(new_name); @@ -2001,7 +2000,7 @@ impl Zeroconf { info!( "insert record with new name '{}' {} into probe", record.get_name(), - rr_type_name(record.get_type()) + record.get_type() ); new_probe.insert_record(record); @@ -2086,9 +2085,10 @@ impl Zeroconf { for question in msg.questions.iter() { debug!("query question: {:?}", &question); + let qtype = question.entry.ty; - if qtype == RR_TYPE_PTR { + if qtype == RRType::PTR { for service in self.my_services.values() { if service.get_status(intf) != ServiceStatus::Announced { continue; @@ -2106,7 +2106,7 @@ impl Zeroconf { &msg, DnsPointer::new( &question.entry.name, - RR_TYPE_PTR, + RRType::PTR, CLASS_IN, service.get_other_ttl(), service.get_type().to_string(), @@ -2119,7 +2119,7 @@ impl Zeroconf { } } else { // Simultaneous Probe Tiebreaking (RFC 6762 section 8.2) - if qtype == RR_TYPE_ANY && msg.num_authorities > 0 { + if qtype == RRType::ANY && msg.num_authorities > 0 { let probe_name = &question.entry.name; if let Some(probe) = dns_registry.probing.get_mut(probe_name) { @@ -2161,7 +2161,7 @@ impl Zeroconf { } } - if qtype == RR_TYPE_A || qtype == RR_TYPE_AAAA || qtype == RR_TYPE_ANY { + if qtype == RRType::A || qtype == RRType::AAAA || qtype == RRType::ANY { for service in self.my_services.values() { if service.get_status(intf) != ServiceStatus::Announced { continue; @@ -2176,11 +2176,11 @@ impl Zeroconf { if service_hostname.to_lowercase() == question.entry.name.to_lowercase() { let intf_addrs = service.get_addrs_on_intf(intf); if intf_addrs.is_empty() - && (qtype == RR_TYPE_A || qtype == RR_TYPE_AAAA) + && (qtype == RRType::A || qtype == RRType::AAAA) { let t = match qtype { - RR_TYPE_A => "TYPE_A", - RR_TYPE_AAAA => "TYPE_AAAA", + RRType::A => "TYPE_A", + RRType::AAAA => "TYPE_AAAA", _ => "invalid_type", }; debug!( @@ -2226,7 +2226,7 @@ impl Zeroconf { continue; } - if qtype == RR_TYPE_SRV || qtype == RR_TYPE_ANY { + if qtype == RRType::SRV || qtype == RRType::ANY { out.add_answer( &msg, DnsSrv::new( @@ -2241,7 +2241,7 @@ impl Zeroconf { ); } - if qtype == RR_TYPE_TXT || qtype == RR_TYPE_ANY { + if qtype == RRType::TXT || qtype == RRType::ANY { out.add_answer( &msg, DnsTxt::new( @@ -2253,7 +2253,7 @@ impl Zeroconf { ); } - if qtype == RR_TYPE_SRV { + if qtype == RRType::SRV { let intf_addrs = service.get_addrs_on_intf(intf); if intf_addrs.is_empty() { error!( @@ -2436,7 +2436,7 @@ impl Zeroconf { self.query_cache_for_service(&ty, &listener); } - self.send_query(&ty, RR_TYPE_PTR); + self.send_query(&ty, RRType::PTR); self.increase_counter(Counter::Browse, 1); let next_time = current_time_millis() + (next_delay * 1000) as u64; @@ -2470,7 +2470,7 @@ impl Zeroconf { self.query_cache_for_hostname(&hostname, listener.clone()); } - self.send_query_vec(&[(&hostname, RR_TYPE_A), (&hostname, RR_TYPE_AAAA)]); + self.send_query_vec(&[(&hostname, RRType::A), (&hostname, RRType::AAAA)]); self.increase_counter(Counter::ResolveHostname, 1); let now = current_time_millis(); @@ -2670,7 +2670,7 @@ impl Zeroconf { let record_vec = self.cache.service_verify_queries(&instance, expire_at); if !record_vec.is_empty() { - let query_vec: Vec<(&str, u16)> = record_vec + let query_vec: Vec<(&str, RRType)> = record_vec .iter() .map(|(record, rr_type)| (record.as_str(), *rr_type)) .collect(); @@ -2696,7 +2696,7 @@ impl Zeroconf { let refreshed_timers = self.cache.refresh_due_ptr(ty_domain); if !refreshed_timers.is_empty() { debug!("sending refresh query for PTR: {}", ty_domain); - self.send_query(ty_domain, RR_TYPE_PTR); + self.send_query(ty_domain, RRType::PTR); query_ptr_count += 1; new_timers.extend(refreshed_timers); } @@ -2704,14 +2704,14 @@ impl Zeroconf { let (instances, timers) = self.cache.refresh_due_srv(ty_domain); for instance in instances.iter() { debug!("sending refresh query for SRV: {}", instance); - self.send_query(instance, RR_TYPE_SRV); + self.send_query(instance, RRType::SRV); query_srv_count += 1; } new_timers.extend(timers); let (hostnames, timers) = self.cache.refresh_due_hosts(ty_domain); for hostname in hostnames.iter() { debug!("sending refresh queries for A and AAAA: {}", hostname); - self.send_query_vec(&[(hostname, RR_TYPE_A), (hostname, RR_TYPE_AAAA)]); + self.send_query_vec(&[(hostname, RRType::A), (hostname, RRType::AAAA)]); query_addr_count += 2; } new_timers.extend(timers); @@ -2807,8 +2807,8 @@ pub struct DnsNameChange { /// - Host name `foo.local.` becomes `foo-2.local.` pub new_name: String, - /// The value is one of `RR_TYPE_` constants. - pub rr_type: u16, + /// The resource record type + pub rr_type: RRType, /// The interface where the name conflict and its change happened. pub intf_name: String, @@ -3112,7 +3112,7 @@ fn prepare_announce( out.add_answer_at_time( DnsPointer::new( info.get_type(), - RR_TYPE_PTR, + RRType::PTR, CLASS_IN, info.get_other_ttl(), service_fullname.to_string(), @@ -3125,7 +3125,7 @@ fn prepare_announce( out.add_answer_at_time( DnsPointer::new( sub, - RR_TYPE_PTR, + RRType::PTR, CLASS_IN, info.get_other_ttl(), service_fullname.to_string(), @@ -3303,7 +3303,7 @@ mod tests { MDNS_PORT, }; use crate::{ - dns_parser::{DnsOutgoing, DnsPointer, CLASS_IN, FLAGS_AA, FLAGS_QR_RESPONSE, RR_TYPE_PTR}, + dns_parser::{DnsOutgoing, DnsPointer, RRType, CLASS_IN, FLAGS_AA, FLAGS_QR_RESPONSE}, service_daemon::check_hostname, }; use std::{ @@ -3438,7 +3438,7 @@ mod tests { // Invalidate the ptr from the service to the host. let invalidate_ptr_packet = DnsPointer::new( my_service.get_type(), - RR_TYPE_PTR, + RRType::PTR, CLASS_IN, 0, my_service.get_fullname().to_string(), diff --git a/src/service_info.rs b/src/service_info.rs index adcdeab..8bef425 100644 --- a/src/service_info.rs +++ b/src/service_info.rs @@ -3,7 +3,7 @@ #[cfg(feature = "logging")] use crate::log::{error, info}; use crate::{ - dns_parser::{rr_type_name, split_sub_domain, DnsRecordBox, DnsRecordExt, DnsSrv, RR_TYPE_SRV}, + dns_parser::{split_sub_domain, DnsRecordBox, DnsRecordExt, DnsSrv, RRType}, Error, Result, }; use if_addrs::{IfAddr, Interface}; @@ -938,7 +938,7 @@ impl DnsRegistry { if answer.matches(record.as_ref()) { info!( "found active record {} {}", - rr_type_name(answer.get_type()), + answer.get_type(), answer.get_name(), ); return true; @@ -960,7 +960,7 @@ impl DnsRegistry { if answer.matches(record.as_ref()) { info!( "found existing record {} in probe of '{}'", - rr_type_name(answer.get_type()), + answer.get_type(), answer.get_name(), ); probe.waiting_services.insert(service_name.to_string()); @@ -970,7 +970,7 @@ impl DnsRegistry { info!( "insert record {} into probe of {}", - rr_type_name(answer.get_type()), + answer.get_type(), answer.get_name(), ); probe.insert_record(answer.clone_box()); @@ -993,7 +993,7 @@ impl DnsRegistry { for (_name, probe) in self.probing.iter_mut() { probe.records.retain(|record| { - if record.get_type() == RR_TYPE_SRV { + if record.get_type() == RRType::SRV { if let Some(srv) = record.any().downcast_ref::() { if srv.host == original { let mut new_record = srv.clone(); @@ -1009,7 +1009,7 @@ impl DnsRegistry { for (_name, records) in self.active.iter_mut() { records.retain(|record| { - if record.get_type() == RR_TYPE_SRV { + if record.get_type() == RRType::SRV { if let Some(srv) = record.any().downcast_ref::() { if srv.host == original { let mut new_record = srv.clone(); @@ -1041,7 +1041,7 @@ impl DnsRegistry { info!( "insert record {} with new hostname {new_name} into probe for: {}", - rr_type_name(record.get_type()), + record.get_type(), record.get_name() ); probe.insert_record(Box::new(record));