1 /*
2   chronyd/chronyc - Programs for keeping computer clocks accurate.
3 
4  **********************************************************************
5  * Copyright (C) Richard P. Curnow  1997-2003
6  * Copyright (C) Miroslav Lichvar  2009, 2015-2017, 2021
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of version 2 of the GNU General Public License as
10  * published by the Free Software Foundation.
11  *
12  * This program is distributed in the hope that it will be useful, but
13  * WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License along
18  * with this program; if not, write to the Free Software Foundation, Inc.,
19  * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
20  *
21  **********************************************************************
22 
23   =======================================================================
24 
25   This module keeps a count of the number of successful accesses by
26   clients, and the times of the last accesses.
27 
28   This can be used for status reporting, and (in the case of a
29   server), if it needs to know which clients have made use of its data
30   recently.
31 
32   */
33 
34 #include "config.h"
35 
36 #include "sysincl.h"
37 
38 #include "array.h"
39 #include "clientlog.h"
40 #include "conf.h"
41 #include "local.h"
42 #include "memory.h"
43 #include "ntp.h"
44 #include "reports.h"
45 #include "util.h"
46 #include "logging.h"
47 
48 #define MAX_SERVICES 3
49 
50 typedef struct {
51   IPAddr ip_addr;
52   uint32_t last_hit[MAX_SERVICES];
53   uint32_t hits[MAX_SERVICES];
54   uint16_t drops[MAX_SERVICES];
55   uint16_t tokens[MAX_SERVICES];
56   int8_t rate[MAX_SERVICES];
57   int8_t ntp_timeout_rate;
58   uint8_t drop_flags;
59 } Record;
60 
61 /* Hash table of records, there is a fixed number of records per slot */
62 static ARR_Instance records;
63 
64 #define SLOT_BITS 4
65 
66 /* Number of records in one slot of the hash table */
67 #define SLOT_SIZE (1U << SLOT_BITS)
68 
69 /* Minimum number of slots */
70 #define MIN_SLOTS 1
71 
72 /* Maximum number of slots, this is a hard limit */
73 #define MAX_SLOTS (1U << (24 - SLOT_BITS))
74 
75 /* Number of slots in the hash table */
76 static unsigned int slots;
77 
78 /* Maximum number of slots given memory allocation limit */
79 static unsigned int max_slots;
80 
81 /* Times of last hits are saved as 32-bit fixed point values */
82 #define TS_FRAC 4
83 #define INVALID_TS 0
84 
85 /* Static offset included in conversion to the fixed-point timestamps to
86    randomise their alignment */
87 static uint32_t ts_offset;
88 
89 /* Request rates are saved in the record as 8-bit scaled log2 values */
90 #define RATE_SCALE 4
91 #define MIN_RATE (-14 * RATE_SCALE)
92 #define INVALID_RATE -128
93 
94 /* Response rates are controlled by token buckets.  The capacity and
95    number of tokens spent on response are determined from configured
96    minimum inverval between responses (in log2) and burst length. */
97 
98 #define MIN_LIMIT_INTERVAL (-15 - TS_FRAC)
99 #define MAX_LIMIT_INTERVAL 12
100 #define MIN_LIMIT_BURST 1
101 #define MAX_LIMIT_BURST 255
102 
103 static uint16_t max_tokens[MAX_SERVICES];
104 static uint16_t tokens_per_hit[MAX_SERVICES];
105 
106 /* Reduction of token rates to avoid overflow of 16-bit counters.  Negative
107    shift is used for coarse limiting with intervals shorter than -TS_FRAC. */
108 static int token_shift[MAX_SERVICES];
109 
110 /* Rates at which responses are randomly allowed (in log2) when the
111    buckets don't have enough tokens.  This is necessary in order to
112    prevent an attacker sending requests with spoofed source address
113    from blocking responses to the address completely. */
114 
115 #define MIN_LEAK_RATE 1
116 #define MAX_LEAK_RATE 4
117 
118 static int leak_rate[MAX_SERVICES];
119 
120 /* Limit intervals in log2 */
121 static int limit_interval[MAX_SERVICES];
122 
123 /* Flag indicating whether facility is turned on or not */
124 static int active;
125 
126 /* RX and TX timestamp saved for clients using interleaved mode */
127 typedef struct {
128   uint64_t rx_ts;
129   uint16_t flags;
130   uint16_t slew_epoch;
131   int32_t tx_ts_offset;
132 } NtpTimestamps;
133 
134 /* Flags for NTP timestamps */
135 #define NTPTS_DISABLED 1
136 #define NTPTS_VALID_TX 2
137 
138 /* RX->TX map using a circular buffer with ordered timestamps */
139 typedef struct {
140   ARR_Instance timestamps;
141   uint32_t first;
142   uint32_t size;
143   uint32_t max_size;
144   uint32_t cached_index;
145   uint64_t cached_rx_ts;
146   uint16_t slew_epoch;
147   double slew_offset;
148 } NtpTimestampMap;
149 
150 static NtpTimestampMap ntp_ts_map;
151 
152 /* Maximum interval of NTP timestamps in future after a backward step */
153 #define NTPTS_FUTURE_LIMIT (1LL << 32) /* 1 second */
154 
155 /* Maximum number of timestamps moved in the array to insert a new timestamp */
156 #define NTPTS_INSERT_LIMIT 64
157 
158 /* Global statistics */
159 static uint32_t total_hits[MAX_SERVICES];
160 static uint32_t total_drops[MAX_SERVICES];
161 static uint32_t total_ntp_auth_hits;
162 static uint32_t total_ntp_interleaved_hits;
163 static uint32_t total_record_drops;
164 
165 #define NSEC_PER_SEC 1000000000U
166 
167 /* ================================================== */
168 
169 static int expand_hashtable(void);
170 static void handle_slew(struct timespec *raw, struct timespec *cooked, double dfreq,
171                         double doffset, LCL_ChangeType change_type, void *anything);
172 
173 /* ================================================== */
174 
175 static int
compare_ts(uint32_t x,uint32_t y)176 compare_ts(uint32_t x, uint32_t y)
177 {
178   if (x == y)
179     return 0;
180   if (y == INVALID_TS)
181     return 1;
182   return (int32_t)(x - y) > 0 ? 1 : -1;
183 }
184 
185 /* ================================================== */
186 
187 static int
compare_total_hits(Record * x,Record * y)188 compare_total_hits(Record *x, Record *y)
189 {
190   uint32_t x_hits, y_hits;
191   int i;
192 
193   for (i = 0, x_hits = y_hits = 0; i < MAX_SERVICES; i++) {
194     x_hits += x->hits[i];
195     y_hits += y->hits[i];
196   }
197 
198   return x_hits > y_hits ? 1 : -1;
199 }
200 
201 /* ================================================== */
202 
203 static Record *
get_record(IPAddr * ip)204 get_record(IPAddr *ip)
205 {
206   uint32_t last_hit = 0, oldest_hit = 0;
207   Record *record, *oldest_record;
208   unsigned int first, i, j;
209 
210   if (!active || (ip->family != IPADDR_INET4 && ip->family != IPADDR_INET6))
211     return NULL;
212 
213   while (1) {
214     /* Get index of the first record in the slot */
215     first = UTI_IPToHash(ip) % slots * SLOT_SIZE;
216 
217     for (i = 0, oldest_record = NULL; i < SLOT_SIZE; i++) {
218       record = ARR_GetElement(records, first + i);
219 
220       if (!UTI_CompareIPs(ip, &record->ip_addr, NULL))
221         return record;
222 
223       if (record->ip_addr.family == IPADDR_UNSPEC)
224         break;
225 
226       for (j = 0; j < MAX_SERVICES; j++) {
227         if (j == 0 || compare_ts(last_hit, record->last_hit[j]) < 0)
228           last_hit = record->last_hit[j];
229       }
230 
231       if (!oldest_record || compare_ts(oldest_hit, last_hit) > 0 ||
232           (oldest_hit == last_hit && compare_total_hits(oldest_record, record) > 0)) {
233         oldest_record = record;
234         oldest_hit = last_hit;
235       }
236     }
237 
238     /* If the slot still has an empty record, use it */
239     if (record->ip_addr.family == IPADDR_UNSPEC)
240       break;
241 
242     /* Resize the table if possible and try again as the new slot may
243        have some empty records */
244     if (expand_hashtable())
245       continue;
246 
247     /* There is no other option, replace the oldest record */
248     record = oldest_record;
249     total_record_drops++;
250     break;
251   }
252 
253   record->ip_addr = *ip;
254   for (i = 0; i < MAX_SERVICES; i++)
255     record->last_hit[i] = INVALID_TS;
256   for (i = 0; i < MAX_SERVICES; i++)
257     record->hits[i] = 0;
258   for (i = 0; i < MAX_SERVICES; i++)
259     record->drops[i] = 0;
260   for (i = 0; i < MAX_SERVICES; i++)
261     record->tokens[i] = max_tokens[i];
262   for (i = 0; i < MAX_SERVICES; i++)
263     record->rate[i] = INVALID_RATE;
264   record->ntp_timeout_rate = INVALID_RATE;
265   record->drop_flags = 0;
266 
267   return record;
268 }
269 
270 /* ================================================== */
271 
272 static int
expand_hashtable(void)273 expand_hashtable(void)
274 {
275   ARR_Instance old_records;
276   Record *old_record, *new_record;
277   unsigned int i;
278 
279   old_records = records;
280 
281   if (2 * slots > max_slots)
282     return 0;
283 
284   records = ARR_CreateInstance(sizeof (Record));
285 
286   slots = MAX(MIN_SLOTS, 2 * slots);
287   assert(slots <= max_slots);
288 
289   ARR_SetSize(records, slots * SLOT_SIZE);
290 
291   /* Mark all new records as empty */
292   for (i = 0; i < slots * SLOT_SIZE; i++) {
293     new_record = ARR_GetElement(records, i);
294     new_record->ip_addr.family = IPADDR_UNSPEC;
295   }
296 
297   if (!old_records)
298     return 1;
299 
300   /* Copy old records to the new hash table */
301   for (i = 0; i < ARR_GetSize(old_records); i++) {
302     old_record = ARR_GetElement(old_records, i);
303     if (old_record->ip_addr.family == IPADDR_UNSPEC)
304       continue;
305 
306     new_record = get_record(&old_record->ip_addr);
307 
308     assert(new_record);
309     *new_record = *old_record;
310   }
311 
312   ARR_DestroyInstance(old_records);
313 
314   return 1;
315 }
316 
317 /* ================================================== */
318 
319 static void
set_bucket_params(int interval,int burst,uint16_t * max_tokens,uint16_t * tokens_per_packet,int * token_shift)320 set_bucket_params(int interval, int burst, uint16_t *max_tokens,
321                   uint16_t *tokens_per_packet, int *token_shift)
322 {
323   interval = CLAMP(MIN_LIMIT_INTERVAL, interval, MAX_LIMIT_INTERVAL);
324   burst = CLAMP(MIN_LIMIT_BURST, burst, MAX_LIMIT_BURST);
325 
326   if (interval >= -TS_FRAC) {
327     /* Find the smallest shift with which the maximum number fits in 16 bits */
328     for (*token_shift = 0; *token_shift < interval + TS_FRAC; (*token_shift)++) {
329       if (burst << (TS_FRAC + interval - *token_shift) < 1U << 16)
330         break;
331     }
332   } else {
333     /* Coarse rate limiting */
334     *token_shift = interval + TS_FRAC;
335     *tokens_per_packet = 1;
336     burst = MAX(1U << -*token_shift, burst);
337   }
338 
339   *tokens_per_packet = 1U << (TS_FRAC + interval - *token_shift);
340   *max_tokens = *tokens_per_packet * burst;
341 
342   DEBUG_LOG("Tokens max %d packet %d shift %d",
343             *max_tokens, *tokens_per_packet, *token_shift);
344 }
345 
346 /* ================================================== */
347 
348 void
CLG_Initialise(void)349 CLG_Initialise(void)
350 {
351   int i, interval, burst, lrate, slots2;
352 
353   for (i = 0; i < MAX_SERVICES; i++) {
354     max_tokens[i] = 0;
355     tokens_per_hit[i] = 0;
356     token_shift[i] = 0;
357     leak_rate[i] = 0;
358     limit_interval[i] = MIN_LIMIT_INTERVAL;
359 
360     switch (i) {
361       case CLG_NTP:
362         if (!CNF_GetNTPRateLimit(&interval, &burst, &lrate))
363           continue;
364         break;
365       case CLG_NTSKE:
366         if (!CNF_GetNtsRateLimit(&interval, &burst, &lrate))
367           continue;
368         break;
369       case CLG_CMDMON:
370         if (!CNF_GetCommandRateLimit(&interval, &burst, &lrate))
371           continue;
372         break;
373       default:
374         assert(0);
375     }
376 
377     set_bucket_params(interval, burst, &max_tokens[i], &tokens_per_hit[i], &token_shift[i]);
378     leak_rate[i] = CLAMP(MIN_LEAK_RATE, lrate, MAX_LEAK_RATE);
379     limit_interval[i] = CLAMP(MIN_LIMIT_INTERVAL, interval, MAX_LIMIT_INTERVAL);
380   }
381 
382   active = !CNF_GetNoClientLog();
383   if (!active) {
384     for (i = 0; i < MAX_SERVICES; i++) {
385       if (leak_rate[i] != 0)
386         LOG_FATAL("Rate limiting cannot be enabled with noclientlog");
387     }
388     return;
389   }
390 
391   /* Calculate the maximum number of slots that can be allocated in the
392      configured memory limit.  Take into account expanding of the hash
393      table where two copies exist at the same time. */
394   max_slots = CNF_GetClientLogLimit() /
395               ((sizeof (Record) + sizeof (NtpTimestamps)) * SLOT_SIZE * 3 / 2);
396   max_slots = CLAMP(MIN_SLOTS, max_slots, MAX_SLOTS);
397   for (slots2 = 0; 1U << (slots2 + 1) <= max_slots; slots2++)
398     ;
399 
400   DEBUG_LOG("Max records %u", 1U << (slots2 + SLOT_BITS));
401 
402   slots = 0;
403   records = NULL;
404 
405   expand_hashtable();
406 
407   UTI_GetRandomBytes(&ts_offset, sizeof (ts_offset));
408   ts_offset %= NSEC_PER_SEC / (1U << TS_FRAC);
409 
410   ntp_ts_map.timestamps = NULL;
411   ntp_ts_map.first = 0;
412   ntp_ts_map.size = 0;
413   ntp_ts_map.max_size = 1U << (slots2 + SLOT_BITS);
414   ntp_ts_map.cached_index = 0;
415   ntp_ts_map.cached_rx_ts = 0ULL;
416   ntp_ts_map.slew_epoch = 0;
417   ntp_ts_map.slew_offset = 0.0;
418 
419   LCL_AddParameterChangeHandler(handle_slew, NULL);
420 }
421 
422 /* ================================================== */
423 
424 void
CLG_Finalise(void)425 CLG_Finalise(void)
426 {
427   if (!active)
428     return;
429 
430   ARR_DestroyInstance(records);
431   if (ntp_ts_map.timestamps)
432     ARR_DestroyInstance(ntp_ts_map.timestamps);
433 
434   LCL_RemoveParameterChangeHandler(handle_slew, NULL);
435 }
436 
437 /* ================================================== */
438 
439 static uint32_t
get_ts_from_timespec(struct timespec * ts)440 get_ts_from_timespec(struct timespec *ts)
441 {
442   uint32_t sec = ts->tv_sec, nsec = ts->tv_nsec;
443 
444   nsec += ts_offset;
445   if (nsec >= NSEC_PER_SEC) {
446     nsec -= NSEC_PER_SEC;
447     sec++;
448   }
449 
450   /* This is fast and accurate enough */
451   return sec << TS_FRAC | (140740U * (nsec >> 15)) >> (32 - TS_FRAC);
452 }
453 
454 /* ================================================== */
455 
456 static void
update_record(CLG_Service service,Record * record,struct timespec * now)457 update_record(CLG_Service service, Record *record, struct timespec *now)
458 {
459   uint32_t interval, now_ts, prev_hit, tokens;
460   int interval2, tshift, mtokens;
461   int8_t *rate;
462 
463   now_ts = get_ts_from_timespec(now);
464 
465   prev_hit = record->last_hit[service];
466   record->last_hit[service] = now_ts;
467   record->hits[service]++;
468 
469   interval = now_ts - prev_hit;
470 
471   if (prev_hit == INVALID_TS || (int32_t)interval < 0)
472     return;
473 
474   tshift = token_shift[service];
475   mtokens = max_tokens[service];
476 
477   if (tshift >= 0)
478     tokens = (now_ts >> tshift) - (prev_hit >> tshift);
479   else if (now_ts - prev_hit > mtokens)
480     tokens = mtokens;
481   else
482     tokens = (now_ts - prev_hit) << -tshift;
483   record->tokens[service] = MIN(record->tokens[service] + tokens, mtokens);
484 
485   /* Convert the interval to scaled and rounded log2 */
486   if (interval) {
487     interval += interval >> 1;
488     for (interval2 = -RATE_SCALE * TS_FRAC; interval2 < -MIN_RATE;
489          interval2 += RATE_SCALE) {
490       if (interval <= 1)
491         break;
492       interval >>= 1;
493     }
494   } else {
495     interval2 = -RATE_SCALE * (TS_FRAC + 1);
496   }
497 
498   /* For the NTP service, update one of the two rates depending on whether
499      the previous request of the client had a reply or it timed out */
500   rate = service == CLG_NTP && record->drop_flags & (1U << service) ?
501            &record->ntp_timeout_rate : &record->rate[service];
502 
503   /* Update the rate in a rough approximation of exponential moving average */
504   if (*rate == INVALID_RATE) {
505     *rate = -interval2;
506   } else {
507     if (*rate < -interval2) {
508       (*rate)++;
509     } else if (*rate > -interval2) {
510       if (*rate > RATE_SCALE * 5 / 2 - interval2)
511         *rate = RATE_SCALE * 5 / 2 - interval2;
512       else
513         *rate = (*rate - interval2 - 1) / 2;
514     }
515   }
516 }
517 
518 /* ================================================== */
519 
520 static int
get_index(Record * record)521 get_index(Record *record)
522 {
523   return record - (Record *)ARR_GetElements(records);
524 }
525 
526 /* ================================================== */
527 
528 int
CLG_GetClientIndex(IPAddr * client)529 CLG_GetClientIndex(IPAddr *client)
530 {
531   Record *record;
532 
533   record = get_record(client);
534   if (record == NULL)
535     return -1;
536 
537   return get_index(record);
538 }
539 
540 /* ================================================== */
541 
542 static void
check_service_number(CLG_Service service)543 check_service_number(CLG_Service service)
544 {
545   assert(service >= 0 && service <= MAX_SERVICES);
546 }
547 
548 /* ================================================== */
549 
550 int
CLG_LogServiceAccess(CLG_Service service,IPAddr * client,struct timespec * now)551 CLG_LogServiceAccess(CLG_Service service, IPAddr *client, struct timespec *now)
552 {
553   Record *record;
554 
555   check_service_number(service);
556 
557   total_hits[service]++;
558 
559   record = get_record(client);
560   if (record == NULL)
561     return -1;
562 
563   update_record(service, record, now);
564 
565   DEBUG_LOG("service %d hits %"PRIu32" rate %d trate %d tokens %d",
566             (int)service, record->hits[service], record->rate[service],
567             service == CLG_NTP ? record->ntp_timeout_rate : INVALID_RATE,
568             record->tokens[service]);
569 
570   return get_index(record);
571 }
572 
573 /* ================================================== */
574 
575 static int
limit_response_random(int leak_rate)576 limit_response_random(int leak_rate)
577 {
578   static uint32_t rnd;
579   static int bits_left = 0;
580   int r;
581 
582   if (bits_left < leak_rate) {
583     UTI_GetRandomBytes(&rnd, sizeof (rnd));
584     bits_left = 8 * sizeof (rnd);
585   }
586 
587   /* Return zero on average once per 2^leak_rate */
588   r = rnd % (1U << leak_rate) ? 1 : 0;
589   rnd >>= leak_rate;
590   bits_left -= leak_rate;
591 
592   return r;
593 }
594 
595 /* ================================================== */
596 
597 int
CLG_LimitServiceRate(CLG_Service service,int index)598 CLG_LimitServiceRate(CLG_Service service, int index)
599 {
600   Record *record;
601   int drop;
602 
603   check_service_number(service);
604 
605   if (tokens_per_hit[service] == 0)
606     return 0;
607 
608   record = ARR_GetElement(records, index);
609   record->drop_flags &= ~(1U << service);
610 
611   if (record->tokens[service] >= tokens_per_hit[service]) {
612     record->tokens[service] -= tokens_per_hit[service];
613     return 0;
614   }
615 
616   drop = limit_response_random(leak_rate[service]);
617 
618   /* Poorly implemented NTP clients can send requests at a higher rate
619      when they are not getting replies.  If the request rate seems to be more
620      than twice as much as when replies are sent, give up on rate limiting to
621      reduce the amount of traffic.  Invert the sense of the leak to respond to
622      most of the requests, but still keep the estimated rate updated. */
623   if (service == CLG_NTP && record->ntp_timeout_rate != INVALID_RATE &&
624       record->ntp_timeout_rate > record->rate[service] + RATE_SCALE)
625     drop = !drop;
626 
627   if (!drop) {
628     record->tokens[service] = 0;
629     return 0;
630   }
631 
632   record->drop_flags |= 1U << service;
633   record->drops[service]++;
634   total_drops[service]++;
635 
636   return 1;
637 }
638 
639 /* ================================================== */
640 
641 void
CLG_LogAuthNtpRequest(void)642 CLG_LogAuthNtpRequest(void)
643 {
644   total_ntp_auth_hits++;
645 }
646 
647 /* ================================================== */
648 
649 int
CLG_GetNtpMinPoll(void)650 CLG_GetNtpMinPoll(void)
651 {
652   return limit_interval[CLG_NTP];
653 }
654 
655 /* ================================================== */
656 
657 static NtpTimestamps *
get_ntp_tss(uint32_t index)658 get_ntp_tss(uint32_t index)
659 {
660   return ARR_GetElement(ntp_ts_map.timestamps,
661                         (ntp_ts_map.first + index) & (ntp_ts_map.max_size - 1));
662 }
663 
664 /* ================================================== */
665 
666 static int
find_ntp_rx_ts(uint64_t rx_ts,uint32_t * index)667 find_ntp_rx_ts(uint64_t rx_ts, uint32_t *index)
668 {
669   uint64_t rx_x, rx_lo, rx_hi, step;
670   uint32_t i, x, lo, hi;
671 
672   if (ntp_ts_map.cached_rx_ts == rx_ts && rx_ts != 0ULL) {
673     *index = ntp_ts_map.cached_index;
674     return 1;
675   }
676 
677   if (ntp_ts_map.size == 0) {
678     *index = 0;
679     return 0;
680   }
681 
682   lo = 0;
683   hi = ntp_ts_map.size - 1;
684   rx_lo = get_ntp_tss(lo)->rx_ts;
685   rx_hi = get_ntp_tss(hi)->rx_ts;
686 
687   /* Check for ts < lo before ts > hi to trim timestamps from "future" later
688      if both conditions are true to not break the order of the endpoints.
689      Compare timestamps by their difference to allow adjacent NTP eras. */
690   if ((int64_t)(rx_ts - rx_lo) < 0) {
691     *index = 0;
692     return 0;
693   } else if ((int64_t)(rx_ts - rx_hi) > 0) {
694     *index = ntp_ts_map.size;
695     return 0;
696   }
697 
698   /* Perform a combined linear interpolation and binary search */
699 
700   for (i = 0; ; i++) {
701     if (rx_ts == rx_hi) {
702       *index = ntp_ts_map.cached_index = hi;
703       ntp_ts_map.cached_rx_ts = rx_ts;
704       return 1;
705     } else if (rx_ts == rx_lo) {
706       *index = ntp_ts_map.cached_index = lo;
707       ntp_ts_map.cached_rx_ts = rx_ts;
708       return 1;
709     } else if (lo + 1 == hi) {
710       *index = hi;
711       return 0;
712     }
713 
714     if (hi - lo > 3 && i % 2 == 0) {
715       step = (rx_hi - rx_lo) / (hi - lo);
716       if (step == 0)
717         step = 1;
718       x = lo + (rx_ts - rx_lo) / step;
719     } else {
720       x = lo + (hi - lo) / 2;
721     }
722 
723     if (x <= lo)
724       x = lo + 1;
725     else if (x >= hi)
726       x = hi - 1;
727 
728     rx_x = get_ntp_tss(x)->rx_ts;
729 
730     if ((int64_t)(rx_x - rx_ts) <= 0) {
731       lo = x;
732       rx_lo = rx_x;
733     } else {
734       hi = x;
735       rx_hi = rx_x;
736     }
737   }
738 }
739 
740 /* ================================================== */
741 
742 static uint64_t
ntp64_to_int64(NTP_int64 * ts)743 ntp64_to_int64(NTP_int64 *ts)
744 {
745   return (uint64_t)ntohl(ts->hi) << 32 | ntohl(ts->lo);
746 }
747 
748 /* ================================================== */
749 
750 static void
int64_to_ntp64(uint64_t ts,NTP_int64 * ntp_ts)751 int64_to_ntp64(uint64_t ts, NTP_int64 *ntp_ts)
752 {
753   ntp_ts->hi = htonl(ts >> 32);
754   ntp_ts->lo = htonl(ts);
755 }
756 
757 /* ================================================== */
758 
759 static uint32_t
push_ntp_tss(uint32_t index)760 push_ntp_tss(uint32_t index)
761 {
762   if (ntp_ts_map.size < ntp_ts_map.max_size) {
763     ntp_ts_map.size++;
764   } else {
765     ntp_ts_map.first = (ntp_ts_map.first + 1) % (ntp_ts_map.max_size);
766     if (index > 0)
767       index--;
768   }
769 
770   return index;
771 }
772 
773 /* ================================================== */
774 
775 static void
set_ntp_tx_offset(NtpTimestamps * tss,NTP_int64 * rx_ts,struct timespec * tx_ts)776 set_ntp_tx_offset(NtpTimestamps *tss, NTP_int64 *rx_ts, struct timespec *tx_ts)
777 {
778   struct timespec ts;
779 
780   if (!tx_ts) {
781     tss->flags &= ~NTPTS_VALID_TX;
782     return;
783   }
784 
785   UTI_Ntp64ToTimespec(rx_ts, &ts);
786   UTI_DiffTimespecs(&ts, tx_ts, &ts);
787 
788   if (ts.tv_sec < -2 || ts.tv_sec > 1) {
789     tss->flags &= ~NTPTS_VALID_TX;
790     return;
791   }
792 
793   tss->tx_ts_offset = (int32_t)ts.tv_nsec + (int32_t)ts.tv_sec * (int32_t)NSEC_PER_SEC;
794   tss->flags |= NTPTS_VALID_TX;
795 }
796 
797 /* ================================================== */
798 
799 static void
get_ntp_tx(NtpTimestamps * tss,struct timespec * tx_ts)800 get_ntp_tx(NtpTimestamps *tss, struct timespec *tx_ts)
801 {
802   int32_t offset = tss->tx_ts_offset;
803   NTP_int64 ntp_ts;
804 
805   if (tss->flags & NTPTS_VALID_TX) {
806     int64_to_ntp64(tss->rx_ts, &ntp_ts);
807     UTI_Ntp64ToTimespec(&ntp_ts, tx_ts);
808     if (offset >= (int32_t)NSEC_PER_SEC) {
809       offset -= NSEC_PER_SEC;
810       tx_ts->tv_sec++;
811     }
812     tx_ts->tv_nsec += offset;
813     UTI_NormaliseTimespec(tx_ts);
814   } else {
815     UTI_ZeroTimespec(tx_ts);
816   }
817 }
818 
819 /* ================================================== */
820 
821 void
CLG_SaveNtpTimestamps(NTP_int64 * rx_ts,struct timespec * tx_ts)822 CLG_SaveNtpTimestamps(NTP_int64 *rx_ts, struct timespec *tx_ts)
823 {
824   NtpTimestamps *tss;
825   uint32_t i, index;
826   uint64_t rx;
827 
828   if (!active)
829     return;
830 
831   /* Allocate the array on first use */
832   if (!ntp_ts_map.timestamps) {
833     ntp_ts_map.timestamps = ARR_CreateInstance(sizeof (NtpTimestamps));
834     ARR_SetSize(ntp_ts_map.timestamps, ntp_ts_map.max_size);
835   }
836 
837   rx = ntp64_to_int64(rx_ts);
838 
839   if (rx == 0ULL)
840     return;
841 
842   /* Disable the RX timestamp if it already exists to avoid responding
843      with a wrong TX timestamp */
844   if (find_ntp_rx_ts(rx, &index)) {
845     get_ntp_tss(index)->flags |= NTPTS_DISABLED;
846     return;
847   }
848 
849   assert(index <= ntp_ts_map.size);
850 
851   if (index == ntp_ts_map.size) {
852     /* Increase the size or drop the oldest timestamp to make room for
853        the new timestamp */
854     index = push_ntp_tss(index);
855   } else {
856     /* Trim timestamps in distant future after backward step */
857     while (index < ntp_ts_map.size &&
858            get_ntp_tss(ntp_ts_map.size - 1)->rx_ts - rx > NTPTS_FUTURE_LIMIT)
859       ntp_ts_map.size--;
860 
861     /* Insert the timestamp if it is close to the latest timestamp.
862        Otherwise, replace the closest older or the oldest timestamp. */
863     if (index + NTPTS_INSERT_LIMIT >= ntp_ts_map.size) {
864       index = push_ntp_tss(index);
865       for (i = ntp_ts_map.size - 1; i > index; i--)
866         *get_ntp_tss(i) = *get_ntp_tss(i - 1);
867     } else {
868       if (index > 0)
869         index--;
870     }
871   }
872 
873   ntp_ts_map.cached_index = index;
874   ntp_ts_map.cached_rx_ts = rx;
875 
876   tss = get_ntp_tss(index);
877   tss->rx_ts = rx;
878   tss->flags = 0;
879   tss->slew_epoch = ntp_ts_map.slew_epoch;
880   set_ntp_tx_offset(tss, rx_ts, tx_ts);
881 
882   DEBUG_LOG("Saved RX+TX index=%"PRIu32" first=%"PRIu32" size=%"PRIu32,
883             index, ntp_ts_map.first, ntp_ts_map.size);
884 }
885 
886 /* ================================================== */
887 
888 static void
handle_slew(struct timespec * raw,struct timespec * cooked,double dfreq,double doffset,LCL_ChangeType change_type,void * anything)889 handle_slew(struct timespec *raw, struct timespec *cooked, double dfreq,
890             double doffset, LCL_ChangeType change_type, void *anything)
891 {
892   /* Drop all timestamps on unknown step */
893   if (change_type == LCL_ChangeUnknownStep) {
894     ntp_ts_map.size = 0;
895     ntp_ts_map.cached_rx_ts = 0ULL;
896   }
897 
898   ntp_ts_map.slew_epoch++;
899   ntp_ts_map.slew_offset = doffset;
900 }
901 
902 /* ================================================== */
903 
904 void
CLG_UndoNtpTxTimestampSlew(NTP_int64 * rx_ts,struct timespec * tx_ts)905 CLG_UndoNtpTxTimestampSlew(NTP_int64 *rx_ts, struct timespec *tx_ts)
906 {
907   uint32_t index;
908 
909   if (!ntp_ts_map.timestamps)
910     return;
911 
912   if (!find_ntp_rx_ts(ntp64_to_int64(rx_ts), &index))
913     return;
914 
915   /* If the RX timestamp was captured before the last correction of the clock,
916      remove the adjustment from the TX timestamp */
917   if ((uint16_t)(get_ntp_tss(index)->slew_epoch + 1U) == ntp_ts_map.slew_epoch)
918     UTI_AddDoubleToTimespec(tx_ts, ntp_ts_map.slew_offset, tx_ts);
919 }
920 
921 /* ================================================== */
922 
923 void
CLG_UpdateNtpTxTimestamp(NTP_int64 * rx_ts,struct timespec * tx_ts)924 CLG_UpdateNtpTxTimestamp(NTP_int64 *rx_ts, struct timespec *tx_ts)
925 {
926   uint32_t index;
927 
928   if (!ntp_ts_map.timestamps)
929     return;
930 
931   if (!find_ntp_rx_ts(ntp64_to_int64(rx_ts), &index))
932     return;
933 
934   set_ntp_tx_offset(get_ntp_tss(index), rx_ts, tx_ts);
935 }
936 
937 /* ================================================== */
938 
939 int
CLG_GetNtpTxTimestamp(NTP_int64 * rx_ts,struct timespec * tx_ts)940 CLG_GetNtpTxTimestamp(NTP_int64 *rx_ts, struct timespec *tx_ts)
941 {
942   NtpTimestamps *tss;
943   uint32_t index;
944 
945   if (!ntp_ts_map.timestamps)
946     return 0;
947 
948   if (!find_ntp_rx_ts(ntp64_to_int64(rx_ts), &index))
949     return 0;
950 
951   tss = get_ntp_tss(index);
952 
953   if (tss->flags & NTPTS_DISABLED)
954     return 0;
955 
956   get_ntp_tx(tss, tx_ts);
957 
958   return 1;
959 }
960 
961 /* ================================================== */
962 
963 void
CLG_DisableNtpTimestamps(NTP_int64 * rx_ts)964 CLG_DisableNtpTimestamps(NTP_int64 *rx_ts)
965 {
966   uint32_t index;
967 
968   if (!ntp_ts_map.timestamps)
969     return;
970 
971   if (find_ntp_rx_ts(ntp64_to_int64(rx_ts), &index))
972     get_ntp_tss(index)->flags |= NTPTS_DISABLED;
973 
974   /* This assumes the function is called only to prevent multiple
975      interleaved responses to the same timestamp */
976   total_ntp_interleaved_hits++;
977 }
978 
979 /* ================================================== */
980 
981 int
CLG_GetNumberOfIndices(void)982 CLG_GetNumberOfIndices(void)
983 {
984   if (!active)
985     return -1;
986 
987   return ARR_GetSize(records);
988 }
989 
990 /* ================================================== */
991 
get_interval(int rate)992 static int get_interval(int rate)
993 {
994   if (rate == INVALID_RATE)
995     return 127;
996 
997   rate += rate > 0 ? RATE_SCALE / 2 : -RATE_SCALE / 2;
998 
999   return rate / -RATE_SCALE;
1000 }
1001 
1002 /* ================================================== */
1003 
get_last_ago(uint32_t x,uint32_t y)1004 static uint32_t get_last_ago(uint32_t x, uint32_t y)
1005 {
1006   if (y == INVALID_TS || (int32_t)(x - y) < 0)
1007     return -1;
1008 
1009   return (x - y) >> TS_FRAC;
1010 }
1011 
1012 /* ================================================== */
1013 
1014 int
CLG_GetClientAccessReportByIndex(int index,int reset,uint32_t min_hits,RPT_ClientAccessByIndex_Report * report,struct timespec * now)1015 CLG_GetClientAccessReportByIndex(int index, int reset, uint32_t min_hits,
1016                                  RPT_ClientAccessByIndex_Report *report, struct timespec *now)
1017 {
1018   Record *record;
1019   uint32_t now_ts;
1020   int i, r;
1021 
1022   if (!active || index < 0 || index >= ARR_GetSize(records))
1023     return 0;
1024 
1025   record = ARR_GetElement(records, index);
1026 
1027   if (record->ip_addr.family == IPADDR_UNSPEC)
1028     return 0;
1029 
1030   if (min_hits == 0) {
1031     r = 1;
1032   } else {
1033     for (i = r = 0; i < MAX_SERVICES; i++) {
1034       if (record->hits[i] >= min_hits) {
1035         r = 1;
1036         break;
1037       }
1038     }
1039   }
1040 
1041   if (r) {
1042     now_ts = get_ts_from_timespec(now);
1043 
1044     report->ip_addr = record->ip_addr;
1045     report->ntp_hits = record->hits[CLG_NTP];
1046     report->nke_hits = record->hits[CLG_NTSKE];
1047     report->cmd_hits = record->hits[CLG_CMDMON];
1048     report->ntp_drops = record->drops[CLG_NTP];
1049     report->nke_drops = record->drops[CLG_NTSKE];
1050     report->cmd_drops = record->drops[CLG_CMDMON];
1051     report->ntp_interval = get_interval(record->rate[CLG_NTP]);
1052     report->nke_interval = get_interval(record->rate[CLG_NTSKE]);
1053     report->cmd_interval = get_interval(record->rate[CLG_CMDMON]);
1054     report->ntp_timeout_interval = get_interval(record->ntp_timeout_rate);
1055     report->last_ntp_hit_ago = get_last_ago(now_ts, record->last_hit[CLG_NTP]);
1056     report->last_nke_hit_ago = get_last_ago(now_ts, record->last_hit[CLG_NTSKE]);
1057     report->last_cmd_hit_ago = get_last_ago(now_ts, record->last_hit[CLG_CMDMON]);
1058   }
1059 
1060   if (reset) {
1061     for (i = 0; i < MAX_SERVICES; i++) {
1062       record->hits[i] = 0;
1063       record->drops[i] = 0;
1064     }
1065   }
1066 
1067   return r;
1068 }
1069 
1070 /* ================================================== */
1071 
1072 void
CLG_GetServerStatsReport(RPT_ServerStatsReport * report)1073 CLG_GetServerStatsReport(RPT_ServerStatsReport *report)
1074 {
1075   report->ntp_hits = total_hits[CLG_NTP];
1076   report->nke_hits = total_hits[CLG_NTSKE];
1077   report->cmd_hits = total_hits[CLG_CMDMON];
1078   report->ntp_drops = total_drops[CLG_NTP];
1079   report->nke_drops = total_drops[CLG_NTSKE];
1080   report->cmd_drops = total_drops[CLG_CMDMON];
1081   report->log_drops = total_record_drops;
1082   report->ntp_auth_hits = total_ntp_auth_hits;
1083   report->ntp_interleaved_hits = total_ntp_interleaved_hits;
1084   report->ntp_timestamps = ntp_ts_map.size;
1085   report->ntp_span_seconds = ntp_ts_map.size > 1 ?
1086                              (get_ntp_tss(ntp_ts_map.size - 1)->rx_ts -
1087                               get_ntp_tss(0)->rx_ts) >> 32 : 0;
1088 }
1089