1use std::{
2    collections::hash_map::RandomState,
3    fmt::Display,
4    io::Cursor,
5    net::{AddrParseError, IpAddr},
6    sync::Arc,
7    time::{Duration, Instant},
8};
9
10use serde::{de, Deserialize, Deserializer};
11
12use crate::{
13    ipfilter::IpFilter, KeySet, NoCipher, NtpClock, NtpPacket, NtpTimestamp, NtpVersion,
14    PacketParsingError, SystemSnapshot,
15};
16
17pub enum ServerAction<'a> {
18    Ignore,
19    Respond { message: &'a [u8] },
20}
21
22#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
23pub enum ServerReason {
24    RateLimit,
26    ParseError,
28    InvalidCrypto,
30    InternalError,
32    Policy,
34}
35
36#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
37pub enum ServerResponse {
38    NTSNak,
40    Deny,
42    Ignore,
44    ProvideTime,
46}
47
48pub trait ServerStatHandler {
49    fn register(&mut self, version: u8, nts: bool, reason: ServerReason, response: ServerResponse);
51}
52
53#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Deserialize)]
54#[serde(rename_all = "lowercase")]
55pub enum FilterAction {
56    Ignore,
57    Deny,
58}
59
60impl From<FilterAction> for ServerResponse {
61    fn from(value: FilterAction) -> Self {
62        match value {
63            FilterAction::Ignore => ServerResponse::Ignore,
64            FilterAction::Deny => ServerResponse::Deny,
65        }
66    }
67}
68
69#[derive(Debug, PartialEq, Eq, Hash, Clone, Deserialize)]
70pub struct FilterList {
71    pub filter: Vec<IpSubnet>,
72    pub action: FilterAction,
73}
74
75#[derive(Debug, Clone, PartialEq, Eq, Hash)]
76pub struct ServerConfig {
77    pub denylist: FilterList,
78    pub allowlist: FilterList,
79    pub rate_limiting_cache_size: usize,
80    pub rate_limiting_cutoff: Duration,
81    pub require_nts: Option<FilterAction>,
82    pub accepted_versions: Vec<NtpVersion>,
83}
84
85pub struct Server<C> {
86    config: ServerConfig,
87    clock: C,
88    denyfilter: IpFilter,
89    allowfilter: IpFilter,
90    client_cache: TimestampedCache<IpAddr>,
91    system: SystemSnapshot,
92    keyset: Arc<KeySet>,
93}
94
95fn fallback_message_version(message: &[u8]) -> u8 {
97    message.first().map(|v| (v & 0b0011_1000) >> 3).unwrap_or(0)
98}
99
100impl<C> Server<C> {
101    pub fn new(
103        config: ServerConfig,
104        clock: C,
105        system: SystemSnapshot,
106        keyset: Arc<KeySet>,
107    ) -> Self {
108        let denyfilter = IpFilter::new(&config.denylist.filter);
109        let allowfilter = IpFilter::new(&config.allowlist.filter);
110        let client_cache = TimestampedCache::new(config.rate_limiting_cache_size);
111        Self {
112            config,
113            clock,
114            denyfilter,
115            allowfilter,
116            client_cache,
117            system,
118            keyset,
119        }
120    }
121
122    pub fn update_config(&mut self, config: ServerConfig) {
124        if self.config.denylist.filter != config.denylist.filter {
125            self.denyfilter = IpFilter::new(&config.denylist.filter);
126        }
127        if self.config.allowlist.filter != config.allowlist.filter {
128            self.allowfilter = IpFilter::new(&config.allowlist.filter);
129        }
130        if self.config.rate_limiting_cache_size != config.rate_limiting_cache_size {
131            self.client_cache = TimestampedCache::new(config.rate_limiting_cache_size);
132        }
133        self.config = config;
134    }
135
136    pub fn update_system(&mut self, system: SystemSnapshot) {
138        self.system = system;
139    }
140
141    pub fn update_keyset(&mut self, keyset: Arc<KeySet>) {
143        self.keyset = keyset;
144    }
145
146    fn intended_action(&mut self, client_ip: IpAddr) -> (ServerResponse, ServerReason) {
147        if self.denyfilter.is_in(&client_ip) {
148            (self.config.denylist.action.into(), ServerReason::Policy)
150        } else if !self.allowfilter.is_in(&client_ip) {
151            (self.config.allowlist.action.into(), ServerReason::Policy)
153        } else if !self.client_cache.is_allowed(
154            client_ip,
155            Instant::now(),
156            self.config.rate_limiting_cutoff,
157        ) {
158            (ServerResponse::Ignore, ServerReason::RateLimit)
160        } else {
161            (ServerResponse::ProvideTime, ServerReason::Policy)
163        }
164    }
165}
166
167impl<C: NtpClock> Server<C> {
168    pub fn handle<'a>(
174        &mut self,
175        client_ip: IpAddr,
176        recv_timestamp: NtpTimestamp,
177        message: &[u8],
178        buffer: &'a mut [u8],
179        stats_handler: &mut impl ServerStatHandler,
180    ) -> ServerAction<'a> {
181        let (mut action, mut reason) = self.intended_action(client_ip);
182
183        if action == ServerResponse::Ignore {
184            stats_handler.register(fallback_message_version(message), false, reason, action);
186            return ServerAction::Ignore;
187        }
188
189        let (packet, cookie) = match NtpPacket::deserialize(message, self.keyset.as_ref()) {
191            Ok((packet, cookie)) => match packet.mode() {
192                crate::NtpAssociationMode::Client => (packet, cookie),
193                _ => {
194                    stats_handler.register(
195                        fallback_message_version(message),
196                        false,
197                        ServerReason::ParseError,
198                        ServerResponse::Ignore,
199                    );
200                    return ServerAction::Ignore;
201                }
202            },
203            Err(PacketParsingError::DecryptError(packet)) => {
204                if action != ServerResponse::Deny {
206                    action = ServerResponse::NTSNak;
207                    reason = ServerReason::InvalidCrypto;
208                }
209                (packet, None)
210            }
211            Err(_) => {
212                stats_handler.register(
213                    fallback_message_version(message),
214                    false,
215                    ServerReason::ParseError,
216                    ServerResponse::Ignore,
217                );
218                return ServerAction::Ignore;
219            }
220        };
221
222        let version = packet.version();
224
225        if !self.config.accepted_versions.contains(&version) {
226            stats_handler.register(
228                version.as_u8(),
229                false,
230                ServerReason::Policy,
231                ServerResponse::Ignore,
232            );
233            return ServerAction::Ignore;
234        }
235
236        let nts = cookie.is_some() || action == ServerResponse::NTSNak;
237
238        if let (false, Some(non_nts_action)) = (nts, self.config.require_nts) {
240            if non_nts_action == FilterAction::Ignore {
241                stats_handler.register(
242                    version.into(),
243                    nts,
244                    ServerReason::Policy,
245                    ServerResponse::Ignore,
246                );
247                return ServerAction::Ignore;
248            } else {
249                action = ServerResponse::Deny;
250                reason = ServerReason::Policy;
251            }
252        }
253
254        let mut cursor = Cursor::new(buffer);
255        let result = match action {
256            ServerResponse::NTSNak => {
257                NtpPacket::nts_nak_response(packet).serialize(&mut cursor, &NoCipher, None)
258            }
259            ServerResponse::Deny => {
260                if let Some(cookie) = cookie {
261                    NtpPacket::nts_deny_response(packet).serialize(
262                        &mut cursor,
263                        cookie.s2c.as_ref(),
264                        None,
265                    )
266                } else {
267                    NtpPacket::deny_response(packet).serialize(&mut cursor, &NoCipher, None)
268                }
269            }
270            ServerResponse::ProvideTime => {
271                if let Some(cookie) = cookie {
272                    NtpPacket::nts_timestamp_response(
273                        &self.system,
274                        packet,
275                        recv_timestamp,
276                        &self.clock,
277                        &cookie,
278                        &self.keyset,
279                    )
280                    .serialize(
281                        &mut cursor,
282                        cookie.s2c.as_ref(),
283                        Some(message.len()),
284                    )
285                } else {
286                    NtpPacket::timestamp_response(&self.system, packet, recv_timestamp, &self.clock)
287                        .serialize(&mut cursor, &NoCipher, Some(message.len()))
288                }
289            }
290            ServerResponse::Ignore => unreachable!(),
291        };
292        match result {
293            Ok(_) => {
294                stats_handler.register(version.into(), nts, reason, action);
295                let length = cursor.position();
296                ServerAction::Respond {
297                    message: &cursor.into_inner()[..length as _],
298                }
299            }
300            Err(e) => {
301                tracing::error!("Could not serialize response: {}", e);
302                stats_handler.register(
303                    version.into(),
304                    nts,
305                    ServerReason::InternalError,
306                    ServerResponse::Ignore,
307                );
308                ServerAction::Ignore
309            }
310        }
311    }
312}
313
314#[derive(Debug)]
330struct TimestampedCache<T> {
331    randomstate: RandomState,
332    elements: Vec<Option<(T, Instant)>>,
333}
334
335impl<T: std::hash::Hash + Eq> TimestampedCache<T> {
336    fn new(length: usize) -> Self {
337        Self {
338            elements: std::iter::repeat_with(|| None).take(length).collect(),
340            randomstate: RandomState::new(),
341        }
342    }
343
344    fn index(&self, item: &T) -> usize {
345        use std::hash::BuildHasher;
346
347        self.randomstate.hash_one(item) as usize % self.elements.len()
348    }
349
350    fn is_allowed(&mut self, item: T, timestamp: Instant, cutoff: Duration) -> bool {
351        if self.elements.is_empty() {
352            return true;
354        }
355
356        let index = self.index(&item);
357
358        let timestamp_if_same = self.elements[index]
360            .as_ref()
361            .and_then(|(v, t)| (&item == v).then_some(t))
362            .copied();
363
364        self.elements[index] = Some((item, timestamp));
365
366        if let Some(old_timestamp) = timestamp_if_same {
367            timestamp.duration_since(old_timestamp) >= cutoff
369        } else {
370            true
372        }
373    }
374}
375
376#[derive(Debug, Clone, PartialEq, Eq, Hash)]
377pub struct IpSubnet {
378    pub addr: IpAddr,
379    pub mask: u8,
380}
381
382#[derive(Debug, Clone, PartialEq, Eq)]
383pub enum SubnetParseError {
384    Subnet,
385    Ip(AddrParseError),
386    Mask,
387}
388
389impl std::error::Error for SubnetParseError {}
390
391impl Display for SubnetParseError {
392    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
393        match self {
394            Self::Subnet => write!(f, "Invalid subnet syntax"),
395            Self::Ip(e) => write!(f, "{e} in subnet"),
396            Self::Mask => write!(f, "Invalid subnet mask"),
397        }
398    }
399}
400
401impl From<AddrParseError> for SubnetParseError {
402    fn from(value: AddrParseError) -> Self {
403        Self::Ip(value)
404    }
405}
406
407impl std::str::FromStr for IpSubnet {
408    type Err = SubnetParseError;
409
410    fn from_str(s: &str) -> Result<Self, Self::Err> {
411        let (addr, mask) = s.split_once('/').ok_or(SubnetParseError::Subnet)?;
412        let addr: IpAddr = addr.parse()?;
413        let mask: u8 = mask.parse().map_err(|_| SubnetParseError::Mask)?;
414        let max_mask = match addr {
415            IpAddr::V4(_) => 32,
416            IpAddr::V6(_) => 128,
417        };
418        if mask > max_mask {
419            return Err(SubnetParseError::Mask);
420        }
421        Ok(IpSubnet { addr, mask })
422    }
423}
424
425impl<'de> Deserialize<'de> for IpSubnet {
426    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
427    where
428        D: Deserializer<'de>,
429    {
430        let s = String::deserialize(deserializer)?;
431        std::str::FromStr::from_str(&s).map_err(de::Error::custom)
432    }
433}
434
435#[cfg(test)]
436mod tests {
437    use std::net::{Ipv4Addr, Ipv6Addr};
438
439    use crate::{
440        nts_record::AeadAlgorithm, packet::AesSivCmac256, Cipher, DecodedServerCookie,
441        KeySetProvider, NtpDuration, NtpLeapIndicator, PollIntervalLimits,
442    };
443
444    use super::*;
445
446    #[derive(Debug, Clone, Default)]
447    struct TestClock {
448        cur: NtpTimestamp,
449    }
450
451    impl NtpClock for TestClock {
452        type Error = std::time::SystemTimeError;
453
454        fn now(&self) -> std::result::Result<NtpTimestamp, Self::Error> {
455            Ok(self.cur)
456        }
457
458        fn set_frequency(&self, _freq: f64) -> Result<NtpTimestamp, Self::Error> {
459            panic!("Shouldn't be called by server");
460        }
461
462        fn get_frequency(&self) -> Result<f64, Self::Error> {
463            Ok(0.0)
464        }
465
466        fn step_clock(&self, _offset: NtpDuration) -> Result<NtpTimestamp, Self::Error> {
467            panic!("Shouldn't be called by server");
468        }
469
470        fn disable_ntp_algorithm(&self) -> Result<(), Self::Error> {
471            panic!("Shouldn't be called by server");
472        }
473
474        fn error_estimate_update(
475            &self,
476            _est_error: NtpDuration,
477            _max_error: NtpDuration,
478        ) -> Result<(), Self::Error> {
479            panic!("Shouldn't be called by server");
480        }
481
482        fn status_update(&self, _leap_status: NtpLeapIndicator) -> Result<(), Self::Error> {
483            panic!("Shouldn't be called by source");
484        }
485    }
486
487    #[derive(Debug, Default)]
488    struct TestStatHandler {
489        last_register: Option<(u8, bool, ServerReason, ServerResponse)>,
490    }
491
492    impl ServerStatHandler for TestStatHandler {
493        fn register(
494            &mut self,
495            version: u8,
496            nts: bool,
497            reason: ServerReason,
498            response: ServerResponse,
499        ) {
500            assert!(self.last_register.is_none());
501            self.last_register = Some((version, nts, reason, response));
502        }
503    }
504
505    fn serialize_packet_unencrypted(send_packet: &NtpPacket) -> Vec<u8> {
506        let mut buf = vec![0; 1024];
507        let mut cursor = Cursor::new(buf.as_mut_slice());
508        send_packet.serialize(&mut cursor, &NoCipher, None).unwrap();
509
510        let end = cursor.position() as usize;
511        buf.truncate(end);
512        buf
513    }
514
515    fn serialize_packet_encrypted(send_packet: &NtpPacket, key: &dyn Cipher) -> Vec<u8> {
516        let mut buf = vec![0; 1024];
517        let mut cursor = Cursor::new(buf.as_mut_slice());
518        send_packet.serialize(&mut cursor, key, None).unwrap();
519
520        let end = cursor.position() as usize;
521        buf.truncate(end);
522        buf
523    }
524
525    #[test]
526    fn test_server_allow_filter() {
527        let config = ServerConfig {
528            denylist: FilterList {
529                filter: vec![],
530                action: FilterAction::Deny,
531            },
532            allowlist: FilterList {
533                filter: vec!["127.0.0.0/24".parse().unwrap()],
534                action: FilterAction::Ignore,
535            },
536            rate_limiting_cutoff: Duration::from_secs(1),
537            rate_limiting_cache_size: 0,
538            require_nts: None,
539            accepted_versions: vec![NtpVersion::V4],
540        };
541        let clock = TestClock {
542            cur: NtpTimestamp::from_fixed_int(200),
543        };
544        let mut stats = TestStatHandler::default();
545
546        let mut server = Server::new(
547            config,
548            clock,
549            SystemSnapshot::default(),
550            KeySetProvider::new(1).get(),
551        );
552
553        let (packet, id) = NtpPacket::poll_message(PollIntervalLimits::default().min);
554        let serialized = serialize_packet_unencrypted(&packet);
555
556        let mut buf = [0; 48];
557        let response = server.handle(
558            "127.0.0.1".parse().unwrap(),
559            NtpTimestamp::from_fixed_int(100),
560            &serialized,
561            &mut buf,
562            &mut stats,
563        );
564        assert_eq!(
565            stats.last_register.take(),
566            Some((4, false, ServerReason::Policy, ServerResponse::ProvideTime))
567        );
568        let data = match response {
569            ServerAction::Ignore => panic!("Server ignored packet"),
570            ServerAction::Respond { message } => message,
571        };
572        let packet = NtpPacket::deserialize(data, &NoCipher).unwrap().0;
573        assert_ne!(packet.stratum(), 0);
574        assert!(packet.valid_server_response(id, false));
575        assert_eq!(
576            packet.receive_timestamp(),
577            NtpTimestamp::from_fixed_int(100)
578        );
579        assert_eq!(
580            packet.transmit_timestamp(),
581            NtpTimestamp::from_fixed_int(200)
582        );
583
584        let mut buf = [0; 48];
585        let response = server.handle(
586            "128.0.0.1".parse().unwrap(),
587            NtpTimestamp::from_fixed_int(100),
588            &serialized,
589            &mut buf,
590            &mut stats,
591        );
592        assert_eq!(
593            stats.last_register.take(),
594            Some((4, false, ServerReason::Policy, ServerResponse::Ignore))
595        );
596        assert!(matches!(response, ServerAction::Ignore));
597
598        let config = ServerConfig {
599            denylist: FilterList {
600                filter: vec![],
601                action: FilterAction::Deny,
602            },
603            allowlist: FilterList {
604                filter: vec!["127.0.0.0/24".parse().unwrap()],
605                action: FilterAction::Deny,
606            },
607            rate_limiting_cutoff: Duration::from_secs(1),
608            rate_limiting_cache_size: 0,
609            require_nts: None,
610            accepted_versions: vec![NtpVersion::V4],
611        };
612        server.update_config(config);
613
614        let mut buf = [0; 48];
615        let response = server.handle(
616            "128.0.0.1".parse().unwrap(),
617            NtpTimestamp::from_fixed_int(100),
618            &serialized,
619            &mut buf,
620            &mut stats,
621        );
622        assert_eq!(
623            stats.last_register.take(),
624            Some((4, false, ServerReason::Policy, ServerResponse::Deny))
625        );
626        let data = match response {
627            ServerAction::Ignore => panic!("Server ignored packet"),
628            ServerAction::Respond { message } => message,
629        };
630        let packet = NtpPacket::deserialize(data, &NoCipher).unwrap().0;
631        assert!(packet.valid_server_response(id, false));
632        assert!(packet.is_kiss_deny());
633    }
634
635    #[test]
636    fn test_server_deny_filter() {
637        let config = ServerConfig {
638            denylist: FilterList {
639                filter: vec!["128.0.0.0/24".parse().unwrap()],
640                action: FilterAction::Deny,
641            },
642            allowlist: FilterList {
643                filter: vec!["0.0.0.0/0".parse().unwrap()],
644                action: FilterAction::Ignore,
645            },
646            rate_limiting_cutoff: Duration::from_secs(1),
647            rate_limiting_cache_size: 0,
648            require_nts: None,
649            accepted_versions: vec![NtpVersion::V4],
650        };
651        let clock = TestClock {
652            cur: NtpTimestamp::from_fixed_int(200),
653        };
654        let mut stats = TestStatHandler::default();
655
656        let mut server = Server::new(
657            config,
658            clock,
659            SystemSnapshot::default(),
660            KeySetProvider::new(1).get(),
661        );
662
663        let (packet, id) = NtpPacket::poll_message(PollIntervalLimits::default().min);
664        let serialized = serialize_packet_unencrypted(&packet);
665
666        let mut buf = [0; 48];
667        let response = server.handle(
668            "127.0.0.1".parse().unwrap(),
669            NtpTimestamp::from_fixed_int(100),
670            &serialized,
671            &mut buf,
672            &mut stats,
673        );
674        assert_eq!(
675            stats.last_register.take(),
676            Some((4, false, ServerReason::Policy, ServerResponse::ProvideTime))
677        );
678        let data = match response {
679            ServerAction::Ignore => panic!("Server ignored packet"),
680            ServerAction::Respond { message } => message,
681        };
682        let packet = NtpPacket::deserialize(data, &NoCipher).unwrap().0;
683        assert_ne!(packet.stratum(), 0);
684        assert!(packet.valid_server_response(id, false));
685        assert_eq!(
686            packet.receive_timestamp(),
687            NtpTimestamp::from_fixed_int(100)
688        );
689        assert_eq!(
690            packet.transmit_timestamp(),
691            NtpTimestamp::from_fixed_int(200)
692        );
693
694        let mut buf = [0; 48];
695        let response = server.handle(
696            "128.0.0.1".parse().unwrap(),
697            NtpTimestamp::from_fixed_int(100),
698            &serialized,
699            &mut buf,
700            &mut stats,
701        );
702        assert_eq!(
703            stats.last_register.take(),
704            Some((4, false, ServerReason::Policy, ServerResponse::Deny))
705        );
706        let data = match response {
707            ServerAction::Ignore => panic!("Server ignored packet"),
708            ServerAction::Respond { message } => message,
709        };
710        let packet = NtpPacket::deserialize(data, &NoCipher).unwrap().0;
711        assert!(packet.valid_server_response(id, false));
712        assert!(packet.is_kiss_deny());
713
714        let config = ServerConfig {
715            denylist: FilterList {
716                filter: vec!["128.0.0.0/24".parse().unwrap()],
717                action: FilterAction::Ignore,
718            },
719            allowlist: FilterList {
720                filter: vec!["0.0.0.0/0".parse().unwrap()],
721                action: FilterAction::Ignore,
722            },
723            rate_limiting_cutoff: Duration::from_secs(1),
724            rate_limiting_cache_size: 0,
725            require_nts: None,
726            accepted_versions: vec![NtpVersion::V4],
727        };
728        server.update_config(config);
729
730        let mut buf = [0; 48];
731        let response = server.handle(
732            "128.0.0.1".parse().unwrap(),
733            NtpTimestamp::from_fixed_int(100),
734            &serialized,
735            &mut buf,
736            &mut stats,
737        );
738        assert_eq!(
739            stats.last_register.take(),
740            Some((4, false, ServerReason::Policy, ServerResponse::Ignore))
741        );
742        assert!(matches!(response, ServerAction::Ignore));
743    }
744
745    #[test]
746    fn test_server_rate_limit() {
747        let config = ServerConfig {
748            denylist: FilterList {
749                filter: vec![],
750                action: FilterAction::Deny,
751            },
752            allowlist: FilterList {
753                filter: vec!["0.0.0.0/0".parse().unwrap()],
754                action: FilterAction::Ignore,
755            },
756            rate_limiting_cutoff: Duration::from_millis(100),
757            rate_limiting_cache_size: 32,
758            require_nts: None,
759            accepted_versions: vec![NtpVersion::V4],
760        };
761        let clock = TestClock {
762            cur: NtpTimestamp::from_fixed_int(200),
763        };
764        let mut stats = TestStatHandler::default();
765
766        let mut server = Server::new(
767            config,
768            clock,
769            SystemSnapshot::default(),
770            KeySetProvider::new(1).get(),
771        );
772
773        let (packet, id) = NtpPacket::poll_message(PollIntervalLimits::default().min);
774        let serialized = serialize_packet_unencrypted(&packet);
775
776        let mut buf = [0; 48];
777        let response = server.handle(
778            "127.0.0.1".parse().unwrap(),
779            NtpTimestamp::from_fixed_int(100),
780            &serialized,
781            &mut buf,
782            &mut stats,
783        );
784        assert_eq!(
785            stats.last_register.take(),
786            Some((4, false, ServerReason::Policy, ServerResponse::ProvideTime))
787        );
788        let data = match response {
789            ServerAction::Ignore => panic!("Server ignored packet"),
790            ServerAction::Respond { message } => message,
791        };
792        let packet = NtpPacket::deserialize(data, &NoCipher).unwrap().0;
793        assert_ne!(packet.stratum(), 0);
794        assert!(packet.valid_server_response(id, false));
795        assert_eq!(
796            packet.receive_timestamp(),
797            NtpTimestamp::from_fixed_int(100)
798        );
799        assert_eq!(
800            packet.transmit_timestamp(),
801            NtpTimestamp::from_fixed_int(200)
802        );
803
804        let mut buf = [0; 48];
805        let response = server.handle(
806            "127.0.0.1".parse().unwrap(),
807            NtpTimestamp::from_fixed_int(100),
808            &serialized,
809            &mut buf,
810            &mut stats,
811        );
812        assert_eq!(
813            stats.last_register.take(),
814            Some((4, false, ServerReason::RateLimit, ServerResponse::Ignore))
815        );
816        assert!(matches!(response, ServerAction::Ignore));
817
818        std::thread::sleep(std::time::Duration::from_millis(120));
819
820        let mut buf = [0; 48];
821        let response = server.handle(
822            "127.0.0.1".parse().unwrap(),
823            NtpTimestamp::from_fixed_int(100),
824            &serialized,
825            &mut buf,
826            &mut stats,
827        );
828        assert_eq!(
829            stats.last_register.take(),
830            Some((4, false, ServerReason::Policy, ServerResponse::ProvideTime))
831        );
832        let data = match response {
833            ServerAction::Ignore => panic!("Server ignored packet"),
834            ServerAction::Respond { message } => message,
835        };
836        let packet = NtpPacket::deserialize(data, &NoCipher).unwrap().0;
837        assert_ne!(packet.stratum(), 0);
838        assert!(packet.valid_server_response(id, false));
839        assert_eq!(
840            packet.receive_timestamp(),
841            NtpTimestamp::from_fixed_int(100)
842        );
843        assert_eq!(
844            packet.transmit_timestamp(),
845            NtpTimestamp::from_fixed_int(200)
846        );
847
848        let config = ServerConfig {
849            denylist: FilterList {
850                filter: vec![],
851                action: FilterAction::Deny,
852            },
853            allowlist: FilterList {
854                filter: vec!["0.0.0.0/0".parse().unwrap()],
855                action: FilterAction::Ignore,
856            },
857            rate_limiting_cutoff: Duration::from_millis(100),
858            rate_limiting_cache_size: 0,
859            require_nts: None,
860            accepted_versions: vec![NtpVersion::V4],
861        };
862
863        server.update_config(config);
864
865        let mut buf = [0; 48];
866        let response = server.handle(
867            "127.0.0.1".parse().unwrap(),
868            NtpTimestamp::from_fixed_int(100),
869            &serialized,
870            &mut buf,
871            &mut stats,
872        );
873        assert_eq!(
874            stats.last_register.take(),
875            Some((4, false, ServerReason::Policy, ServerResponse::ProvideTime))
876        );
877        let data = match response {
878            ServerAction::Ignore => panic!("Server ignored packet"),
879            ServerAction::Respond { message } => message,
880        };
881        let packet = NtpPacket::deserialize(data, &NoCipher).unwrap().0;
882        assert_ne!(packet.stratum(), 0);
883        assert!(packet.valid_server_response(id, false));
884        assert_eq!(
885            packet.receive_timestamp(),
886            NtpTimestamp::from_fixed_int(100)
887        );
888        assert_eq!(
889            packet.transmit_timestamp(),
890            NtpTimestamp::from_fixed_int(200)
891        );
892
893        let mut buf = [0; 48];
894        let response = server.handle(
895            "127.0.0.1".parse().unwrap(),
896            NtpTimestamp::from_fixed_int(100),
897            &serialized,
898            &mut buf,
899            &mut stats,
900        );
901        assert_eq!(
902            stats.last_register.take(),
903            Some((4, false, ServerReason::Policy, ServerResponse::ProvideTime))
904        );
905        let data = match response {
906            ServerAction::Ignore => panic!("Server ignored packet"),
907            ServerAction::Respond { message } => message,
908        };
909        let packet = NtpPacket::deserialize(data, &NoCipher).unwrap().0;
910        assert_ne!(packet.stratum(), 0);
911        assert!(packet.valid_server_response(id, false));
912        assert_eq!(
913            packet.receive_timestamp(),
914            NtpTimestamp::from_fixed_int(100)
915        );
916        assert_eq!(
917            packet.transmit_timestamp(),
918            NtpTimestamp::from_fixed_int(200)
919        );
920    }
921
922    #[test]
923    fn test_server_ignores_non_request() {
924        let config = ServerConfig {
925            denylist: FilterList {
926                filter: vec![],
927                action: FilterAction::Deny,
928            },
929            allowlist: FilterList {
930                filter: vec!["0.0.0.0/0".parse().unwrap()],
931                action: FilterAction::Ignore,
932            },
933            rate_limiting_cutoff: Duration::from_millis(100),
934            rate_limiting_cache_size: 0,
935            require_nts: None,
936            accepted_versions: vec![NtpVersion::V4],
937        };
938        let clock = TestClock {
939            cur: NtpTimestamp::from_fixed_int(200),
940        };
941        let mut stats = TestStatHandler::default();
942
943        let mut server = Server::new(
944            config,
945            clock,
946            SystemSnapshot::default(),
947            KeySetProvider::new(1).get(),
948        );
949
950        let (packet, _) = NtpPacket::poll_message(PollIntervalLimits::default().min);
951        let mut serialized = serialize_packet_unencrypted(&packet);
952
953        for version in 0..8 {
954            for mode in 0..8 {
955                if mode == 3 {
956                    continue;
958                }
959
960                serialized[0] = (serialized[0] & 0xC0) | (version << 3) | mode;
961
962                let mut buf = [0; 48];
963                let response = server.handle(
964                    "127.0.0.1".parse().unwrap(),
965                    NtpTimestamp::from_fixed_int(100),
966                    &serialized,
967                    &mut buf,
968                    &mut stats,
969                );
970                stats.last_register.take();
971
972                assert!(matches!(response, ServerAction::Ignore));
973            }
974        }
975    }
976
977    #[test]
978    fn test_server_corrupted() {
979        let config = ServerConfig {
980            denylist: FilterList {
981                filter: vec![],
982                action: FilterAction::Deny,
983            },
984            allowlist: FilterList {
985                filter: vec!["0.0.0.0/0".parse().unwrap()],
986                action: FilterAction::Ignore,
987            },
988            rate_limiting_cutoff: Duration::from_millis(100),
989            rate_limiting_cache_size: 0,
990            require_nts: None,
991            accepted_versions: vec![NtpVersion::V4],
992        };
993        let clock = TestClock {
994            cur: NtpTimestamp::from_fixed_int(200),
995        };
996        let mut stats = TestStatHandler::default();
997
998        let mut server = Server::new(
999            config,
1000            clock,
1001            SystemSnapshot::default(),
1002            KeySetProvider::new(1).get(),
1003        );
1004
1005        let (packet, _) = NtpPacket::poll_message(PollIntervalLimits::default().min);
1006        let mut serialized = serialize_packet_unencrypted(&packet);
1007
1008        let mut buf = [0; 1];
1009        let response = server.handle(
1010            "127.0.0.1".parse().unwrap(),
1011            NtpTimestamp::from_fixed_int(100),
1012            &serialized,
1013            &mut buf,
1014            &mut stats,
1015        );
1016        assert_eq!(
1017            stats.last_register.take(),
1018            Some((
1019                4,
1020                false,
1021                ServerReason::InternalError,
1022                ServerResponse::Ignore
1023            ))
1024        );
1025        assert!(matches!(response, ServerAction::Ignore));
1026
1027        serialized[0] = 42;
1028
1029        let mut buf = [0; 48];
1030        let response = server.handle(
1031            "127.0.0.1".parse().unwrap(),
1032            NtpTimestamp::from_fixed_int(100),
1033            &serialized,
1034            &mut buf,
1035            &mut stats,
1036        );
1037        assert_eq!(
1038            stats.last_register.take(),
1039            Some((5, false, ServerReason::ParseError, ServerResponse::Ignore))
1040        );
1041        assert!(matches!(response, ServerAction::Ignore));
1042
1043        let config = ServerConfig {
1044            denylist: FilterList {
1045                filter: vec![],
1046                action: FilterAction::Deny,
1047            },
1048            allowlist: FilterList {
1049                filter: vec!["128.0.0.0/24".parse().unwrap()],
1050                action: FilterAction::Deny,
1051            },
1052            rate_limiting_cutoff: Duration::from_millis(100),
1053            rate_limiting_cache_size: 0,
1054            require_nts: None,
1055            accepted_versions: vec![NtpVersion::V4],
1056        };
1057        server.update_config(config);
1058
1059        let mut buf = [0; 48];
1060        let response = server.handle(
1061            "127.0.0.1".parse().unwrap(),
1062            NtpTimestamp::from_fixed_int(100),
1063            &serialized,
1064            &mut buf,
1065            &mut stats,
1066        );
1067        assert_eq!(
1068            stats.last_register.take(),
1069            Some((5, false, ServerReason::ParseError, ServerResponse::Ignore))
1070        );
1071        assert!(matches!(response, ServerAction::Ignore));
1072
1073        let config = ServerConfig {
1074            denylist: FilterList {
1075                filter: vec![],
1076                action: FilterAction::Deny,
1077            },
1078            allowlist: FilterList {
1079                filter: vec!["128.0.0.0/24".parse().unwrap()],
1080                action: FilterAction::Ignore,
1081            },
1082            rate_limiting_cutoff: Duration::from_millis(100),
1083            rate_limiting_cache_size: 0,
1084            require_nts: None,
1085            accepted_versions: vec![NtpVersion::V4],
1086        };
1087        server.update_config(config);
1088
1089        let mut buf = [0; 48];
1090        let response = server.handle(
1091            "127.0.0.1".parse().unwrap(),
1092            NtpTimestamp::from_fixed_int(100),
1093            &serialized,
1094            &mut buf,
1095            &mut stats,
1096        );
1097        assert_eq!(
1098            stats.last_register.take(),
1099            Some((5, false, ServerReason::Policy, ServerResponse::Ignore))
1100        );
1101        assert!(matches!(response, ServerAction::Ignore));
1102
1103        let config = ServerConfig {
1104            denylist: FilterList {
1105                filter: vec!["127.0.0.0/24".parse().unwrap()],
1106                action: FilterAction::Deny,
1107            },
1108            allowlist: FilterList {
1109                filter: vec!["0.0.0.0/0".parse().unwrap()],
1110                action: FilterAction::Ignore,
1111            },
1112            rate_limiting_cutoff: Duration::from_millis(100),
1113            rate_limiting_cache_size: 0,
1114            require_nts: None,
1115            accepted_versions: vec![NtpVersion::V4],
1116        };
1117        server.update_config(config);
1118
1119        let mut buf = [0; 48];
1120        let response = server.handle(
1121            "127.0.0.1".parse().unwrap(),
1122            NtpTimestamp::from_fixed_int(100),
1123            &serialized,
1124            &mut buf,
1125            &mut stats,
1126        );
1127        assert_eq!(
1128            stats.last_register.take(),
1129            Some((5, false, ServerReason::ParseError, ServerResponse::Ignore))
1130        );
1131        assert!(matches!(response, ServerAction::Ignore));
1132
1133        let config = ServerConfig {
1134            denylist: FilterList {
1135                filter: vec!["127.0.0.0/24".parse().unwrap()],
1136                action: FilterAction::Ignore,
1137            },
1138            allowlist: FilterList {
1139                filter: vec!["0.0.0.0/0".parse().unwrap()],
1140                action: FilterAction::Ignore,
1141            },
1142            rate_limiting_cutoff: Duration::from_millis(100),
1143            rate_limiting_cache_size: 0,
1144            require_nts: None,
1145            accepted_versions: vec![NtpVersion::V4],
1146        };
1147        server.update_config(config);
1148
1149        let mut buf = [0; 48];
1150        let response = server.handle(
1151            "127.0.0.1".parse().unwrap(),
1152            NtpTimestamp::from_fixed_int(100),
1153            &serialized,
1154            &mut buf,
1155            &mut stats,
1156        );
1157        assert_eq!(
1158            stats.last_register.take(),
1159            Some((5, false, ServerReason::Policy, ServerResponse::Ignore))
1160        );
1161        assert!(matches!(response, ServerAction::Ignore));
1162    }
1163
1164    #[test]
1165    fn test_server_nts() {
1166        let config = ServerConfig {
1167            denylist: FilterList {
1168                filter: vec![],
1169                action: FilterAction::Deny,
1170            },
1171            allowlist: FilterList {
1172                filter: vec!["0.0.0.0/0".parse().unwrap()],
1173                action: FilterAction::Ignore,
1174            },
1175            rate_limiting_cutoff: Duration::from_millis(100),
1176            rate_limiting_cache_size: 0,
1177            require_nts: Some(FilterAction::Ignore),
1178            accepted_versions: vec![NtpVersion::V4],
1179        };
1180        let clock = TestClock {
1181            cur: NtpTimestamp::from_fixed_int(200),
1182        };
1183        let mut stats = TestStatHandler::default();
1184        let keyset = KeySetProvider::new(1).get();
1185
1186        let mut server = Server::new(config, clock, SystemSnapshot::default(), keyset.clone());
1187
1188        let decodedcookie = DecodedServerCookie {
1189            algorithm: AeadAlgorithm::AeadAesSivCmac256,
1190            s2c: Box::new(AesSivCmac256::new([0; 32].into())),
1191            c2s: Box::new(AesSivCmac256::new([0; 32].into())),
1192        };
1193        let cookie = keyset.encode_cookie(&decodedcookie);
1194        let (packet, id) =
1195            NtpPacket::nts_poll_message(&cookie, 0, PollIntervalLimits::default().min);
1196        let serialized = serialize_packet_encrypted(&packet, decodedcookie.c2s.as_ref());
1197
1198        let mut buf = [0; 1024];
1199        let response = server.handle(
1200            "127.0.0.1".parse().unwrap(),
1201            NtpTimestamp::from_fixed_int(100),
1202            &serialized,
1203            &mut buf,
1204            &mut stats,
1205        );
1206        assert_eq!(
1207            stats.last_register.take(),
1208            Some((4, true, ServerReason::Policy, ServerResponse::ProvideTime))
1209        );
1210        let data = match response {
1211            ServerAction::Ignore => panic!("Server ignored packet"),
1212            ServerAction::Respond { message } => message,
1213        };
1214        let packet = NtpPacket::deserialize(data, decodedcookie.s2c.as_ref())
1215            .unwrap()
1216            .0;
1217        assert_ne!(packet.stratum(), 0);
1218        assert!(packet.valid_server_response(id, true));
1219        assert_eq!(
1220            packet.receive_timestamp(),
1221            NtpTimestamp::from_fixed_int(100)
1222        );
1223        assert_eq!(
1224            packet.transmit_timestamp(),
1225            NtpTimestamp::from_fixed_int(200)
1226        );
1227
1228        let cookie_invalid = KeySetProvider::new(1).get().encode_cookie(&decodedcookie);
1229        let (packet_invalid, _) =
1230            NtpPacket::nts_poll_message(&cookie_invalid, 0, PollIntervalLimits::default().min);
1231        let serialized = serialize_packet_encrypted(&packet_invalid, decodedcookie.c2s.as_ref());
1232
1233        let mut buf = [0; 1024];
1234        let response = server.handle(
1235            "127.0.0.1".parse().unwrap(),
1236            NtpTimestamp::from_fixed_int(100),
1237            &serialized,
1238            &mut buf,
1239            &mut stats,
1240        );
1241        assert_eq!(
1242            stats.last_register.take(),
1243            Some((4, true, ServerReason::InvalidCrypto, ServerResponse::NTSNak))
1244        );
1245        let data = match response {
1246            ServerAction::Ignore => panic!("Server ignored packet"),
1247            ServerAction::Respond { message } => message,
1248        };
1249        let packet = NtpPacket::deserialize(data, decodedcookie.s2c.as_ref())
1250            .unwrap()
1251            .0;
1252        assert!(packet.is_kiss_ntsn());
1253    }
1254
1255    #[test]
1256    fn test_server_require_nts() {
1257        let mut config = ServerConfig {
1258            denylist: FilterList {
1259                filter: vec![],
1260                action: FilterAction::Deny,
1261            },
1262            allowlist: FilterList {
1263                filter: vec!["0.0.0.0/0".parse().unwrap()],
1264                action: FilterAction::Ignore,
1265            },
1266            rate_limiting_cutoff: Duration::from_secs(1),
1267            rate_limiting_cache_size: 0,
1268            require_nts: Some(FilterAction::Ignore),
1269            accepted_versions: vec![NtpVersion::V4],
1270        };
1271        let clock = TestClock {
1272            cur: NtpTimestamp::from_fixed_int(200),
1273        };
1274        let mut stats = TestStatHandler::default();
1275
1276        let mut server = Server::new(
1277            config.clone(),
1278            clock,
1279            SystemSnapshot::default(),
1280            KeySetProvider::new(1).get(),
1281        );
1282
1283        let (packet, _) = NtpPacket::poll_message(PollIntervalLimits::default().min);
1284        let serialized = serialize_packet_unencrypted(&packet);
1285
1286        let mut buf = [0; 1024];
1287        let response = server.handle(
1288            "127.0.0.1".parse().unwrap(),
1289            NtpTimestamp::from_fixed_int(100),
1290            &serialized,
1291            &mut buf,
1292            &mut stats,
1293        );
1294        assert_eq!(
1295            stats.last_register.take(),
1296            Some((4, false, ServerReason::Policy, ServerResponse::Ignore))
1297        );
1298        assert!(matches!(response, ServerAction::Ignore));
1299
1300        let decodedcookie = DecodedServerCookie {
1301            algorithm: AeadAlgorithm::AeadAesSivCmac256,
1302            s2c: Box::new(AesSivCmac256::new([0; 32].into())),
1303            c2s: Box::new(AesSivCmac256::new([0; 32].into())),
1304        };
1305        let cookie_invalid = KeySetProvider::new(1).get().encode_cookie(&decodedcookie);
1306        let (packet_invalid, _) =
1307            NtpPacket::nts_poll_message(&cookie_invalid, 0, PollIntervalLimits::default().min);
1308        let serialized = serialize_packet_encrypted(&packet_invalid, decodedcookie.c2s.as_ref());
1309        let response = server.handle(
1310            "127.0.0.1".parse().unwrap(),
1311            NtpTimestamp::from_fixed_int(100),
1312            &serialized,
1313            &mut buf,
1314            &mut stats,
1315        );
1316        assert_eq!(
1317            stats.last_register.take(),
1318            Some((4, true, ServerReason::InvalidCrypto, ServerResponse::NTSNak))
1319        );
1320        let data = match response {
1321            ServerAction::Ignore => panic!("Server ignored packet"),
1322            ServerAction::Respond { message } => message,
1323        };
1324        let packet = NtpPacket::deserialize(data, decodedcookie.s2c.as_ref())
1325            .unwrap()
1326            .0;
1327        assert!(packet.is_kiss_ntsn());
1328
1329        config.require_nts = Some(FilterAction::Deny);
1330        server.update_config(config.clone());
1331
1332        let (packet, id) = NtpPacket::poll_message(PollIntervalLimits::default().min);
1333        let serialized = serialize_packet_unencrypted(&packet);
1334        let response = server.handle(
1335            "127.0.0.1".parse().unwrap(),
1336            NtpTimestamp::from_fixed_int(100),
1337            &serialized,
1338            &mut buf,
1339            &mut stats,
1340        );
1341        assert_eq!(
1342            stats.last_register.take(),
1343            Some((4, false, ServerReason::Policy, ServerResponse::Deny))
1344        );
1345        let ServerAction::Respond { message } = response else {
1346            panic!("Server ignored packet")
1347        };
1348
1349        let packet = NtpPacket::deserialize(message, &NoCipher).unwrap().0;
1350        assert!(packet.valid_server_response(id, false));
1351        assert!(packet.is_kiss_deny());
1352    }
1353
1354    #[test]
1355    fn test_server_v5() {
1356        let config = ServerConfig {
1357            denylist: FilterList {
1358                filter: vec![],
1359                action: FilterAction::Deny,
1360            },
1361            allowlist: FilterList {
1362                filter: vec!["127.0.0.0/24".parse().unwrap()],
1363                action: FilterAction::Deny,
1364            },
1365            rate_limiting_cutoff: Duration::from_millis(100),
1366            rate_limiting_cache_size: 0,
1367            require_nts: None,
1368            accepted_versions: vec![NtpVersion::V5],
1369        };
1370        let clock = TestClock {
1371            cur: NtpTimestamp::from_fixed_int(200),
1372        };
1373        let mut stats = TestStatHandler::default();
1374
1375        let mut server = Server::new(
1376            config,
1377            clock,
1378            SystemSnapshot::default(),
1379            KeySetProvider::new(1).get(),
1380        );
1381
1382        let (packet, id) = NtpPacket::poll_message_v5(PollIntervalLimits::default().min);
1383        let serialized = serialize_packet_unencrypted(&packet);
1384
1385        let mut buf = [0; 1024];
1386        let response = server.handle(
1387            "127.0.0.1".parse().unwrap(),
1388            NtpTimestamp::from_fixed_int(100),
1389            &serialized,
1390            &mut buf,
1391            &mut stats,
1392        );
1393        assert_eq!(
1394            stats.last_register.take(),
1395            Some((5, false, ServerReason::Policy, ServerResponse::ProvideTime))
1396        );
1397        let data = match response {
1398            ServerAction::Ignore => panic!("Server ignored packet"),
1399            ServerAction::Respond { message } => message,
1400        };
1401        let packet = NtpPacket::deserialize(data, &NoCipher).unwrap().0;
1402        assert_ne!(packet.stratum(), 0);
1403        assert!(packet.valid_server_response(id, false));
1404        assert_eq!(
1405            packet.receive_timestamp(),
1406            NtpTimestamp::from_fixed_int(100)
1407        );
1408        assert_eq!(
1409            packet.transmit_timestamp(),
1410            NtpTimestamp::from_fixed_int(200)
1411        );
1412
1413        let mut buf = [0; 1024];
1414        let response = server.handle(
1415            "128.0.0.1".parse().unwrap(),
1416            NtpTimestamp::from_fixed_int(100),
1417            &serialized,
1418            &mut buf,
1419            &mut stats,
1420        );
1421        assert_eq!(
1422            stats.last_register.take(),
1423            Some((5, false, ServerReason::Policy, ServerResponse::Deny))
1424        );
1425        let data = match response {
1426            ServerAction::Ignore => panic!("Server ignored packet"),
1427            ServerAction::Respond { message } => message,
1428        };
1429        let packet = NtpPacket::deserialize(data, &NoCipher).unwrap().0;
1430        assert!(packet.valid_server_response(id, false));
1431        assert!(packet.is_kiss_deny());
1432    }
1433
1434    #[test]
1435    fn test_server_ignore_version() {
1436        let config = ServerConfig {
1437            denylist: FilterList {
1438                filter: vec![],
1439                action: FilterAction::Deny,
1440            },
1441            allowlist: FilterList {
1442                filter: vec!["0.0.0.0/0".parse().unwrap()],
1443                action: FilterAction::Ignore,
1444            },
1445            rate_limiting_cutoff: Duration::from_millis(1000),
1446            rate_limiting_cache_size: 0,
1447            require_nts: None,
1448            accepted_versions: vec![NtpVersion::V3, NtpVersion::V4],
1449        };
1450        let clock = TestClock {
1451            cur: NtpTimestamp::from_fixed_int(200),
1452        };
1453        let mut stats = TestStatHandler::default();
1454
1455        let mut server = Server::new(
1456            config,
1457            clock,
1458            SystemSnapshot::default(),
1459            KeySetProvider::new(1).get(),
1460        );
1461
1462        let (packet, _) = NtpPacket::poll_message_v5(PollIntervalLimits::default().min);
1463        let serialized = serialize_packet_unencrypted(&packet);
1464
1465        let mut buf = [0; 1024];
1466        let response = server.handle(
1467            "128.0.0.1".parse().unwrap(),
1468            NtpTimestamp::from_fixed_int(100),
1469            &serialized,
1470            &mut buf,
1471            &mut stats,
1472        );
1473
1474        assert_eq!(
1475            stats.last_register.take(),
1476            Some((5, false, ServerReason::Policy, ServerResponse::Ignore))
1477        );
1478        assert!(matches!(response, ServerAction::Ignore));
1479
1480        server.update_config(ServerConfig {
1481            denylist: FilterList {
1482                filter: vec![],
1483                action: FilterAction::Deny,
1484            },
1485            allowlist: FilterList {
1486                filter: vec!["0.0.0.0/0".parse().unwrap()],
1487                action: FilterAction::Ignore,
1488            },
1489            rate_limiting_cutoff: Duration::from_millis(100),
1490            rate_limiting_cache_size: 0,
1491            require_nts: None,
1492            accepted_versions: vec![NtpVersion::V5],
1493        });
1494
1495        let (packet, _) = NtpPacket::poll_message(PollIntervalLimits::default().min);
1496        let serialized = serialize_packet_unencrypted(&packet);
1497
1498        let mut buf = [0; 1024];
1499        let response = server.handle(
1500            "128.0.0.1".parse().unwrap(),
1501            NtpTimestamp::from_fixed_int(100),
1502            &serialized,
1503            &mut buf,
1504            &mut stats,
1505        );
1506
1507        assert_eq!(
1508            stats.last_register.take(),
1509            Some((4, false, ServerReason::Policy, ServerResponse::Ignore))
1510        );
1511        assert!(matches!(response, ServerAction::Ignore));
1512    }
1513
1514    #[test]
1516    fn timestamped_cache() {
1517        let length = 8u8;
1518        let mut cache: TimestampedCache<u8> = TimestampedCache::new(length as usize);
1519
1520        let second = Duration::from_secs(1);
1521        let instant = Instant::now();
1522
1523        assert!(cache.is_allowed(0, instant, second));
1524
1525        assert!(!cache.is_allowed(0, instant, second));
1526
1527        let later = instant + 2 * second;
1528        assert!(cache.is_allowed(0, later, second));
1529
1530        let even_later = later + 2 * second;
1532        assert!(cache.is_allowed(length, even_later, second));
1533    }
1534
1535    #[test]
1536    fn timestamped_cache_size_0() {
1537        let mut cache = TimestampedCache::new(0);
1538
1539        let second = Duration::from_secs(1);
1540        let instant = Instant::now();
1541
1542        assert!(cache.is_allowed(0, instant, second));
1543    }
1544
1545    #[test]
1547    fn test_ipv4_subnet_parse() {
1548        use std::str::FromStr;
1549
1550        assert!(matches!(
1551            IpSubnet::from_str("bla/5"),
1552            Err(SubnetParseError::Ip(_))
1553        ));
1554        assert_eq!(IpSubnet::from_str("0.0.0.0"), Err(SubnetParseError::Subnet));
1555        assert_eq!(
1556            IpSubnet::from_str("0.0.0.0/33"),
1557            Err(SubnetParseError::Mask)
1558        );
1559
1560        assert_eq!(
1561            IpSubnet::from_str("0.0.0.0/0"),
1562            Ok(IpSubnet {
1563                addr: IpAddr::V4(Ipv4Addr::UNSPECIFIED),
1564                mask: 0
1565            })
1566        );
1567        assert_eq!(
1568            IpSubnet::from_str("127.0.0.1/32"),
1569            Ok(IpSubnet {
1570                addr: IpAddr::V4(Ipv4Addr::LOCALHOST),
1571                mask: 32
1572            })
1573        );
1574
1575        assert_eq!(
1576            serde_json::from_str::<IpSubnet>(r#""0.0.0.0/0""#).unwrap(),
1577            IpSubnet {
1578                addr: IpAddr::V4(Ipv4Addr::UNSPECIFIED),
1579                mask: 0,
1580            }
1581        );
1582
1583        assert_eq!(
1584            serde_json::from_str::<IpSubnet>(r#""127.0.0.1/32""#).unwrap(),
1585            IpSubnet {
1586                addr: IpAddr::V4(Ipv4Addr::LOCALHOST),
1587                mask: 32,
1588            }
1589        );
1590    }
1591
1592    #[test]
1593    fn test_ipv6_subnet_parse() {
1594        use std::str::FromStr;
1595
1596        assert!(matches!(
1597            IpSubnet::from_str("bla/5"),
1598            Err(SubnetParseError::Ip(_))
1599        ));
1600        assert_eq!(IpSubnet::from_str("::"), Err(SubnetParseError::Subnet));
1601        assert_eq!(IpSubnet::from_str("::/129"), Err(SubnetParseError::Mask));
1602
1603        assert_eq!(
1604            IpSubnet::from_str("::/0"),
1605            Ok(IpSubnet {
1606                addr: IpAddr::V6(Ipv6Addr::UNSPECIFIED),
1607                mask: 0
1608            })
1609        );
1610        assert_eq!(
1611            IpSubnet::from_str("::1/128"),
1612            Ok(IpSubnet {
1613                addr: IpAddr::V6(Ipv6Addr::LOCALHOST),
1614                mask: 128
1615            })
1616        );
1617
1618        assert_eq!(
1619            serde_json::from_str::<IpSubnet>(r#""::/0""#).unwrap(),
1620            IpSubnet {
1621                addr: IpAddr::V6(Ipv6Addr::UNSPECIFIED),
1622                mask: 0,
1623            }
1624        );
1625
1626        assert_eq!(
1627            serde_json::from_str::<IpSubnet>(r#""::1/128""#).unwrap(),
1628            IpSubnet {
1629                addr: IpAddr::V6(Ipv6Addr::LOCALHOST),
1630                mask: 128,
1631            }
1632        );
1633    }
1634}