Skip to main content

ddns/core/parser/record/
endpoint.rs

1use std::{
2    convert::TryFrom,
3    fmt::Display,
4    hash::{Hash, Hasher},
5    net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6},
6    path::Path,
7};
8
9use base64::Engine;
10use bytes::BufMut;
11use dhttp_identity::certificate::{CertificateChainKey, CertificateChainKind, CertificateSequence};
12use dquic::qbase::net::addr::EndpointAddr as DquicEndpointAddr;
13use nom::{
14    IResult, Parser,
15    bytes::streaming::take,
16    combinator::{flat_map, map},
17    error::{ErrorKind, make_error},
18    number::streaming::{be_u8, be_u16, be_u32, be_u128},
19};
20use rustls::{SignatureScheme, pki_types::SubjectPublicKeyInfoDer};
21use snafu::{ResultExt, Snafu};
22
23use crate::core::parser::{
24    sigin,
25    varint::{VarInt, WriteVarInt, be_varint},
26};
27
28#[derive(Debug, Snafu)]
29#[snafu(module)]
30pub enum SignEndpointError {
31    #[snafu(display("failed to sign endpoint address"))]
32    Sign {
33        source: dhttp_identity::identity::SignError,
34    },
35    #[snafu(display("no supported signature scheme for endpoint address"))]
36    NoSupportedScheme,
37}
38
39/// EndpointAddress record (Type E = 266)
40///
41/// Unified endpoint format that encodes address family, routing, clustering and NAT information
42/// in a single flags byte, followed by optional fields.
43///
44/// ## Wire format
45///
46/// ```text
47/// +-------+-----------------+--------------------+----------------+----------------------------+
48/// | flags | sequence(varint)| addr               | load(optional) | signature (optional)       |
49/// +-------+-----------------+--------------------+----------------+----------------------------+
50/// | u8    | QUIC varint     | see addr layout    | f32            | scheme(u16)+len(varint)+N  |
51/// +-------+-----------------+--------------------+----------------+----------------------------+
52///
53/// addr layout:
54/// +---------+-----------------------------------------+
55/// | kind    | addr fields                             |
56/// +---------+-----------------------------------------+
57/// | direct  | port(u16) + IP(u32/u128)                |
58/// +---------+-----------------------------------------+
59/// | nat     | outer_port(u16) + outer_IP(u32/u128)    |
60/// |         | + agent_port(u16) + agent_IP(u32/u128)  |
61/// +---------+-----------------------------------------+
62/// ```
63///
64/// ## flags (u8) bit layout (bit 1 = MSB)
65///
66/// - bit 1 (0x80): FAMILY    — address family: 0=IPv4, 1=IPv6
67/// - bit 2 (0x40): MAIN      — primary/backup: 1=primary, 0=backup
68/// - bit 3 (0x20): CLUSTERED — multiple hosts share this name; record includes a device sequence number
69/// - bit 4 (0x10): NAT       — endpoint is behind NAT; record includes the agent endpoint address
70/// - bit 5 (0x08): LOAD      — record carries 1-minute load average (f32)
71/// - bit 6 (0x04): reserved
72/// - bit 7 (0x02): reserved
73/// - bit 8 (0x01): SIGNED    — record carries a publisher key signature to prevent DNS poisoning
74///
75/// ## Field order
76///
77/// `flags` → `sequence` (if CLUSTERED) → `addr` → `agent addr` (if NAT) → `load` (if LOAD) → `signature` (if SIGNED)
78///
79#[derive(Debug, Clone, PartialEq, Eq, Hash)]
80pub struct EndpointSignature {
81    scheme: u16,
82    signature: Vec<u8>,
83}
84
85#[derive(Debug, Clone)]
86pub struct EndpointAddr {
87    flags: u8,
88    /// Certificate-chain sequence used when multiple hosts share a domain (CLUSTERED).
89    /// None means no sequence number.
90    sequence: Option<CertificateSequence>,
91    /// 1-minute load average (present when LOAD flag is set)
92    load: Option<f32>,
93    signature: Option<EndpointSignature>,
94    /// Primary address (the direct address, or the outer/public address for NAT)
95    pub primary: SocketAddr,
96    /// Agent address used for NAT traversal (present when NAT flag is set)
97    pub agent: Option<SocketAddr>,
98}
99
100impl PartialEq for EndpointAddr {
101    fn eq(&self, other: &Self) -> bool {
102        self.flags == other.flags
103            && self.sequence == other.sequence
104            && self.load.map(f32::to_bits) == other.load.map(f32::to_bits)
105            && self.signature == other.signature
106            && self.primary == other.primary
107            && self.agent == other.agent
108    }
109}
110
111impl Eq for EndpointAddr {}
112
113impl Hash for EndpointAddr {
114    fn hash<H: Hasher>(&self, state: &mut H) {
115        self.flags.hash(state);
116        self.sequence.hash(state);
117        self.load.map(f32::to_bits).hash(state);
118        self.signature.hash(state);
119        self.primary.hash(state);
120        self.agent.hash(state);
121    }
122}
123
124impl EndpointAddr {
125    const FLAG_FAMILY: u8 = 0b1000_0000; // bit 1: 0=IPv4, 1=IPv6
126    const FLAG_MAIN: u8 = 0b0100_0000; // bit 2: 1=primary, 0=backup
127    const FLAG_CLUSTERED: u8 = 0b0010_0000; // bit 3: multiple hosts share this domain
128    const FLAG_NAT: u8 = 0b0001_0000; // bit 4: endpoint is behind NAT, agent address present
129    const FLAG_LOAD: u8 = 0b0000_1000; // bit 5: record carries load average
130    // bit 6 (0x04): reserved
131    // bit 7 (0x02): reserved
132    const FLAG_SIGNED: u8 = 0b0000_0001; // bit 8: record carries publisher signature
133
134    pub fn direct_v4(addr: SocketAddrV4) -> Self {
135        Self {
136            flags: 0, // IPv4 direct: FAMILY=0, NAT=0
137            sequence: None,
138            load: None,
139            signature: None,
140            primary: addr.into(),
141            agent: None,
142        }
143    }
144
145    pub fn direct_v6(addr: SocketAddrV6) -> Self {
146        Self {
147            flags: Self::FLAG_FAMILY, // IPv6 direct: FAMILY=1, NAT=0
148            sequence: None,
149            load: None,
150            signature: None,
151            primary: addr.into(),
152            agent: None,
153        }
154    }
155
156    /// Create an IPv4 endpoint that requires NAT traversal.
157    /// `outer` is the public address; `agent` is the NAT helper address.
158    pub fn nat_v4(outer: SocketAddrV4, agent: SocketAddrV4) -> Self {
159        Self {
160            flags: Self::FLAG_NAT, // IPv4 NAT: FAMILY=0, NAT=1
161            sequence: None,
162            load: None,
163            signature: None,
164            primary: outer.into(),
165            agent: Some(agent.into()),
166        }
167    }
168
169    /// Create an IPv6 endpoint that requires NAT traversal.
170    /// `outer` is the public address; `agent` is the NAT helper address.
171    pub fn nat_v6(outer: SocketAddrV6, agent: SocketAddrV6) -> Self {
172        Self {
173            flags: Self::FLAG_FAMILY | Self::FLAG_NAT, // IPv6 NAT: FAMILY=1, NAT=1
174            sequence: None,
175            load: None,
176            signature: None,
177            primary: outer.into(),
178            agent: Some(agent.into()),
179        }
180    }
181
182    /// Returns true if the address family is IPv6.
183    pub fn is_ipv6(&self) -> bool {
184        self.flags & Self::FLAG_FAMILY != 0
185    }
186
187    /// Returns true if NAT traversal is required (agent address is present).
188    pub fn is_nat(&self) -> bool {
189        self.flags & Self::FLAG_NAT != 0
190    }
191
192    /// Returns true if this domain maps to a cluster of hosts (sequence number is present).
193    pub fn is_clustered(&self) -> bool {
194        self.flags & Self::FLAG_CLUSTERED != 0
195    }
196
197    /// Returns true if the record carries a load average value.
198    pub fn is_load(&self) -> bool {
199        self.flags & Self::FLAG_LOAD != 0
200    }
201
202    pub fn set_clustered(&mut self, clustered: bool) {
203        if clustered {
204            self.flags |= Self::FLAG_CLUSTERED;
205        } else {
206            self.flags &= !Self::FLAG_CLUSTERED;
207            self.sequence = None; // clear sequence number
208        }
209    }
210
211    pub fn set_load(&mut self, load: Option<f32>) {
212        self.load = load;
213        if self.load.is_some() {
214            self.flags |= Self::FLAG_LOAD;
215        } else {
216            self.flags &= !Self::FLAG_LOAD;
217        }
218    }
219
220    pub async fn sign_with_authority(
221        &mut self,
222        authority: &(impl dhttp_identity::identity::LocalAuthority + ?Sized),
223    ) -> Result<(), SignEndpointError> {
224        self.set_signed(true);
225        let data = self.signed_data();
226
227        let scheme = authority
228            .cert_chain()
229            .first()
230            .and_then(|_| sigin::canonical_scheme_for_spki(authority.public_key()))
231            .ok_or(SignEndpointError::NoSupportedScheme)?;
232        let signature = authority
233            .sign(&data)
234            .await
235            .context(sign_endpoint_error::SignSnafu)?;
236
237        self.signature = Some(EndpointSignature {
238            scheme: u16::from(scheme),
239            signature,
240        });
241        Ok(())
242    }
243
244    pub fn verify_signature(
245        &self,
246        spki: SubjectPublicKeyInfoDer<'_>,
247    ) -> Result<bool, sigin::VerifyError> {
248        let Some(sig) = &self.signature else {
249            return Ok(false);
250        };
251        let data = self.signed_data();
252        sigin::verify(
253            spki,
254            SignatureScheme::from(sig.scheme),
255            &data,
256            &sig.signature,
257        )
258    }
259
260    pub fn verify_signature_from_der(&self, cert_der: &[u8]) -> Result<bool, sigin::VerifyError> {
261        let (_, cert) = x509_parser::parse_x509_certificate(cert_der).map_err(|e| {
262            sigin::VerifyError::InvalidCertificate {
263                details: e.to_string(),
264            }
265        })?;
266
267        let spki = SubjectPublicKeyInfoDer::from(cert.tbs_certificate.subject_pki.raw);
268        self.verify_signature(spki)
269    }
270
271    pub fn verify_signature_from_pem(&self, cert_pem: &[u8]) -> Result<bool, sigin::VerifyError> {
272        let mut reader = std::io::Cursor::new(cert_pem);
273        if let Some(item) = rustls_pemfile::certs(&mut reader).next() {
274            let cert_der = item.map_err(|e| sigin::VerifyError::InvalidPem { source: e })?;
275            return self.verify_signature_from_der(&cert_der);
276        }
277        Err(sigin::VerifyError::InvalidCertificate {
278            details: "No certificate found in PEM".to_string(),
279        })
280    }
281
282    pub fn verify_signature_from_base64(
283        &self,
284        cert_base64: &str,
285    ) -> Result<bool, sigin::VerifyError> {
286        let cert_base64 = cert_base64.trim();
287        let cert_der = base64::engine::general_purpose::STANDARD
288            .decode(cert_base64)
289            .map_err(|e| sigin::VerifyError::InvalidBase64 { source: e })?;
290        self.verify_signature_from_der(&cert_der)
291    }
292
293    pub fn verify_signature_from_file(
294        &self,
295        path: impl AsRef<Path>,
296    ) -> Result<bool, sigin::VerifyError> {
297        let contents = std::fs::read(path).map_err(|e| sigin::VerifyError::Io { source: e })?;
298        // Try PEM first
299        if let Ok(res) = self.verify_signature_from_pem(&contents) {
300            return Ok(res);
301        }
302        // If PEM failed, try DER
303        self.verify_signature_from_der(&contents)
304    }
305
306    pub fn is_main(&self) -> bool {
307        self.flags() & Self::FLAG_MAIN == Self::FLAG_MAIN
308    }
309
310    pub fn set_main(&mut self, is_main: bool) {
311        let flags = self.flags_mut();
312        if is_main {
313            *flags |= Self::FLAG_MAIN;
314        } else {
315            *flags &= !Self::FLAG_MAIN;
316        }
317    }
318
319    pub fn is_signed(&self) -> bool {
320        self.flags() & Self::FLAG_SIGNED == Self::FLAG_SIGNED
321    }
322
323    pub fn set_signed(&mut self, is_signed: bool) {
324        let flags = self.flags_mut();
325        if is_signed {
326            *flags |= Self::FLAG_SIGNED;
327        } else {
328            *flags &= !Self::FLAG_SIGNED;
329        }
330    }
331
332    pub fn encpding_size(&self) -> usize {
333        let mut meta_len = 1; // flags
334
335        // sequence is only encoded when CLUSTERED flag is set
336        if let Some(seq) = &self.sequence {
337            meta_len += VarInt::from_u32(seq.get()).encoding_size();
338        }
339
340        if self.load.is_some() {
341            meta_len += 4; // f32
342        }
343
344        if self.is_signed()
345            && let Some(sig) = &self.signature
346        {
347            let sig_len =
348                VarInt::try_from(sig.signature.len() as u64).unwrap_or(VarInt::from_u32(0));
349            meta_len += 2 + sig_len.encoding_size() + sig.signature.len();
350        }
351
352        let addr_len = match (self.is_ipv6(), self.is_nat()) {
353            (false, false) => 2 + 4,      // IPv4 direct: port + ipv4
354            (false, true) => (2 + 4) * 2, // IPv4 NAT: (port + ipv4) * 2
355            (true, false) => 2 + 16,      // IPv6 direct: port + ipv6
356            (true, true) => (2 + 16) * 2, // IPv6 NAT: (port + ipv6) * 2
357        };
358
359        meta_len + addr_len
360    }
361
362    pub fn addr(&self) -> SocketAddr {
363        self.primary
364    }
365
366    pub fn agent_addr(&self) -> Option<SocketAddr> {
367        self.agent
368    }
369
370    pub fn sequence(&self) -> Option<CertificateSequence> {
371        self.sequence
372    }
373
374    pub fn normalized_sequence(&self) -> CertificateSequence {
375        self.sequence
376            .unwrap_or_else(|| CertificateSequence::from(0u8))
377    }
378
379    pub fn set_sequence(&mut self, sequence: CertificateSequence) {
380        if sequence.get() > 0 {
381            self.sequence = Some(sequence);
382            self.set_clustered(true);
383        } else {
384            self.sequence = None;
385            self.set_clustered(false);
386        }
387    }
388
389    pub fn certificate_chain_key(&self) -> CertificateChainKey {
390        let kind = if self.is_main() {
391            CertificateChainKind::Primary
392        } else {
393            CertificateChainKind::Secondary
394        };
395        CertificateChainKey::new(self.normalized_sequence(), kind)
396    }
397
398    pub fn load(&self) -> Option<f32> {
399        self.load
400    }
401
402    fn flags(&self) -> u8 {
403        self.flags
404    }
405
406    fn flags_mut(&mut self) -> &mut u8 {
407        &mut self.flags
408    }
409
410    pub fn signature(&self) -> Option<&EndpointSignature> {
411        self.signature.as_ref()
412    }
413
414    pub fn signature_base64(&self) -> Option<String> {
415        self.signature
416            .as_ref()
417            .map(|sig| base64::engine::general_purpose::STANDARD.encode(&sig.signature))
418    }
419
420    fn write_base<B: BufMut>(&self, buf: &mut B) {
421        buf.put_u8(self.flags);
422
423        // Sequence is only written when CLUSTERED is set
424        if let Some(seq) = &self.sequence {
425            buf.put_varint(VarInt::from_u32(seq.get()));
426        }
427
428        // Write primary address
429        match self.primary {
430            SocketAddr::V4(addr) => buf.put_socket_addr_v4(&addr),
431            SocketAddr::V6(addr) => buf.put_socket_addr_v6(&addr),
432        }
433
434        // Write agent address when NAT traversal is required
435        if let Some(agent_addr) = &self.agent {
436            match agent_addr {
437                SocketAddr::V4(addr) => buf.put_socket_addr_v4(addr),
438                SocketAddr::V6(addr) => buf.put_socket_addr_v6(addr),
439            }
440        }
441
442        if let Some(load) = self.load {
443            buf.put_u32(load.to_bits());
444        }
445    }
446
447    fn signed_data(&self) -> Vec<u8> {
448        let mut unsigned = self.clone();
449        unsigned.set_signed(true);
450        unsigned.signature = None;
451        let mut buf = bytes::BytesMut::with_capacity(unsigned.encpding_size());
452        unsigned.write_base(&mut buf);
453        buf.to_vec()
454    }
455}
456
457pub(crate) trait WriteEndpointAddr {
458    fn put_endpoint_addr(&mut self, endpoint: &EndpointAddr);
459}
460
461impl<B: BufMut> WriteEndpointAddr for B {
462    fn put_endpoint_addr(&mut self, endpoint: &EndpointAddr) {
463        endpoint.write_base(self);
464        if endpoint.is_signed()
465            && let Some(sig) = endpoint.signature()
466        {
467            self.put_u16(sig.scheme);
468            let len = VarInt::try_from(sig.signature.len() as u64).unwrap_or(VarInt::from_u32(0));
469            self.put_varint(len);
470            self.put_slice(&sig.signature);
471        }
472    }
473}
474
475pub fn be_endpoint_addr(input: &[u8]) -> nom::IResult<&[u8], EndpointAddr> {
476    let (remain, flags) = be_u8(input)?;
477
478    let is_clustered = flags & EndpointAddr::FLAG_CLUSTERED != 0;
479    let is_ipv6 = flags & EndpointAddr::FLAG_FAMILY != 0;
480    let is_nat = flags & EndpointAddr::FLAG_NAT != 0;
481    let has_load = flags & EndpointAddr::FLAG_LOAD != 0;
482
483    // Sequence number is only present when CLUSTERED is set
484    let (remain, sequence) = if is_clustered {
485        let (remain, seq) = be_varint(remain)?;
486        let sequence = match CertificateSequence::try_from(seq.into_inner()) {
487            Ok(sequence) => sequence,
488            Err(_error) => {
489                return Err(nom::Err::Failure(make_error(remain, ErrorKind::TooLarge)));
490            }
491        };
492        (remain, Some(sequence))
493    } else {
494        (remain, None)
495    };
496
497    let (remain, primary) = if is_ipv6 {
498        let (remain, addr) = be_socket_addr_v6(remain)?;
499        (remain, SocketAddr::V6(addr))
500    } else {
501        let (remain, addr) = be_socket_addr_v4(remain)?;
502        (remain, SocketAddr::V4(addr))
503    };
504
505    let (remain, agent) = if is_nat {
506        let agent_addr = if is_ipv6 {
507            let (remain, addr) = be_socket_addr_v6(remain)?;
508            (remain, SocketAddr::V6(addr))
509        } else {
510            let (remain, addr) = be_socket_addr_v4(remain)?;
511            (remain, SocketAddr::V4(addr))
512        };
513        let (remain, addr) = agent_addr;
514        (remain, Some(addr))
515    } else {
516        (remain, None)
517    };
518
519    let (remain, load) = if has_load {
520        let (remain, load) = be_u32(remain)?;
521        (remain, Some(f32::from_bits(load)))
522    } else {
523        (remain, None)
524    };
525
526    let (remain, signature) = be_endpoint_signature(remain, flags)?;
527
528    Ok((
529        remain,
530        EndpointAddr {
531            flags,
532            sequence,
533            load,
534            signature,
535            primary,
536            agent,
537        },
538    ))
539}
540
541/// Parse an EndpointAddr with backward compatibility.
542///
543/// - If `rdlen` matches a legacy fixed length, parse as address-only and fill in default flags.
544/// - Otherwise parse as the modern format (with `flags` + optional fields).
545///
546/// Note: Legacy and modern records differ in their leading bytes.
547/// Disambiguation is done via `RDLENGTH` to avoid misinterpreting the port's high byte as `flags`.
548pub(crate) fn be_endpoint_addr_compat(
549    input: &[u8],
550    rdlen: u16,
551) -> nom::IResult<&[u8], EndpointAddr> {
552    // Check for legacy fixed lengths
553    let legacy_lengths = [
554        6,  // IPv4 direct: port(2) + ip(4)
555        12, // IPv4 NAT:    (port(2) + ip(4)) * 2
556        18, // IPv6 direct: port(2) + ip(16)
557        36, // IPv6 NAT:    (port(2) + ip(16)) * 2
558    ];
559
560    if legacy_lengths.contains(&(rdlen as usize)) {
561        // Modern records have variable length, so a valid modern encoding can
562        // legitimately be 12, 18, or 36 bytes as well. Prefer a complete
563        // modern parse and only fall back to the legacy layout when it fails.
564        if let Ok((remaining, endpoint)) = be_endpoint_addr(input)
565            && remaining.is_empty()
566        {
567            return Ok((remaining, endpoint));
568        }
569        return be_legacy_endpoint_addr_by_length(input, rdlen);
570    }
571
572    // Modern format
573    be_endpoint_addr(input)
574}
575
576/// Parse a legacy EndpointAddr record, identified by its fixed RDLENGTH.
577fn be_legacy_endpoint_addr_by_length(
578    input: &[u8],
579    rdlen: u16,
580) -> nom::IResult<&[u8], EndpointAddr> {
581    match rdlen {
582        6 => {
583            // IPv4 direct
584            let (remain, addr) = be_socket_addr_v4(input)?;
585            Ok((
586                remain,
587                EndpointAddr {
588                    flags: 0,
589                    sequence: None,
590                    load: None,
591                    signature: None,
592                    primary: addr.into(),
593                    agent: None,
594                },
595            ))
596        }
597        12 => {
598            // IPv4 NAT
599            let (remain, primary) = be_socket_addr_v4(input)?;
600            let (remain, agent) = be_socket_addr_v4(remain)?;
601            Ok((
602                remain,
603                EndpointAddr {
604                    flags: EndpointAddr::FLAG_NAT,
605                    sequence: None,
606                    load: None,
607                    signature: None,
608                    primary: primary.into(),
609                    agent: Some(agent.into()),
610                },
611            ))
612        }
613        18 => {
614            // IPv6 direct
615            let (remain, addr) = be_socket_addr_v6(input)?;
616            Ok((
617                remain,
618                EndpointAddr {
619                    flags: EndpointAddr::FLAG_FAMILY,
620                    sequence: None,
621                    load: None,
622                    signature: None,
623                    primary: addr.into(),
624                    agent: None,
625                },
626            ))
627        }
628        36 => {
629            // IPv6 NAT
630            let (remain, primary) = be_socket_addr_v6(input)?;
631            let (remain, agent) = be_socket_addr_v6(remain)?;
632            Ok((
633                remain,
634                EndpointAddr {
635                    flags: EndpointAddr::FLAG_FAMILY | EndpointAddr::FLAG_NAT,
636                    sequence: None,
637                    load: None,
638                    signature: None,
639                    primary: primary.into(),
640                    agent: Some(agent.into()),
641                },
642            ))
643        }
644        _ => Err(nom::Err::Error(nom::error::make_error(
645            input,
646            nom::error::ErrorKind::LengthValue,
647        ))),
648    }
649}
650
651fn be_endpoint_signature(input: &[u8], flags: u8) -> IResult<&[u8], Option<EndpointSignature>> {
652    if (flags & EndpointAddr::FLAG_SIGNED) != EndpointAddr::FLAG_SIGNED {
653        if !input.is_empty() {
654            return Err(nom::Err::Error(make_error(input, ErrorKind::Eof)));
655        }
656        return Ok((input, None));
657    }
658
659    let (remain, scheme_u16) = be_u16(input)?;
660    let (remain, sig_len) = be_varint(remain)?;
661    let sig_len = usize::try_from(sig_len.into_inner())
662        .map_err(|_| nom::Err::Error(make_error(remain, ErrorKind::TooLarge)))?;
663    let (remain, sig) = take(sig_len)(remain)?;
664    Ok((
665        remain,
666        Some(EndpointSignature {
667            scheme: scheme_u16,
668            signature: sig.to_vec(),
669        }),
670    ))
671}
672
673pub trait WriteSocketAddr {
674    fn put_socket_addr_v4(&mut self, addr: &SocketAddrV4);
675
676    fn put_socket_addr_v6(&mut self, addr: &SocketAddrV6);
677
678    fn put_socket_addr(&mut self, addr: &SocketAddr) {
679        match addr {
680            SocketAddr::V4(v4) => self.put_socket_addr_v4(v4),
681            SocketAddr::V6(v6) => self.put_socket_addr_v6(v6),
682        }
683    }
684}
685
686impl<T: BufMut> WriteSocketAddr for T {
687    fn put_socket_addr_v4(&mut self, addr: &SocketAddrV4) {
688        self.put_u16(addr.port());
689        self.put_u32(u32::from(*addr.ip()));
690    }
691
692    fn put_socket_addr_v6(&mut self, addr: &SocketAddrV6) {
693        self.put_u16(addr.port());
694        self.put_u128(u128::from(*addr.ip()));
695    }
696}
697
698pub fn be_socket_addr_v4(input: &[u8]) -> IResult<&[u8], SocketAddrV4> {
699    flat_map(be_u16, |port| {
700        map(be_ipv4_addr, move |ip| SocketAddrV4::new(ip, port))
701    })
702    .parse(input)
703}
704
705pub fn be_socket_addr_v6(input: &[u8]) -> IResult<&[u8], SocketAddrV6> {
706    flat_map(be_u16, |port| {
707        map(be_ipv6_addr, move |ip| SocketAddrV6::new(ip, port, 0, 0))
708    })
709    .parse(input)
710}
711
712pub fn be_ipv4_addr(input: &[u8]) -> IResult<&[u8], Ipv4Addr> {
713    map(be_u32, Ipv4Addr::from).parse(input)
714}
715
716pub fn be_ipv6_addr(input: &[u8]) -> IResult<&[u8], Ipv6Addr> {
717    map(be_u128, Ipv6Addr::from).parse(input)
718}
719
720pub fn be_ip_addr(is_v6: bool) -> impl Fn(&[u8]) -> IResult<&[u8], IpAddr> {
721    move |input| match is_v6 {
722        true => map(be_u128, |ip| IpAddr::V6(Ipv6Addr::from(ip))).parse(input),
723        false => map(be_u32, |ip| IpAddr::V4(Ipv4Addr::from(ip))).parse(input),
724    }
725}
726
727impl Display for EndpointAddr {
728    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
729        if let Some(agent_addr) = &self.agent {
730            write!(f, "{}-{agent_addr}", self.primary)
731        } else {
732            write!(f, "{}", self.primary)
733        }
734    }
735}
736
737impl TryFrom<DquicEndpointAddr> for EndpointAddr {
738    type Error = ();
739
740    fn try_from(value: DquicEndpointAddr) -> Result<Self, Self::Error> {
741        match value {
742            DquicEndpointAddr::Direct {
743                addr: SocketAddr::V4(addr),
744            } => Ok(Self::direct_v4(addr)),
745            DquicEndpointAddr::Direct {
746                addr: SocketAddr::V6(addr),
747            } => Ok(Self::direct_v6(addr)),
748            DquicEndpointAddr::Agent {
749                agent: SocketAddr::V4(agent),
750                outer: SocketAddr::V4(outer),
751            } => Ok(Self::nat_v4(outer, agent)),
752            DquicEndpointAddr::Agent {
753                agent: SocketAddr::V6(agent),
754                outer: SocketAddr::V6(outer),
755            } => Ok(Self::nat_v6(outer, agent)),
756            _ => Err(()),
757        }
758    }
759}
760
761impl TryFrom<EndpointAddr> for DquicEndpointAddr {
762    type Error = ();
763
764    fn try_from(value: EndpointAddr) -> Result<Self, Self::Error> {
765        if let Some(agent_addr) = value.agent {
766            match (value.primary, agent_addr) {
767                (SocketAddr::V4(outer), SocketAddr::V4(agent)) => Ok(DquicEndpointAddr::Agent {
768                    outer: SocketAddr::V4(outer),
769                    agent: SocketAddr::V4(agent),
770                }),
771                (SocketAddr::V6(outer), SocketAddr::V6(agent)) => Ok(DquicEndpointAddr::Agent {
772                    outer: SocketAddr::V6(outer),
773                    agent: SocketAddr::V6(agent),
774                }),
775                _ => Err(()),
776            }
777        } else {
778            match value.primary {
779                SocketAddr::V4(addr) => Ok(DquicEndpointAddr::Direct {
780                    addr: SocketAddr::V4(addr),
781                }),
782                SocketAddr::V6(addr) => Ok(DquicEndpointAddr::Direct {
783                    addr: SocketAddr::V6(addr),
784                }),
785            }
786        }
787    }
788}
789
790pub async fn sign_endponit_address(
791    server_id: u8,
792    authority: Option<&(impl dhttp_identity::identity::LocalAuthority + ?Sized)>,
793    endpoint: DquicEndpointAddr,
794) -> Option<EndpointAddr> {
795    let mut ep: EndpointAddr = endpoint.try_into().ok()?;
796    ep.set_main(server_id == 0);
797    ep.set_sequence(CertificateSequence::from(server_id));
798    if let Some(authority) = authority {
799        let _ = ep.sign_with_authority(authority).await;
800    }
801    Some(ep)
802}
803
804#[cfg(test)]
805mod tests {
806    use std::{
807        net::{Ipv4Addr, Ipv6Addr},
808        sync::Arc,
809    };
810
811    use bytes::BytesMut;
812    use futures::future::BoxFuture;
813    use ring::signature::KeyPair;
814    use rustls::sign::{Signer, SigningKey};
815
816    use super::*;
817
818    fn v4_outer() -> SocketAddrV4 {
819        SocketAddrV4::new(Ipv4Addr::new(203, 0, 113, 10), 4433)
820    }
821
822    #[test]
823    fn endpoint_certificate_chain_key_normalizes_missing_sequence() {
824        let mut endpoint = EndpointAddr::direct_v4(v4_outer());
825        endpoint.set_main(true);
826
827        let key = endpoint.certificate_chain_key();
828
829        assert_eq!(
830            key.kind(),
831            dhttp_identity::certificate::CertificateChainKind::Primary
832        );
833        assert_eq!(key.sequence().get(), 0);
834        assert_eq!(key.to_string(), "primary:0");
835    }
836
837    #[test]
838    fn endpoint_certificate_chain_key_uses_present_sequence() {
839        let mut endpoint = EndpointAddr::direct_v4(v4_outer());
840        endpoint.set_main(false);
841        endpoint.set_sequence(
842            dhttp_identity::certificate::CertificateSequence::try_from(7u32).unwrap(),
843        );
844
845        let key = endpoint.certificate_chain_key();
846
847        assert_eq!(
848            key.kind(),
849            dhttp_identity::certificate::CertificateChainKind::Secondary
850        );
851        assert_eq!(key.sequence().get(), 7);
852        assert_eq!(key.to_string(), "secondary:7");
853    }
854
855    #[test]
856    fn endpoint_parser_rejects_over_range_certificate_sequence() {
857        let sequence = crate::core::parser::varint::VarInt::from_u64(
858            dhttp_identity::certificate::CertificateSequence::MAX as u64 + 1,
859        )
860        .unwrap();
861        let mut packet = BytesMut::new();
862        packet.put_u8(EndpointAddr::FLAG_MAIN | EndpointAddr::FLAG_CLUSTERED);
863        packet.put_varint(sequence);
864        packet.put_u16(v4_outer().port());
865        packet.put_slice(&v4_outer().ip().octets());
866
867        assert!(be_endpoint_addr(&packet).is_err());
868    }
869
870    #[test]
871    fn legacy_endpoint_v4_direct_without_meta() {
872        let port = 5353u16;
873        let ip = Ipv4Addr::new(10, 0, 0, 1);
874        let mut buf = BytesMut::new();
875        buf.extend_from_slice(&port.to_be_bytes());
876        buf.extend_from_slice(&u32::from(ip).to_be_bytes());
877        let (remain, decoded) = be_endpoint_addr_compat(&buf, 6).unwrap();
878        assert!(remain.is_empty());
879        assert_eq!(
880            decoded,
881            EndpointAddr::direct_v4(SocketAddrV4::new(ip, port))
882        );
883    }
884
885    #[test]
886    fn legacy_endpoint_v4_nat_without_meta() {
887        let outer = SocketAddrV4::new(Ipv4Addr::new(10, 0, 0, 1), 1000);
888        let agent = SocketAddrV4::new(Ipv4Addr::new(10, 0, 0, 2), 2000);
889        let mut buf = BytesMut::new();
890        buf.extend_from_slice(&outer.port().to_be_bytes());
891        buf.extend_from_slice(&u32::from(*outer.ip()).to_be_bytes());
892        buf.extend_from_slice(&agent.port().to_be_bytes());
893        buf.extend_from_slice(&u32::from(*agent.ip()).to_be_bytes());
894        let (remain, decoded) = be_endpoint_addr_compat(&buf, 12).unwrap();
895        assert!(remain.is_empty());
896        assert_eq!(decoded, EndpointAddr::nat_v4(outer, agent));
897    }
898
899    #[test]
900    fn flag_bit_ops_work() {
901        let addr = SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), 5353);
902        let mut ep = EndpointAddr {
903            flags: 0b0011_0000,
904            sequence: None,
905            load: None,
906            signature: None,
907            primary: addr.into(),
908            agent: None,
909        };
910
911        assert!(!ep.is_main());
912        assert!(!ep.is_signed());
913
914        ep.set_main(true);
915        assert!(ep.is_main());
916        assert_eq!(ep.flags, 0b0111_0000);
917
918        ep.set_signed(true);
919        assert!(ep.is_signed());
920        assert_eq!(ep.flags, 0b0111_0001);
921
922        ep.set_main(false);
923        assert!(!ep.is_main());
924        assert!(ep.is_signed());
925        assert_eq!(ep.flags, 0b0011_0001);
926
927        ep.set_signed(false);
928        assert!(!ep.is_signed());
929        assert_eq!(ep.flags, 0b0011_0000);
930    }
931
932    #[test]
933    fn varint_roundtrip_and_len() {
934        fn roundtrip(v: u64) {
935            let v = VarInt::from_u64(v).unwrap();
936            let mut buf = BytesMut::new();
937            buf.put_varint(v);
938            assert_eq!(buf.len(), v.encoding_size());
939            let (remain, decoded) = be_varint(&buf).unwrap();
940            assert!(remain.is_empty());
941            assert_eq!(decoded, v);
942        }
943
944        for v in [
945            0u64,
946            1,
947            63,
948            64,
949            16383,
950            16384,
951            (1 << 30) - 1,
952            1 << 30,
953            (1 << 62) - 1,
954        ] {
955            roundtrip(v);
956        }
957    }
958
959    #[test]
960    fn varint_rejects_overflow_and_incomplete() {
961        assert!(VarInt::from_u64((1 << 62) + 1).is_err());
962
963        let incomplete = [0b01_000000u8];
964        match be_varint(&incomplete) {
965            Err(nom::Err::Incomplete(_)) => {}
966            other => panic!("expected Incomplete, got {other:?}"),
967        }
968    }
969
970    #[test]
971    fn endpoint_encode_decode_roundtrip() {
972        let v4_outer = SocketAddrV4::new(Ipv4Addr::new(10, 0, 0, 1), 1000);
973        let v4_agent = SocketAddrV4::new(Ipv4Addr::new(10, 0, 0, 2), 2000);
974        let v6_outer = SocketAddrV6::new(Ipv6Addr::LOCALHOST, 3000, 0, 0);
975        let v6_agent = SocketAddrV6::new(Ipv6Addr::LOCALHOST, 4000, 0, 0);
976
977        let mut with_load = EndpointAddr::direct_v4(v4_outer);
978        with_load.set_load(Some(0.42_f32));
979
980        let cases = vec![
981            // IPv4 direct, MAIN + CLUSTERED flags
982            EndpointAddr {
983                flags: EndpointAddr::FLAG_MAIN | EndpointAddr::FLAG_CLUSTERED,
984                sequence: Some(CertificateSequence::from(0u8)),
985                load: None,
986                signature: None,
987                primary: v4_outer.into(),
988                agent: None,
989            },
990            // IPv4 NAT, CLUSTERED flag
991            EndpointAddr {
992                flags: EndpointAddr::FLAG_NAT | EndpointAddr::FLAG_CLUSTERED,
993                sequence: Some(CertificateSequence::try_from(127u32).unwrap()),
994                load: None,
995                signature: None,
996                primary: v4_outer.into(),
997                agent: Some(v4_agent.into()),
998            },
999            // IPv6 direct, MAIN + CLUSTERED flags
1000            EndpointAddr {
1001                flags: EndpointAddr::FLAG_FAMILY
1002                    | EndpointAddr::FLAG_MAIN
1003                    | EndpointAddr::FLAG_CLUSTERED,
1004                sequence: Some(CertificateSequence::try_from(128u32).unwrap()),
1005                load: None,
1006                signature: None,
1007                primary: v6_outer.into(),
1008                agent: None,
1009            },
1010            // IPv6 NAT, CLUSTERED flag
1011            EndpointAddr {
1012                flags: EndpointAddr::FLAG_FAMILY
1013                    | EndpointAddr::FLAG_NAT
1014                    | EndpointAddr::FLAG_CLUSTERED,
1015                sequence: Some(CertificateSequence::try_from(16_384u32).unwrap()),
1016                load: None,
1017                signature: None,
1018                primary: v6_outer.into(),
1019                agent: Some(v6_agent.into()),
1020            },
1021            // IPv4 direct with LOAD
1022            with_load,
1023        ];
1024
1025        for ep in cases {
1026            let mut buf = BytesMut::new();
1027            buf.put_endpoint_addr(&ep);
1028            assert_eq!(buf.len(), ep.encpding_size());
1029
1030            let (remain, decoded) = be_endpoint_addr(&buf).unwrap();
1031            assert!(remain.is_empty());
1032            assert_eq!(decoded, ep);
1033        }
1034    }
1035
1036    #[test]
1037    fn compat_parser_does_not_misclassify_modern_lengths_as_legacy() {
1038        let mut direct = EndpointAddr::direct_v4("203.0.113.10:4433".parse().unwrap());
1039        direct.set_main(true);
1040        direct.set_sequence(CertificateSequence::try_from(10u32).unwrap());
1041        direct.set_load(Some(1.0));
1042
1043        let mut nat = EndpointAddr::nat_v4(
1044            "198.51.100.10:4433".parse().unwrap(),
1045            "192.0.2.10:4433".parse().unwrap(),
1046        );
1047        nat.set_main(true);
1048        nat.set_sequence(CertificateSequence::from(1u8));
1049        nat.set_load(Some(2.0));
1050
1051        for endpoint in [direct, nat] {
1052            let mut buf = BytesMut::new();
1053            buf.put_endpoint_addr(&endpoint);
1054            assert!([12, 18].contains(&buf.len()));
1055
1056            let (remaining, decoded) =
1057                be_endpoint_addr_compat(&buf, u16::try_from(buf.len()).unwrap()).unwrap();
1058            assert!(remaining.is_empty());
1059            assert_eq!(decoded, endpoint);
1060        }
1061    }
1062
1063    #[test]
1064    fn endpoint_signature_roundtrip_and_verify() {
1065        #[derive(Debug)]
1066        struct Ed25519Key {
1067            keypair: Arc<ring::signature::Ed25519KeyPair>,
1068            cert_chain: Vec<rustls::pki_types::CertificateDer<'static>>,
1069        }
1070
1071        #[derive(Debug)]
1072        struct Ed25519Signer(Arc<ring::signature::Ed25519KeyPair>);
1073
1074        impl Signer for Ed25519Signer {
1075            fn sign(&self, message: &[u8]) -> Result<Vec<u8>, rustls::Error> {
1076                Ok(self.0.sign(message).as_ref().to_vec())
1077            }
1078
1079            fn scheme(&self) -> SignatureScheme {
1080                SignatureScheme::ED25519
1081            }
1082        }
1083
1084        impl SigningKey for Ed25519Key {
1085            fn choose_scheme(&self, offered: &[SignatureScheme]) -> Option<Box<dyn Signer>> {
1086                offered
1087                    .contains(&SignatureScheme::ED25519)
1088                    .then(|| Box::new(Ed25519Signer(self.keypair.clone())) as Box<dyn Signer>)
1089            }
1090
1091            fn algorithm(&self) -> rustls::SignatureAlgorithm {
1092                rustls::SignatureAlgorithm::ED25519
1093            }
1094        }
1095
1096        impl dhttp_identity::identity::LocalAuthority for Ed25519Key {
1097            fn name(&self) -> &str {
1098                "authority.example"
1099            }
1100
1101            fn cert_chain(&self) -> &[rustls::pki_types::CertificateDer<'static>] {
1102                &self.cert_chain
1103            }
1104
1105            fn sign(
1106                &self,
1107                data: &[u8],
1108            ) -> BoxFuture<'_, Result<Vec<u8>, dhttp_identity::identity::SignError>> {
1109                let result = dhttp_identity::identity::sign_with_key(self, data);
1110                Box::pin(std::future::ready(result))
1111            }
1112        }
1113
1114        let rng = ring::rand::SystemRandom::new();
1115        let pkcs8 = ring::signature::Ed25519KeyPair::generate_pkcs8(&rng).unwrap();
1116        let keypair =
1117            Arc::new(ring::signature::Ed25519KeyPair::from_pkcs8(pkcs8.as_ref()).unwrap());
1118        let mut spki = Vec::with_capacity(44);
1119        spki.extend_from_slice(&[
1120            0x30, 0x2a, 0x30, 0x05, 0x06, 0x03, 0x2b, 0x65, 0x70, 0x03, 0x21, 0x00,
1121        ]);
1122        spki.extend_from_slice(keypair.public_key().as_ref());
1123        let key = Ed25519Key {
1124            keypair: keypair.clone(),
1125            cert_chain: vec![rustls::pki_types::CertificateDer::from(spki.clone())],
1126        };
1127
1128        let addr = SocketAddrV4::new(Ipv4Addr::new(10, 0, 0, 1), 5353);
1129        let mut ep = EndpointAddr::direct_v4(addr);
1130        ep.set_main(true);
1131        futures::executor::block_on(ep.sign_with_authority(&key)).unwrap();
1132
1133        let mut buf = BytesMut::new();
1134        buf.put_endpoint_addr(&ep);
1135        assert_eq!(buf.len(), ep.encpding_size());
1136
1137        let (remain, decoded) = be_endpoint_addr(&buf).unwrap();
1138        assert!(remain.is_empty());
1139        assert!(decoded.is_signed());
1140        assert!(decoded.signature().is_some());
1141        assert!(
1142            decoded
1143                .verify_signature(SubjectPublicKeyInfoDer::from(spki.as_slice()))
1144                .unwrap()
1145        );
1146
1147        let mut tampered = decoded.clone();
1148        tampered.set_main(false);
1149        assert!(
1150            !tampered
1151                .verify_signature(SubjectPublicKeyInfoDer::from(spki.as_slice()))
1152                .unwrap()
1153        );
1154    }
1155
1156    #[test]
1157    fn sign_with_authority_uses_canonical_scheme_from_public_key() {
1158        #[derive(Debug)]
1159        struct Ed25519Authority {
1160            cert_chain: Vec<rustls::pki_types::CertificateDer<'static>>,
1161        }
1162
1163        impl dhttp_identity::identity::LocalAuthority for Ed25519Authority {
1164            fn name(&self) -> &str {
1165                "authority.example"
1166            }
1167
1168            fn cert_chain(&self) -> &[rustls::pki_types::CertificateDer<'static>] {
1169                &self.cert_chain
1170            }
1171
1172            fn sign(
1173                &self,
1174                _data: &[u8],
1175            ) -> BoxFuture<'_, Result<Vec<u8>, dhttp_identity::identity::SignError>> {
1176                Box::pin(async move { Ok(vec![1, 2, 3]) })
1177            }
1178        }
1179
1180        let cert_chain = vec![rustls::pki_types::CertificateDer::from(vec![
1181            0x30, 0x2a, 0x30, 0x05, 0x06, 0x03, 0x2b, 0x65, 0x70, 0x03, 0x21, 0x00, 0, 0, 0, 0, 0,
1182            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1183        ])];
1184        let mut ep = EndpointAddr::direct_v4(SocketAddrV4::new(Ipv4Addr::LOCALHOST, 5353));
1185        futures::executor::block_on(ep.sign_with_authority(&Ed25519Authority { cert_chain }))
1186            .unwrap();
1187
1188        let signature = ep.signature().unwrap();
1189        assert_eq!(
1190            SignatureScheme::from(signature.scheme),
1191            SignatureScheme::ED25519
1192        );
1193        assert_eq!(signature.signature, vec![1, 2, 3]);
1194    }
1195
1196    #[test]
1197    fn optional_fields_flags_follow_values() {
1198        let addr = SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), 5353);
1199        let mut ep = EndpointAddr::direct_v4(addr);
1200
1201        assert!(!ep.is_load());
1202
1203        ep.set_load(Some(0.5_f32));
1204
1205        assert!(ep.is_load());
1206        assert_eq!(ep.load(), Some(0.5_f32));
1207
1208        ep.set_load(None);
1209
1210        assert!(!ep.is_load());
1211        assert_eq!(ep.load(), None);
1212    }
1213}