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}