[new/rdata] Add Srv

This commit is contained in:
arya dradjica
2026-07-14 14:22:25 +02:00
parent 6a934d2f41
commit d89a2827e2
2 changed files with 125 additions and 0 deletions
+13
View File
@@ -43,6 +43,7 @@
//! - [`Mx`]
//! - [`Txt`]
//! - [`Rp`]
//! - [`Srv`]
//!
//! Indirection types:
//! - [`CName`]
@@ -115,6 +116,9 @@ pub use edns::{EdnsOptionsIter, Opt};
mod rp;
pub use rp::Rp;
mod srv;
pub use srv::Srv;
mod dnssec;
pub use dnssec::{
DNSKey, DNSKeyFlags, DigestType, Ds, NSec, NSec3, NSec3Flags,
@@ -280,6 +284,9 @@ define_record_data! {
/// Identification of the person/party responsible for this domain.
Rp(Rp<N>) = RP,
/// The locations of services associated with this domain.
Srv(&'a Srv) = SRV,
/// The IPv6 address of a host responsible for this domain.
Aaaa(Aaaa) = AAAA,
@@ -331,6 +338,7 @@ impl<'a, N> RecordData<'a, N> {
Self::Txt(r) => RecordData::Txt(r),
Self::Rp(r) => RecordData::Rp(r.map_names(f)),
Self::Aaaa(r) => RecordData::Aaaa(r),
Self::Srv(r) => RecordData::Srv(r),
Self::DName(r) => RecordData::DName(r),
Self::Opt(r) => RecordData::Opt(r),
Self::Ds(r) => RecordData::Ds(r),
@@ -360,6 +368,7 @@ impl<'a, N> RecordData<'a, N> {
Self::Txt(r) => RecordData::Txt(r),
Self::Rp(r) => RecordData::Rp(r.map_names_by_ref(f)),
Self::Aaaa(r) => RecordData::Aaaa(*r),
Self::Srv(r) => RecordData::Srv(r),
Self::DName(r) => RecordData::DName(r),
Self::Opt(r) => RecordData::Opt(r),
Self::Ds(r) => RecordData::Ds(r),
@@ -395,6 +404,7 @@ impl<'a, N> RecordData<'a, N> {
Self::Txt(r) => RecordData::Txt(copy_to_bump(*r, bump)),
Self::Rp(r) => RecordData::Rp(r.clone()),
Self::Aaaa(r) => RecordData::Aaaa(*r),
Self::Srv(r) => RecordData::Srv(copy_to_bump(*r, bump)),
Self::DName(r) => RecordData::DName(copy_to_bump(*r, bump)),
Self::Opt(r) => RecordData::Opt(copy_to_bump(*r, bump)),
Self::Ds(r) => RecordData::Ds(copy_to_bump(*r, bump)),
@@ -450,6 +460,9 @@ impl<'a, N: SplitMessageBytes<'a>> ParseRecordData<'a> for RecordData<'a, N> {
RType::AAAA => {
Aaaa::parse_bytes(&contents[start..]).map(Self::Aaaa)
}
RType::SRV => {
<&Srv>::parse_bytes(&contents[start..]).map(Self::Srv)
}
RType::DNAME => {
<&DName>::parse_bytes(&contents[start..]).map(Self::DName)
}
+112
View File
@@ -0,0 +1,112 @@
//! The SRV record data type.
//!
//! See [RFC 2782](https://datatracker.ietf.org/doc/html/rfc2782).
use core::cmp::Ordering;
use crate::new::base::build::{
AsBytes, BuildBytes, BuildInMessage, NameCompressor,
};
use crate::new::base::name::{CanonicalName, Name};
use crate::new::base::wire::*;
use crate::new::base::{
CanonicalRecordData, ParseRecordData, ParseRecordDataBytes, RType,
};
use crate::utils::dst::UnsizedCopy;
//----------- Srv ------------------------------------------------------------
/// The locations of services associated with this domain.
//
// TODO: Documentation.
#[derive(
Debug,
PartialEq,
Eq,
PartialOrd,
Ord,
Hash,
AsBytes,
BuildBytes,
ParseBytesZC,
SplitBytesZC,
UnsizedCopy,
)]
#[repr(C)]
pub struct Srv {
/// The priority of this host.
pub priority: U16,
/// The relative weight for selection of this host.
pub weight: U16,
/// The port number on which the service is provided.
pub port: U16,
/// The domain name of the target host.
pub name: Name,
}
//--- Canonical operations
impl CanonicalRecordData for Srv {
fn build_canonical_bytes<'b>(
&self,
bytes: &'b mut [u8],
) -> Result<&'b mut [u8], TruncationError> {
let bytes = self.priority.build_bytes(bytes)?;
let bytes = self.weight.build_bytes(bytes)?;
let bytes = self.port.build_bytes(bytes)?;
let bytes = self.name.build_lowercased_bytes(bytes)?;
Ok(bytes)
}
fn cmp_canonical(&self, other: &Self) -> Ordering {
// `Srv` uses canonical comparisons by default.
self.cmp(other)
}
}
//--- Building into DNS messages
impl BuildInMessage for Srv {
fn build_in_message(
&self,
contents: &mut [u8],
start: usize,
_compressor: &mut NameCompressor,
) -> Result<usize, TruncationError> {
let bytes = self.as_bytes();
let end = start + bytes.len();
contents
.get_mut(start..end)
.ok_or(TruncationError)?
.copy_from_slice(bytes);
Ok(end)
}
}
//--- Cloning
#[cfg(feature = "alloc")]
impl Clone for alloc::boxed::Box<Srv> {
fn clone(&self) -> Self {
(*self).unsized_copy_into()
}
}
//--- Parsing record data
impl<'a> ParseRecordData<'a> for &'a Srv {}
impl<'a> ParseRecordDataBytes<'a> for &'a Srv {
fn parse_record_data_bytes(
bytes: &'a [u8],
rtype: RType,
) -> Result<Self, ParseError> {
match rtype {
RType::SRV => Self::parse_bytes(bytes),
_ => Err(ParseError),
}
}
}