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, 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        if self.is_main() {
391            crate::core::certificate::primary_chain_key(self.normalized_sequence())
392        } else {
393            crate::core::certificate::secondary_chain_key(self.normalized_sequence())
394        }
395    }
396
397    pub fn load(&self) -> Option<f32> {
398        self.load
399    }
400
401    fn flags(&self) -> u8 {
402        self.flags
403    }
404
405    fn flags_mut(&mut self) -> &mut u8 {
406        &mut self.flags
407    }
408
409    pub fn signature(&self) -> Option<&EndpointSignature> {
410        self.signature.as_ref()
411    }
412
413    pub fn signature_base64(&self) -> Option<String> {
414        self.signature
415            .as_ref()
416            .map(|sig| base64::engine::general_purpose::STANDARD.encode(&sig.signature))
417    }
418
419    fn write_base<B: BufMut>(&self, buf: &mut B) {
420        buf.put_u8(self.flags);
421
422        // Sequence is only written when CLUSTERED is set
423        if let Some(seq) = &self.sequence {
424            buf.put_varint(VarInt::from_u32(seq.get()));
425        }
426
427        // Write primary address
428        match self.primary {
429            SocketAddr::V4(addr) => buf.put_socket_addr_v4(&addr),
430            SocketAddr::V6(addr) => buf.put_socket_addr_v6(&addr),
431        }
432
433        // Write agent address when NAT traversal is required
434        if let Some(agent_addr) = &self.agent {
435            match agent_addr {
436                SocketAddr::V4(addr) => buf.put_socket_addr_v4(addr),
437                SocketAddr::V6(addr) => buf.put_socket_addr_v6(addr),
438            }
439        }
440
441        if let Some(load) = self.load {
442            buf.put_u32(load.to_bits());
443        }
444    }
445
446    fn signed_data(&self) -> Vec<u8> {
447        let mut unsigned = self.clone();
448        unsigned.set_signed(true);
449        unsigned.signature = None;
450        let mut buf = bytes::BytesMut::with_capacity(unsigned.encpding_size());
451        unsigned.write_base(&mut buf);
452        buf.to_vec()
453    }
454}
455
456pub(crate) trait WriteEndpointAddr {
457    fn put_endpoint_addr(&mut self, endpoint: &EndpointAddr);
458}
459
460impl<B: BufMut> WriteEndpointAddr for B {
461    fn put_endpoint_addr(&mut self, endpoint: &EndpointAddr) {
462        endpoint.write_base(self);
463        if endpoint.is_signed()
464            && let Some(sig) = endpoint.signature()
465        {
466            self.put_u16(sig.scheme);
467            let len = VarInt::try_from(sig.signature.len() as u64).unwrap_or(VarInt::from_u32(0));
468            self.put_varint(len);
469            self.put_slice(&sig.signature);
470        }
471    }
472}
473
474pub fn be_endpoint_addr(input: &[u8]) -> nom::IResult<&[u8], EndpointAddr> {
475    let (remain, flags) = be_u8(input)?;
476
477    let is_clustered = flags & EndpointAddr::FLAG_CLUSTERED != 0;
478    let is_ipv6 = flags & EndpointAddr::FLAG_FAMILY != 0;
479    let is_nat = flags & EndpointAddr::FLAG_NAT != 0;
480    let has_load = flags & EndpointAddr::FLAG_LOAD != 0;
481
482    // Sequence number is only present when CLUSTERED is set
483    let (remain, sequence) = if is_clustered {
484        let (remain, seq) = be_varint(remain)?;
485        let sequence = match CertificateSequence::try_from(seq.into_inner()) {
486            Ok(sequence) => sequence,
487            Err(_error) => {
488                return Err(nom::Err::Failure(make_error(remain, ErrorKind::TooLarge)));
489            }
490        };
491        (remain, Some(sequence))
492    } else {
493        (remain, None)
494    };
495
496    let (remain, primary) = if is_ipv6 {
497        let (remain, addr) = be_socket_addr_v6(remain)?;
498        (remain, SocketAddr::V6(addr))
499    } else {
500        let (remain, addr) = be_socket_addr_v4(remain)?;
501        (remain, SocketAddr::V4(addr))
502    };
503
504    let (remain, agent) = if is_nat {
505        let agent_addr = if is_ipv6 {
506            let (remain, addr) = be_socket_addr_v6(remain)?;
507            (remain, SocketAddr::V6(addr))
508        } else {
509            let (remain, addr) = be_socket_addr_v4(remain)?;
510            (remain, SocketAddr::V4(addr))
511        };
512        let (remain, addr) = agent_addr;
513        (remain, Some(addr))
514    } else {
515        (remain, None)
516    };
517
518    let (remain, load) = if has_load {
519        let (remain, load) = be_u32(remain)?;
520        (remain, Some(f32::from_bits(load)))
521    } else {
522        (remain, None)
523    };
524
525    let (remain, signature) = be_endpoint_signature(remain, flags)?;
526
527    Ok((
528        remain,
529        EndpointAddr {
530            flags,
531            sequence,
532            load,
533            signature,
534            primary,
535            agent,
536        },
537    ))
538}
539
540/// Parse an EndpointAddr with backward compatibility.
541///
542/// - If `rdlen` matches a legacy fixed length, parse as address-only and fill in default flags.
543/// - Otherwise parse as the modern format (with `flags` + optional fields).
544///
545/// Note: Legacy and modern records differ in their leading bytes.
546/// Disambiguation is done via `RDLENGTH` to avoid misinterpreting the port's high byte as `flags`.
547pub(crate) fn be_endpoint_addr_compat(
548    input: &[u8],
549    rdlen: u16,
550) -> nom::IResult<&[u8], EndpointAddr> {
551    // Check for legacy fixed lengths
552    let legacy_lengths = [
553        6,  // IPv4 direct: port(2) + ip(4)
554        12, // IPv4 NAT:    (port(2) + ip(4)) * 2
555        18, // IPv6 direct: port(2) + ip(16)
556        36, // IPv6 NAT:    (port(2) + ip(16)) * 2
557    ];
558
559    if legacy_lengths.contains(&(rdlen as usize)) {
560        // Modern records have variable length, so a valid modern encoding can
561        // legitimately be 12, 18, or 36 bytes as well. Prefer a complete
562        // modern parse and only fall back to the legacy layout when it fails.
563        if let Ok((remaining, endpoint)) = be_endpoint_addr(input)
564            && remaining.is_empty()
565        {
566            return Ok((remaining, endpoint));
567        }
568        return be_legacy_endpoint_addr_by_length(input, rdlen);
569    }
570
571    // Modern format
572    be_endpoint_addr(input)
573}
574
575/// Parse a legacy EndpointAddr record, identified by its fixed RDLENGTH.
576fn be_legacy_endpoint_addr_by_length(
577    input: &[u8],
578    rdlen: u16,
579) -> nom::IResult<&[u8], EndpointAddr> {
580    match rdlen {
581        6 => {
582            // IPv4 direct
583            let (remain, addr) = be_socket_addr_v4(input)?;
584            Ok((
585                remain,
586                EndpointAddr {
587                    flags: 0,
588                    sequence: None,
589                    load: None,
590                    signature: None,
591                    primary: addr.into(),
592                    agent: None,
593                },
594            ))
595        }
596        12 => {
597            // IPv4 NAT
598            let (remain, primary) = be_socket_addr_v4(input)?;
599            let (remain, agent) = be_socket_addr_v4(remain)?;
600            Ok((
601                remain,
602                EndpointAddr {
603                    flags: EndpointAddr::FLAG_NAT,
604                    sequence: None,
605                    load: None,
606                    signature: None,
607                    primary: primary.into(),
608                    agent: Some(agent.into()),
609                },
610            ))
611        }
612        18 => {
613            // IPv6 direct
614            let (remain, addr) = be_socket_addr_v6(input)?;
615            Ok((
616                remain,
617                EndpointAddr {
618                    flags: EndpointAddr::FLAG_FAMILY,
619                    sequence: None,
620                    load: None,
621                    signature: None,
622                    primary: addr.into(),
623                    agent: None,
624                },
625            ))
626        }
627        36 => {
628            // IPv6 NAT
629            let (remain, primary) = be_socket_addr_v6(input)?;
630            let (remain, agent) = be_socket_addr_v6(remain)?;
631            Ok((
632                remain,
633                EndpointAddr {
634                    flags: EndpointAddr::FLAG_FAMILY | EndpointAddr::FLAG_NAT,
635                    sequence: None,
636                    load: None,
637                    signature: None,
638                    primary: primary.into(),
639                    agent: Some(agent.into()),
640                },
641            ))
642        }
643        _ => Err(nom::Err::Error(nom::error::make_error(
644            input,
645            nom::error::ErrorKind::LengthValue,
646        ))),
647    }
648}
649
650fn be_endpoint_signature(input: &[u8], flags: u8) -> IResult<&[u8], Option<EndpointSignature>> {
651    if (flags & EndpointAddr::FLAG_SIGNED) != EndpointAddr::FLAG_SIGNED {
652        if !input.is_empty() {
653            return Err(nom::Err::Error(make_error(input, ErrorKind::Eof)));
654        }
655        return Ok((input, None));
656    }
657
658    let (remain, scheme_u16) = be_u16(input)?;
659    let (remain, sig_len) = be_varint(remain)?;
660    let sig_len = usize::try_from(sig_len.into_inner())
661        .map_err(|_| nom::Err::Error(make_error(remain, ErrorKind::TooLarge)))?;
662    let (remain, sig) = take(sig_len)(remain)?;
663    Ok((
664        remain,
665        Some(EndpointSignature {
666            scheme: scheme_u16,
667            signature: sig.to_vec(),
668        }),
669    ))
670}
671
672pub trait WriteSocketAddr {
673    fn put_socket_addr_v4(&mut self, addr: &SocketAddrV4);
674
675    fn put_socket_addr_v6(&mut self, addr: &SocketAddrV6);
676
677    fn put_socket_addr(&mut self, addr: &SocketAddr) {
678        match addr {
679            SocketAddr::V4(v4) => self.put_socket_addr_v4(v4),
680            SocketAddr::V6(v6) => self.put_socket_addr_v6(v6),
681        }
682    }
683}
684
685impl<T: BufMut> WriteSocketAddr for T {
686    fn put_socket_addr_v4(&mut self, addr: &SocketAddrV4) {
687        self.put_u16(addr.port());
688        self.put_u32(u32::from(*addr.ip()));
689    }
690
691    fn put_socket_addr_v6(&mut self, addr: &SocketAddrV6) {
692        self.put_u16(addr.port());
693        self.put_u128(u128::from(*addr.ip()));
694    }
695}
696
697pub fn be_socket_addr_v4(input: &[u8]) -> IResult<&[u8], SocketAddrV4> {
698    flat_map(be_u16, |port| {
699        map(be_ipv4_addr, move |ip| SocketAddrV4::new(ip, port))
700    })
701    .parse(input)
702}
703
704pub fn be_socket_addr_v6(input: &[u8]) -> IResult<&[u8], SocketAddrV6> {
705    flat_map(be_u16, |port| {
706        map(be_ipv6_addr, move |ip| SocketAddrV6::new(ip, port, 0, 0))
707    })
708    .parse(input)
709}
710
711pub fn be_ipv4_addr(input: &[u8]) -> IResult<&[u8], Ipv4Addr> {
712    map(be_u32, Ipv4Addr::from).parse(input)
713}
714
715pub fn be_ipv6_addr(input: &[u8]) -> IResult<&[u8], Ipv6Addr> {
716    map(be_u128, Ipv6Addr::from).parse(input)
717}
718
719pub fn be_ip_addr(is_v6: bool) -> impl Fn(&[u8]) -> IResult<&[u8], IpAddr> {
720    move |input| match is_v6 {
721        true => map(be_u128, |ip| IpAddr::V6(Ipv6Addr::from(ip))).parse(input),
722        false => map(be_u32, |ip| IpAddr::V4(Ipv4Addr::from(ip))).parse(input),
723    }
724}
725
726impl Display for EndpointAddr {
727    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
728        if let Some(agent_addr) = &self.agent {
729            write!(f, "{}-{agent_addr}", self.primary)
730        } else {
731            write!(f, "{}", self.primary)
732        }
733    }
734}
735
736impl TryFrom<DquicEndpointAddr> for EndpointAddr {
737    type Error = ();
738
739    fn try_from(value: DquicEndpointAddr) -> Result<Self, Self::Error> {
740        match value {
741            DquicEndpointAddr::Direct {
742                addr: SocketAddr::V4(addr),
743            } => Ok(Self::direct_v4(addr)),
744            DquicEndpointAddr::Direct {
745                addr: SocketAddr::V6(addr),
746            } => Ok(Self::direct_v6(addr)),
747            DquicEndpointAddr::Mediate {
748                agent: SocketAddr::V4(agent),
749                outer: SocketAddr::V4(outer),
750            } => Ok(Self::nat_v4(outer, agent)),
751            DquicEndpointAddr::Mediate {
752                agent: SocketAddr::V6(agent),
753                outer: SocketAddr::V6(outer),
754            } => Ok(Self::nat_v6(outer, agent)),
755            _ => Err(()),
756        }
757    }
758}
759
760impl TryFrom<EndpointAddr> for DquicEndpointAddr {
761    type Error = ();
762
763    fn try_from(value: EndpointAddr) -> Result<Self, Self::Error> {
764        if let Some(agent_addr) = value.agent {
765            match (value.primary, agent_addr) {
766                (SocketAddr::V4(outer), SocketAddr::V4(agent)) => Ok(DquicEndpointAddr::Mediate {
767                    outer: SocketAddr::V4(outer),
768                    agent: SocketAddr::V4(agent),
769                }),
770                (SocketAddr::V6(outer), SocketAddr::V6(agent)) => Ok(DquicEndpointAddr::Mediate {
771                    outer: SocketAddr::V6(outer),
772                    agent: SocketAddr::V6(agent),
773                }),
774                _ => Err(()),
775            }
776        } else {
777            match value.primary {
778                SocketAddr::V4(addr) => Ok(DquicEndpointAddr::Direct {
779                    addr: SocketAddr::V4(addr),
780                }),
781                SocketAddr::V6(addr) => Ok(DquicEndpointAddr::Direct {
782                    addr: SocketAddr::V6(addr),
783                }),
784            }
785        }
786    }
787}
788
789pub async fn sign_endponit_address(
790    server_id: u8,
791    authority: Option<&(impl dhttp_identity::identity::LocalAuthority + ?Sized)>,
792    endpoint: DquicEndpointAddr,
793) -> Option<EndpointAddr> {
794    let mut ep: EndpointAddr = endpoint.try_into().ok()?;
795    ep.set_main(server_id == 0);
796    ep.set_sequence(CertificateSequence::from(server_id));
797    if let Some(authority) = authority {
798        let _ = ep.sign_with_authority(authority).await;
799    }
800    Some(ep)
801}
802
803#[cfg(test)]
804mod tests {
805    use std::{
806        net::{Ipv4Addr, Ipv6Addr},
807        sync::Arc,
808    };
809
810    use bytes::BytesMut;
811    use futures::future::BoxFuture;
812    use ring::signature::KeyPair;
813    use rustls::sign::{Signer, SigningKey};
814
815    use super::*;
816
817    fn v4_outer() -> SocketAddrV4 {
818        SocketAddrV4::new(Ipv4Addr::new(203, 0, 113, 10), 4433)
819    }
820
821    #[test]
822    fn endpoint_certificate_chain_key_normalizes_missing_sequence() {
823        let mut endpoint = EndpointAddr::direct_v4(v4_outer());
824        endpoint.set_main(true);
825
826        let key = endpoint.certificate_chain_key();
827
828        assert_eq!(key.usage().kind_flag(), "0");
829        assert_eq!(key.sequence().get(), 0);
830    }
831
832    #[test]
833    fn endpoint_certificate_chain_key_uses_present_sequence() {
834        let mut endpoint = EndpointAddr::direct_v4(v4_outer());
835        endpoint.set_main(false);
836        endpoint.set_sequence(
837            dhttp_identity::certificate::CertificateSequence::try_from(7u32).unwrap(),
838        );
839
840        let key = endpoint.certificate_chain_key();
841
842        assert_eq!(key.usage().kind_flag(), "1");
843        assert_eq!(key.sequence().get(), 7);
844    }
845
846    #[test]
847    fn endpoint_parser_rejects_over_range_certificate_sequence() {
848        let sequence = crate::core::parser::varint::VarInt::from_u64(
849            dhttp_identity::certificate::CertificateSequence::MAX as u64 + 1,
850        )
851        .unwrap();
852        let mut packet = BytesMut::new();
853        packet.put_u8(EndpointAddr::FLAG_MAIN | EndpointAddr::FLAG_CLUSTERED);
854        packet.put_varint(sequence);
855        packet.put_u16(v4_outer().port());
856        packet.put_slice(&v4_outer().ip().octets());
857
858        assert!(be_endpoint_addr(&packet).is_err());
859    }
860
861    #[test]
862    fn legacy_endpoint_v4_direct_without_meta() {
863        let port = 5353u16;
864        let ip = Ipv4Addr::new(10, 0, 0, 1);
865        let mut buf = BytesMut::new();
866        buf.extend_from_slice(&port.to_be_bytes());
867        buf.extend_from_slice(&u32::from(ip).to_be_bytes());
868        let (remain, decoded) = be_endpoint_addr_compat(&buf, 6).unwrap();
869        assert!(remain.is_empty());
870        assert_eq!(
871            decoded,
872            EndpointAddr::direct_v4(SocketAddrV4::new(ip, port))
873        );
874    }
875
876    #[test]
877    fn legacy_endpoint_v4_nat_without_meta() {
878        let outer = SocketAddrV4::new(Ipv4Addr::new(10, 0, 0, 1), 1000);
879        let agent = SocketAddrV4::new(Ipv4Addr::new(10, 0, 0, 2), 2000);
880        let mut buf = BytesMut::new();
881        buf.extend_from_slice(&outer.port().to_be_bytes());
882        buf.extend_from_slice(&u32::from(*outer.ip()).to_be_bytes());
883        buf.extend_from_slice(&agent.port().to_be_bytes());
884        buf.extend_from_slice(&u32::from(*agent.ip()).to_be_bytes());
885        let (remain, decoded) = be_endpoint_addr_compat(&buf, 12).unwrap();
886        assert!(remain.is_empty());
887        assert_eq!(decoded, EndpointAddr::nat_v4(outer, agent));
888    }
889
890    #[test]
891    fn flag_bit_ops_work() {
892        let addr = SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), 5353);
893        let mut ep = EndpointAddr {
894            flags: 0b0011_0000,
895            sequence: None,
896            load: None,
897            signature: None,
898            primary: addr.into(),
899            agent: None,
900        };
901
902        assert!(!ep.is_main());
903        assert!(!ep.is_signed());
904
905        ep.set_main(true);
906        assert!(ep.is_main());
907        assert_eq!(ep.flags, 0b0111_0000);
908
909        ep.set_signed(true);
910        assert!(ep.is_signed());
911        assert_eq!(ep.flags, 0b0111_0001);
912
913        ep.set_main(false);
914        assert!(!ep.is_main());
915        assert!(ep.is_signed());
916        assert_eq!(ep.flags, 0b0011_0001);
917
918        ep.set_signed(false);
919        assert!(!ep.is_signed());
920        assert_eq!(ep.flags, 0b0011_0000);
921    }
922
923    #[test]
924    fn varint_roundtrip_and_len() {
925        fn roundtrip(v: u64) {
926            let v = VarInt::from_u64(v).unwrap();
927            let mut buf = BytesMut::new();
928            buf.put_varint(v);
929            assert_eq!(buf.len(), v.encoding_size());
930            let (remain, decoded) = be_varint(&buf).unwrap();
931            assert!(remain.is_empty());
932            assert_eq!(decoded, v);
933        }
934
935        for v in [
936            0u64,
937            1,
938            63,
939            64,
940            16383,
941            16384,
942            (1 << 30) - 1,
943            1 << 30,
944            (1 << 62) - 1,
945        ] {
946            roundtrip(v);
947        }
948    }
949
950    #[test]
951    fn varint_rejects_overflow_and_incomplete() {
952        assert!(VarInt::from_u64((1 << 62) + 1).is_err());
953
954        let incomplete = [0b01_000000u8];
955        match be_varint(&incomplete) {
956            Err(nom::Err::Incomplete(_)) => {}
957            other => panic!("expected Incomplete, got {other:?}"),
958        }
959    }
960
961    #[test]
962    fn endpoint_encode_decode_roundtrip() {
963        let v4_outer = SocketAddrV4::new(Ipv4Addr::new(10, 0, 0, 1), 1000);
964        let v4_agent = SocketAddrV4::new(Ipv4Addr::new(10, 0, 0, 2), 2000);
965        let v6_outer = SocketAddrV6::new(Ipv6Addr::LOCALHOST, 3000, 0, 0);
966        let v6_agent = SocketAddrV6::new(Ipv6Addr::LOCALHOST, 4000, 0, 0);
967
968        let mut with_load = EndpointAddr::direct_v4(v4_outer);
969        with_load.set_load(Some(0.42_f32));
970
971        let cases = vec![
972            // IPv4 direct, MAIN + CLUSTERED flags
973            EndpointAddr {
974                flags: EndpointAddr::FLAG_MAIN | EndpointAddr::FLAG_CLUSTERED,
975                sequence: Some(CertificateSequence::from(0u8)),
976                load: None,
977                signature: None,
978                primary: v4_outer.into(),
979                agent: None,
980            },
981            // IPv4 NAT, CLUSTERED flag
982            EndpointAddr {
983                flags: EndpointAddr::FLAG_NAT | EndpointAddr::FLAG_CLUSTERED,
984                sequence: Some(CertificateSequence::try_from(127u32).unwrap()),
985                load: None,
986                signature: None,
987                primary: v4_outer.into(),
988                agent: Some(v4_agent.into()),
989            },
990            // IPv6 direct, MAIN + CLUSTERED flags
991            EndpointAddr {
992                flags: EndpointAddr::FLAG_FAMILY
993                    | EndpointAddr::FLAG_MAIN
994                    | EndpointAddr::FLAG_CLUSTERED,
995                sequence: Some(CertificateSequence::try_from(128u32).unwrap()),
996                load: None,
997                signature: None,
998                primary: v6_outer.into(),
999                agent: None,
1000            },
1001            // IPv6 NAT, CLUSTERED flag
1002            EndpointAddr {
1003                flags: EndpointAddr::FLAG_FAMILY
1004                    | EndpointAddr::FLAG_NAT
1005                    | EndpointAddr::FLAG_CLUSTERED,
1006                sequence: Some(CertificateSequence::try_from(16_384u32).unwrap()),
1007                load: None,
1008                signature: None,
1009                primary: v6_outer.into(),
1010                agent: Some(v6_agent.into()),
1011            },
1012            // IPv4 direct with LOAD
1013            with_load,
1014        ];
1015
1016        for ep in cases {
1017            let mut buf = BytesMut::new();
1018            buf.put_endpoint_addr(&ep);
1019            assert_eq!(buf.len(), ep.encpding_size());
1020
1021            let (remain, decoded) = be_endpoint_addr(&buf).unwrap();
1022            assert!(remain.is_empty());
1023            assert_eq!(decoded, ep);
1024        }
1025    }
1026
1027    #[test]
1028    fn compat_parser_does_not_misclassify_modern_lengths_as_legacy() {
1029        let mut direct = EndpointAddr::direct_v4("203.0.113.10:4433".parse().unwrap());
1030        direct.set_main(true);
1031        direct.set_sequence(CertificateSequence::try_from(10u32).unwrap());
1032        direct.set_load(Some(1.0));
1033
1034        let mut nat = EndpointAddr::nat_v4(
1035            "198.51.100.10:4433".parse().unwrap(),
1036            "192.0.2.10:4433".parse().unwrap(),
1037        );
1038        nat.set_main(true);
1039        nat.set_sequence(CertificateSequence::from(1u8));
1040        nat.set_load(Some(2.0));
1041
1042        for endpoint in [direct, nat] {
1043            let mut buf = BytesMut::new();
1044            buf.put_endpoint_addr(&endpoint);
1045            assert!([12, 18].contains(&buf.len()));
1046
1047            let (remaining, decoded) =
1048                be_endpoint_addr_compat(&buf, u16::try_from(buf.len()).unwrap()).unwrap();
1049            assert!(remaining.is_empty());
1050            assert_eq!(decoded, endpoint);
1051        }
1052    }
1053
1054    #[test]
1055    fn endpoint_signature_roundtrip_and_verify() {
1056        #[derive(Debug)]
1057        struct Ed25519Key {
1058            keypair: Arc<ring::signature::Ed25519KeyPair>,
1059            cert_chain: Vec<rustls::pki_types::CertificateDer<'static>>,
1060        }
1061
1062        #[derive(Debug)]
1063        struct Ed25519Signer(Arc<ring::signature::Ed25519KeyPair>);
1064
1065        impl Signer for Ed25519Signer {
1066            fn sign(&self, message: &[u8]) -> Result<Vec<u8>, rustls::Error> {
1067                Ok(self.0.sign(message).as_ref().to_vec())
1068            }
1069
1070            fn scheme(&self) -> SignatureScheme {
1071                SignatureScheme::ED25519
1072            }
1073        }
1074
1075        impl SigningKey for Ed25519Key {
1076            fn choose_scheme(&self, offered: &[SignatureScheme]) -> Option<Box<dyn Signer>> {
1077                offered
1078                    .contains(&SignatureScheme::ED25519)
1079                    .then(|| Box::new(Ed25519Signer(self.keypair.clone())) as Box<dyn Signer>)
1080            }
1081
1082            fn algorithm(&self) -> rustls::SignatureAlgorithm {
1083                rustls::SignatureAlgorithm::ED25519
1084            }
1085        }
1086
1087        impl dhttp_identity::identity::LocalAuthority for Ed25519Key {
1088            fn name(&self) -> &str {
1089                "authority.example"
1090            }
1091
1092            fn cert_chain(&self) -> &[rustls::pki_types::CertificateDer<'static>] {
1093                &self.cert_chain
1094            }
1095
1096            fn sign(
1097                &self,
1098                data: &[u8],
1099            ) -> BoxFuture<'_, Result<Vec<u8>, dhttp_identity::identity::SignError>> {
1100                let result = dhttp_identity::identity::sign_with_key(self, data);
1101                Box::pin(std::future::ready(result))
1102            }
1103        }
1104
1105        let rng = ring::rand::SystemRandom::new();
1106        let pkcs8 = ring::signature::Ed25519KeyPair::generate_pkcs8(&rng).unwrap();
1107        let keypair =
1108            Arc::new(ring::signature::Ed25519KeyPair::from_pkcs8(pkcs8.as_ref()).unwrap());
1109        let mut spki = Vec::with_capacity(44);
1110        spki.extend_from_slice(&[
1111            0x30, 0x2a, 0x30, 0x05, 0x06, 0x03, 0x2b, 0x65, 0x70, 0x03, 0x21, 0x00,
1112        ]);
1113        spki.extend_from_slice(keypair.public_key().as_ref());
1114        let key = Ed25519Key {
1115            keypair: keypair.clone(),
1116            cert_chain: vec![rustls::pki_types::CertificateDer::from(spki.clone())],
1117        };
1118
1119        let addr = SocketAddrV4::new(Ipv4Addr::new(10, 0, 0, 1), 5353);
1120        let mut ep = EndpointAddr::direct_v4(addr);
1121        ep.set_main(true);
1122        futures::executor::block_on(ep.sign_with_authority(&key)).unwrap();
1123
1124        let mut buf = BytesMut::new();
1125        buf.put_endpoint_addr(&ep);
1126        assert_eq!(buf.len(), ep.encpding_size());
1127
1128        let (remain, decoded) = be_endpoint_addr(&buf).unwrap();
1129        assert!(remain.is_empty());
1130        assert!(decoded.is_signed());
1131        assert!(decoded.signature().is_some());
1132        assert!(
1133            decoded
1134                .verify_signature(SubjectPublicKeyInfoDer::from(spki.as_slice()))
1135                .unwrap()
1136        );
1137
1138        let mut tampered = decoded.clone();
1139        tampered.set_main(false);
1140        assert!(
1141            !tampered
1142                .verify_signature(SubjectPublicKeyInfoDer::from(spki.as_slice()))
1143                .unwrap()
1144        );
1145    }
1146
1147    #[test]
1148    fn sign_with_authority_uses_canonical_scheme_from_public_key() {
1149        #[derive(Debug)]
1150        struct Ed25519Authority {
1151            cert_chain: Vec<rustls::pki_types::CertificateDer<'static>>,
1152        }
1153
1154        impl dhttp_identity::identity::LocalAuthority for Ed25519Authority {
1155            fn name(&self) -> &str {
1156                "authority.example"
1157            }
1158
1159            fn cert_chain(&self) -> &[rustls::pki_types::CertificateDer<'static>] {
1160                &self.cert_chain
1161            }
1162
1163            fn sign(
1164                &self,
1165                _data: &[u8],
1166            ) -> BoxFuture<'_, Result<Vec<u8>, dhttp_identity::identity::SignError>> {
1167                Box::pin(async move { Ok(vec![1, 2, 3]) })
1168            }
1169        }
1170
1171        let cert_chain = vec![rustls::pki_types::CertificateDer::from(vec![
1172            0x30, 0x2a, 0x30, 0x05, 0x06, 0x03, 0x2b, 0x65, 0x70, 0x03, 0x21, 0x00, 0, 0, 0, 0, 0,
1173            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,
1174        ])];
1175        let mut ep = EndpointAddr::direct_v4(SocketAddrV4::new(Ipv4Addr::LOCALHOST, 5353));
1176        futures::executor::block_on(ep.sign_with_authority(&Ed25519Authority { cert_chain }))
1177            .unwrap();
1178
1179        let signature = ep.signature().unwrap();
1180        assert_eq!(
1181            SignatureScheme::from(signature.scheme),
1182            SignatureScheme::ED25519
1183        );
1184        assert_eq!(signature.signature, vec![1, 2, 3]);
1185    }
1186
1187    #[test]
1188    fn optional_fields_flags_follow_values() {
1189        let addr = SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), 5353);
1190        let mut ep = EndpointAddr::direct_v4(addr);
1191
1192        assert!(!ep.is_load());
1193
1194        ep.set_load(Some(0.5_f32));
1195
1196        assert!(ep.is_load());
1197        assert_eq!(ep.load(), Some(0.5_f32));
1198
1199        ep.set_load(None);
1200
1201        assert!(!ep.is_load());
1202        assert_eq!(ep.load(), None);
1203    }
1204}