@@ -77,6 +77,19 @@ pub trait DNSResolverMessageHandler {
7777 /// [`OnionMessenger`]: crate::onion_message::messenger::OnionMessenger
7878 fn handle_dnssec_proof ( & self , message : DNSSECProof , context : DNSResolverContext ) ;
7979
80+ /// Handle a [`DNSSECError`] message (in response to a [`DNSSECQuery`] we presumably sent),
81+ /// indicating that the resolver was unable to resolve the requested name.
82+ ///
83+ /// The provided [`DNSResolverContext`] was authenticated by the [`OnionMessenger`] as coming from
84+ /// a blinded path that we created.
85+ ///
86+ /// Receiving this lets us avoid waiting for a [`DNSSECProof`] which will never come, failing the
87+ /// pending operation early instead (at least if the name is
88+ /// [definitely unresolvable](DNSSECError::definitely_unresolvable)).
89+ ///
90+ /// [`OnionMessenger`]: crate::onion_message::messenger::OnionMessenger
91+ fn handle_dnssec_error ( & self , message : DNSSECError , context : DNSResolverContext ) ;
92+
8093 /// Gets the node feature flags which this handler itself supports. Useful for setting the
8194 /// `dns_resolver` flag if this handler supports returning [`DNSSECProof`] messages in response
8295 /// to [`DNSSECQuery`] messages.
@@ -99,6 +112,9 @@ impl<T: DNSResolverMessageHandler + ?Sized, D: Deref<Target = T>> DNSResolverMes
99112 fn handle_dnssec_proof ( & self , message : DNSSECProof , context : DNSResolverContext ) {
100113 self . deref ( ) . handle_dnssec_proof ( message, context)
101114 }
115+ fn handle_dnssec_error ( & self , message : DNSSECError , context : DNSResolverContext ) {
116+ self . deref ( ) . handle_dnssec_error ( message, context)
117+ }
102118 fn provided_node_features ( & self ) -> NodeFeatures {
103119 self . deref ( ) . provided_node_features ( )
104120 }
@@ -115,10 +131,14 @@ pub enum DNSResolverMessage {
115131 DNSSECQuery ( DNSSECQuery ) ,
116132 /// A response containing a DNSSEC proof
117133 DNSSECProof ( DNSSECProof ) ,
134+ /// An error in response to a [`DNSSECQuery`], indicating that the requested name could not be
135+ /// resolved into a [`DNSSECProof`].
136+ DNSSECError ( DNSSECError ) ,
118137}
119138
120139const DNSSEC_QUERY_TYPE : u64 = 65536 ;
121140const DNSSEC_PROOF_TYPE : u64 = 65538 ;
141+ const DNSSEC_ERROR_TYPE : u64 = 65550 ;
122142
123143#[ derive( Clone , Debug , Hash , PartialEq , Eq ) ]
124144/// A message which is sent to a DNSSEC prover requesting a DNSSEC proof for the given name.
@@ -136,11 +156,30 @@ pub struct DNSSECProof {
136156 pub proof : Vec < u8 > ,
137157}
138158
159+ #[ derive( Clone , Debug , Hash , PartialEq , Eq ) ]
160+ /// A message which is sent in response to a [`DNSSECQuery`] when the resolver was unable to build a
161+ /// [`DNSSECProof`] for the requested name.
162+ ///
163+ /// This lets the recipient stop waiting for a [`DNSSECProof`] which will not be forthcoming.
164+ pub struct DNSSECError {
165+ /// The name which the [`DNSSECQuery`] was for and which we were unable to resolve.
166+ pub name : Name ,
167+ /// Whether the name is known to be permanently unresolvable, as opposed to having failed due to
168+ /// some transient error.
169+ ///
170+ /// This is set if the requested name does not exist (i.e. the resolver received an NXDOMAIN
171+ /// response) or if the name is not in a DNSSEC-signed zone, in which case retrying or querying a
172+ /// different resolver will not help. It is not set for transient failures (e.g. a timeout
173+ /// communicating with an upstream DNS server), where a retry or a different resolver may yet
174+ /// succeed.
175+ pub definitely_unresolvable : bool ,
176+ }
177+
139178impl DNSResolverMessage {
140179 /// Returns whether `tlv_type` corresponds to a TLV record for DNS Resolvers.
141180 pub fn is_known_type ( tlv_type : u64 ) -> bool {
142181 match tlv_type {
143- DNSSEC_QUERY_TYPE | DNSSEC_PROOF_TYPE => true ,
182+ DNSSEC_QUERY_TYPE | DNSSEC_PROOF_TYPE | DNSSEC_ERROR_TYPE => true ,
144183 _ => false ,
145184 }
146185 }
@@ -158,6 +197,11 @@ impl Writeable for DNSResolverMessage {
158197 w. write_all ( & name. as_str ( ) . as_bytes ( ) ) ?;
159198 proof. write ( w)
160199 } ,
200+ Self :: DNSSECError ( DNSSECError { name, definitely_unresolvable } ) => {
201+ ( name. as_str ( ) . len ( ) as u8 ) . write ( w) ?;
202+ w. write_all ( & name. as_str ( ) . as_bytes ( ) ) ?;
203+ definitely_unresolvable. write ( w)
204+ } ,
161205 }
162206 }
163207}
@@ -176,6 +220,12 @@ impl ReadableArgs<u64> for DNSResolverMessage {
176220 let proof = Readable :: read ( r) ?;
177221 Ok ( DNSResolverMessage :: DNSSECProof ( DNSSECProof { name, proof } ) )
178222 } ,
223+ DNSSEC_ERROR_TYPE => {
224+ let s = Hostname :: read ( r) ?;
225+ let name = s. try_into ( ) . map_err ( |_| DecodeError :: InvalidValue ) ?;
226+ let definitely_unresolvable = Readable :: read ( r) ?;
227+ Ok ( DNSResolverMessage :: DNSSECError ( DNSSECError { name, definitely_unresolvable } ) )
228+ } ,
179229 _ => Err ( DecodeError :: InvalidValue ) ,
180230 }
181231 }
@@ -187,19 +237,22 @@ impl OnionMessageContents for DNSResolverMessage {
187237 match self {
188238 DNSResolverMessage :: DNSSECQuery ( _) => "DNS(SEC) Query" . to_string ( ) ,
189239 DNSResolverMessage :: DNSSECProof ( _) => "DNSSEC Proof" . to_string ( ) ,
240+ DNSResolverMessage :: DNSSECError ( _) => "DNSSEC Error" . to_string ( ) ,
190241 }
191242 }
192243 #[ cfg( not( c_bindings) ) ]
193244 fn msg_type ( & self ) -> & ' static str {
194245 match self {
195246 DNSResolverMessage :: DNSSECQuery ( _) => "DNS(SEC) Query" ,
196247 DNSResolverMessage :: DNSSECProof ( _) => "DNSSEC Proof" ,
248+ DNSResolverMessage :: DNSSECError ( _) => "DNSSEC Error" ,
197249 }
198250 }
199251 fn tlv_type ( & self ) -> u64 {
200252 match self {
201253 DNSResolverMessage :: DNSSECQuery ( _) => DNSSEC_QUERY_TYPE ,
202254 DNSResolverMessage :: DNSSECProof ( _) => DNSSEC_PROOF_TYPE ,
255+ DNSResolverMessage :: DNSSECError ( _) => DNSSEC_ERROR_TYPE ,
203256 }
204257 }
205258}
0 commit comments