Skip to main content

pharos_plugins/
any.rs

1use pharos_proto::{Class, MessageBuilder, Opcode, Section, Type};
2use pharos_server::{Context, Error, Next, Outcome, Plugin, Protocol};
3
4/// Answers ANY Queries with a minimal HINFO Response.
5#[derive(Debug)]
6pub struct Any;
7
8impl Plugin for Any {
9    async fn serve<N: Next + Send>(&self, cx: &mut Context<'_>, next: N) -> Outcome {
10        let Some(question) = cx.query.questions().next() else {
11            return next.run(cx).await;
12        };
13        if question.qtype != Type::ANY {
14            return next.run(cx).await;
15        }
16        let result = (|| {
17            let max_size = cx.max_response_size.max(512);
18            if cx.response.capacity() < max_size {
19                if cx.protocol == Protocol::Tcp {
20                    cx.response
21                        .reserve(max_size.saturating_sub(cx.response.len()));
22                } else {
23                    return Err(Error::ResponseBufferTooSmall);
24                }
25            }
26            let mut flags = 0x8000 | (cx.query.flags() & 0x7800);
27            if cx.query.opcode() == Opcode::QUERY {
28                flags |= cx.query.flags() & 0x0110;
29            }
30            let mut builder = MessageBuilder::new(cx.response, max_size, cx.query.id(), flags)
31                .map_err(Error::Build)?;
32            builder
33                .question(question.name, question.qtype, question.qclass)
34                .map_err(Error::Build)?;
35            // RFC 8482 ยง4.2: synthesize an HINFO record for an ANY Query.
36            builder
37                .record(
38                    Section::Answer,
39                    question.name,
40                    Type::HINFO,
41                    Class::IN,
42                    8482,
43                    b"\x0dANY obsoleted\x0cSee RFC 8482",
44                )
45                .map_err(Error::Build)?;
46            let _ = builder.finish();
47            Ok(())
48        })();
49        match result {
50            Ok(()) => Outcome::Response,
51            Err(error) => Outcome::Error(error),
52        }
53    }
54}