Skip to main content

pharos_plugins/
bufsize.rs

1//! Limit the EDNS UDP payload advertised to downstream Plugins.
2
3use pharos_corefile::{Cursor, Error as CorefileError};
4use pharos_server::{Context, Next, Outcome, Plugin, Protocol};
5
6#[derive(Debug)]
7pub struct Bufsize {
8    size: u16,
9}
10
11impl Bufsize {
12    pub(crate) fn parse(cursor: &mut Cursor<'_>) -> Result<Self, CorefileError> {
13        cursor.next();
14        let args = cursor.remaining_args();
15        let size = match args.as_slice() {
16            [] => 1232,
17            [arg] => arg
18                .parse::<u16>()
19                .ok()
20                .filter(|n| (512..=4096).contains(n))
21                .ok_or_else(|| cursor.arg_err())?,
22            _ => return Err(cursor.arg_err()),
23        };
24        Ok(Self { size })
25    }
26}
27
28impl Plugin for Bufsize {
29    async fn serve<N: Next + Send>(&self, cx: &mut Context<'_>, next: N) -> Outcome {
30        if cx
31            .query
32            .opt()
33            .is_some_and(|opt| opt.udp_payload_size() > self.size)
34        {
35            // RFC 6891 ยง6.2.5: limit the advertised UDP payload without increasing it.
36            cx.query = cx.query.with_udp_payload_limit(self.size);
37            if cx.protocol == Protocol::Udp {
38                cx.max_response_size = cx.max_response_size.min(usize::from(self.size));
39            }
40        }
41        next.run(cx).await
42    }
43}