Coverage Report

Created: 2026-08-31 07:18

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/ntp-dev/ntpd/ntp_restrict.c
Line
Count
Source
1
/*
2
 * ntp_restrict.c - determine host restrictions
3
 */
4
#ifdef HAVE_CONFIG_H
5
#include <config.h>
6
#endif
7
8
#include <stdio.h>
9
#include <sys/types.h>
10
11
#include "ntpd.h"
12
#include "ntp_if.h"
13
#include "ntp_lists.h"
14
#include "ntp_stdlib.h"
15
#include "ntp_assert.h"
16
17
/*
18
 * This code keeps a simple address-and-mask list of addressses we want
19
 * to place restrictions on (or remove them from). The restrictions are
20
 * implemented as a set of flags which tell you what matching addresses
21
 * can't do.  The list is sorted retrieve the restrictions most specific
22
*  to the address.
23
 *
24
 * This was originally intended to restrict you from sync'ing to your
25
 * own broadcasts when you are doing that, by restricting yourself from
26
 * your own interfaces. It was also thought it would sometimes be useful
27
 * to keep a misbehaving host or two from abusing your primary clock. It
28
 * has been expanded, however, to suit the needs of those with more
29
 * restrictive access policies.
30
 */
31
#define MASK_IPV6_ADDR(dst, src, msk)         \
32
0
  do {               \
33
0
    int x;              \
34
0
                  \
35
0
    for (x = 0; x < (int)COUNTOF((dst)->s6_addr); x++) { \
36
0
      (dst)->s6_addr[x] =   (src)->s6_addr[x]   \
37
0
              & (msk)->s6_addr[x];  \
38
0
    }              \
39
0
  } while (FALSE)
40
41
/*
42
 * We allocate INC_RESLIST{4|6} entries to the free list whenever empty.
43
 * Auto-tune these to be just less than 1 KB (leaving at least 32 bytes
44
 * for allocator overhead).  We'll use one entry for each "restrict"
45
 * in ntp.conf, plus one for each local address.  This tuning gives us
46
 * room for 31 IPv4 entries and 17 IPv6 entries per allocation on a
47
 * 64-bit system, which is enough for the most common configurations
48
 * to have all the restrictions in a a pair of 1 KB "hot zones" that will
49
 * be accessed on every incoming packet of the respective address family
50
 * and should stay in cache.  This is a performance optimization
51
 * compared to allocating and freeing each entry as needed.
52
 */
53
2
#define INC_RESLIST4  ((1024 - 32) / V4_SIZEOF_RESTRICT_U)
54
0
#define INC_RESLIST6  ((1024 - 32) / V6_SIZEOF_RESTRICT_U)
55
56
/*
57
 * The restriction list
58
 */
59
restrict_u *restrictlist4;
60
restrict_u *restrictlist6;
61
static int restrictcount; /* count in the restrict lists */
62
63
/*
64
 * The free list and associated counters.  Also some uninteresting
65
 * stat counters.
66
 */
67
static restrict_u *resfree4;  /* available entries (free list) */
68
static restrict_u *resfree6;
69
70
static u_long res_calls;
71
static u_long res_found;
72
static u_long res_not_found;
73
74
/*
75
 * Count number of restriction entries referring to RES_LIMITED, to
76
 * control implicit activation/deactivation of the MRU monlist.
77
 */
78
static  u_long res_limited_refcnt;
79
80
/*
81
 * Our default entries.
82
 *
83
 * We can make this cleaner with c99 support: see init_restrict().
84
 */
85
static  restrict_u  restrict_def4;
86
static  restrict_u  restrict_def6;
87
88
/*
89
 * "restrict source ..." enabled knob and restriction bits.
90
 */
91
static  int   restrict_source_enabled;
92
static  u_int32   restrict_source_rflags;
93
static  u_short   restrict_source_mflags;
94
static  short   restrict_source_ippeerlimit;
95
96
/*
97
 * private functions
98
 */
99
static  restrict_u *  alloc_res4(void);
100
static  restrict_u *  alloc_res6(void);
101
static  void    free_res(restrict_u *, int);
102
static  inline void inc_res_limited(void);
103
static  inline void dec_res_limited(void);
104
static  restrict_u *  match_restrict4_addr(u_int32, u_short);
105
static  restrict_u *  match_restrict6_addr(const struct in6_addr *,
106
               u_short);
107
static  restrict_u *  match_restrict_entry(const restrict_u *, int);
108
static inline int/*BOOL*/ mflags_sorts_before(u_short, u_short);
109
static  int/*BOOL*/ res_sorts_before4(restrict_u *, restrict_u *);
110
static  int/*BOOL*/ res_sorts_before6(restrict_u *, restrict_u *);
111
112
typedef int (*res_sort_fn)(restrict_u *, restrict_u *);
113
114
115
/* dump_restrict() & dump_restricts() are DEBUG-only */
116
#ifdef DEBUG  
117
static void   dump_restrict(restrict_u *, int);
118
119
120
/*
121
 * dump_restrict - spit out a single restriction entry
122
 */
123
static void
124
dump_restrict(
125
  restrict_u *  res,
126
  int   is_ipv6
127
)
128
0
{
129
0
  char as[INET6_ADDRSTRLEN];
130
0
  char ms[INET6_ADDRSTRLEN];
131
132
0
  if (is_ipv6) {
133
0
    inet_ntop(AF_INET6, &res->u.v6.addr, as, sizeof as);
134
0
    inet_ntop(AF_INET6, &res->u.v6.mask, ms, sizeof ms);
135
0
  } else {
136
0
    struct in_addr  sia, sim;
137
138
0
    sia.s_addr = htonl(res->u.v4.addr);
139
0
    sim.s_addr = htonl(res->u.v4.addr);
140
0
    inet_ntop(AF_INET, &sia, as, sizeof as);
141
0
    inet_ntop(AF_INET, &sim, ms, sizeof ms);
142
0
  }
143
0
  printf("%s/%s: hits %u ippeerlimit %hd mflags %s rflags %s",
144
0
    as, ms, res->count, res->ippeerlimit,
145
0
    mflags_str(res->mflags),
146
0
    rflags_str(res->rflags));
147
0
  if (res->expire > 0) {
148
0
    printf(" expire %u\n", res->expire);
149
0
  } else {
150
0
    printf("\n");
151
0
  }
152
0
}
153
154
155
/*
156
 * dump_restricts - spit out the 'restrict' entries
157
 */
158
void
159
dump_restricts(void)
160
0
{
161
0
  restrict_u *  res;
162
163
  /* Spit out the IPv4 list */
164
0
  printf("dump_restricts: restrictlist4: %p\n", restrictlist4);
165
0
  for (res = restrictlist4; res != NULL; res = res->link) {
166
0
    dump_restrict(res, 0);
167
0
  }
168
169
  /* Spit out the IPv6 list */
170
0
  printf("dump_restricts: restrictlist6: %p\n", restrictlist6);
171
0
  for (res = restrictlist6; res != NULL; res = res->link) {
172
0
    dump_restrict(res, 1);
173
0
  }
174
0
}
175
#endif /* DEBUG - dump_restrict() / dump_restricts() */
176
177
178
/*
179
 * init_restrict - initialize the restriction data structures
180
 */
181
void
182
init_restrict(void)
183
1
{
184
  /*
185
   * The restriction lists end with a default entry with address
186
   * and mask 0, which will match any entry.  The lists are kept
187
   * sorted by descending address followed by descending mask:
188
   *
189
   *   address    mask
190
   * 192.168.0.0  255.255.255.0 kod limited noquery nopeer
191
   * 192.168.0.0  255.255.0.0 kod limited
192
   * 0.0.0.0  0.0.0.0   kod limited noquery
193
   *
194
   * The first entry which matches an address is used.  With the
195
   * example restrictions above, 192.168.0.0/24 matches the first
196
   * entry, the rest of 192.168.0.0/16 matches the second, and
197
   * everything else matches the third (default).
198
   *
199
   * Note this achieves the same result a little more efficiently
200
   * than the documented behavior, which is to keep the lists
201
   * sorted by ascending address followed by ascending mask, with
202
   * the _last_ matching entry used.
203
   *
204
   * An additional wrinkle is we may have multiple entries with
205
   * the same address and mask but differing match flags (mflags).
206
   * We want to never talk to ourself, so RES_IGNORE entries for
207
   * each local address are added by ntp_io.c with a host mask and
208
   * both RESM_INTERFACE and RESM_NTPONLY set.  We sort those
209
   * entries before entries without those flags to achieve this.
210
   * The remaining match flag is RESM_SOURCE, used to dynamically
211
   * set restrictions for each peer based on the prototype set by
212
   * "restrict source" in the configuration.  We want those entries
213
   * to be considered only when there is not a static host
214
   * restriction for the address in the configuration, to allow
215
   * operators to blacklist pool and manycast servers at runtime as
216
   * desired using ntpq runtime configuration.  Such static entries
217
   * have no RESM_ bits set, so the sort order for mflags is first
218
   * RESM_INTERFACE, then entries without RESM_SOURCE, finally the
219
   * remaining.
220
   */
221
222
1
  restrict_def4.ippeerlimit = -1;   /* Cleaner if we have C99 */
223
1
  restrict_def6.ippeerlimit = -1;   /* Cleaner if we have C99 */
224
225
1
  LINK_SLIST(restrictlist4, &restrict_def4, link);
226
1
  LINK_SLIST(restrictlist6, &restrict_def6, link);
227
1
  restrictcount = 2;
228
1
}
229
230
231
static restrict_u *
232
alloc_res4(void)
233
2
{
234
2
  const size_t  cb = V4_SIZEOF_RESTRICT_U;
235
2
  const size_t  count = INC_RESLIST4;
236
2
  restrict_u* rl;
237
2
  restrict_u* res;
238
2
  size_t    i;
239
240
2
  UNLINK_HEAD_SLIST(res, resfree4, link);
241
2
  if (res != NULL) {
242
1
    return res;
243
1
  }
244
1
  rl = eallocarray(count, cb);  /* zeroes */
245
  /* link all but the first onto free list */
246
1
  res = INCR_PTR(rl, (count - 1) * cb);
247
31
  for (i = count - 1; i > 0; i--) {
248
30
    LINK_SLIST(resfree4, res, link);
249
30
    res = (void *)((char *)res - cb);
250
30
  }
251
1
  DEBUG_INSIST(rl == res);
252
  /* allocate the first */
253
0
  return res;
254
2
}
255
256
257
static restrict_u *
258
alloc_res6(void)
259
0
{
260
0
  const size_t  cb = V6_SIZEOF_RESTRICT_U;
261
0
  const size_t  count = INC_RESLIST6;
262
0
  restrict_u *  rl;
263
0
  restrict_u *  res;
264
0
  size_t    i;
265
266
0
  UNLINK_HEAD_SLIST(res, resfree6, link);
267
0
  if (res != NULL) {
268
0
    return res;
269
0
  }
270
0
  rl = eallocarray(count, cb);  /* zeroes */
271
  /* link all but the first onto free list */
272
0
  res = INCR_PTR(rl, (count - 1) * cb);
273
0
  for (i = count - 1; i > 0; i--) {
274
0
    LINK_SLIST(resfree6, res, link);
275
0
    res = (void *)((char *)res - cb);
276
0
  }
277
0
  DEBUG_INSIST(rl == res);
278
  /* allocate the first */
279
0
  return res;
280
0
}
281
282
283
static void
284
free_res(
285
  restrict_u *  res,
286
  int   v6
287
  )
288
0
{
289
0
  restrict_u ** rlisthead_ptr;
290
0
  restrict_u ** flisthead_ptr;
291
0
  restrict_u *  unlinked;
292
0
  size_t    sz;
293
294
0
  restrictcount--;
295
0
  if (RES_LIMITED & res->rflags) {
296
0
    dec_res_limited();
297
0
  }
298
0
  if (v6) {
299
0
    rlisthead_ptr = &restrictlist6;
300
0
    flisthead_ptr = &resfree6;
301
0
    sz = V6_SIZEOF_RESTRICT_U;
302
0
  } else {
303
0
    rlisthead_ptr = &restrictlist4;
304
0
    flisthead_ptr = &resfree4;
305
0
    sz = V4_SIZEOF_RESTRICT_U;
306
0
  }
307
0
  UNLINK_SLIST(unlinked, *rlisthead_ptr, res, link, restrict_u);
308
0
  INSIST(unlinked == res);
309
0
  zero_mem(res, sz);
310
0
  LINK_SLIST(*flisthead_ptr, res, link);
311
0
}
312
313
314
static inline void
315
inc_res_limited(void)
316
0
{
317
0
  if (0 == res_limited_refcnt) {
318
0
    mon_start(MON_RES);
319
0
  }
320
0
  res_limited_refcnt++;
321
0
}
322
323
324
static inline void
325
dec_res_limited(void)
326
0
{
327
0
  res_limited_refcnt--;
328
0
  if (0 == res_limited_refcnt) {
329
0
    mon_stop(MON_RES);
330
0
  }
331
0
}
332
333
334
static restrict_u *
335
match_restrict4_addr(
336
  u_int32 addr,
337
  u_short port
338
  )
339
2.20k
{
340
2.20k
  const int v6 = FALSE;
341
2.20k
  restrict_u *  res;
342
2.20k
  restrict_u *  next;
343
344
4.41k
  for (res = restrictlist4; res != NULL; res = next) {
345
4.41k
    next = res->link;
346
4.41k
    if (res->expire > 0 && res->expire <= current_time) {
347
0
      free_res(res, v6);  /* zeroes the contents */
348
0
      continue;
349
0
    }
350
4.41k
    if (   res->u.v4.addr == (addr & res->u.v4.mask)
351
2.20k
        && (   !(RESM_NTPONLY & res->mflags)
352
2.20k
      || NTP_PORT == port)) {
353
354
2.20k
      break;
355
2.20k
    }
356
4.41k
  }
357
2.20k
  return res;
358
2.20k
}
359
360
361
static restrict_u *
362
match_restrict6_addr(
363
  const struct in6_addr * addr,
364
  u_short     port
365
  )
366
0
{
367
0
  const int v6 = TRUE;
368
0
  restrict_u *  res;
369
0
  restrict_u *  next;
370
0
  struct in6_addr masked;
371
372
0
  for (res = restrictlist6; res != NULL; res = next) {
373
0
    next = res->link;
374
0
    if (res->expire > 0 && res->expire <= current_time) {
375
0
      free_res(res, v6);  /* zeroes the contents */
376
0
      continue;
377
0
    }
378
0
    MASK_IPV6_ADDR(&masked, addr, &res->u.v6.mask);
379
0
    if (ADDR6_EQ(&masked, &res->u.v6.addr)
380
0
        && (   !(RESM_NTPONLY & res->mflags)
381
0
      || NTP_PORT == (int)port)) {
382
383
0
      break;
384
0
    }
385
0
  }
386
0
  return res;
387
0
}
388
389
390
/*
391
 * match_restrict_entry - find an exact match on a restrict list.
392
 *
393
 * Exact match is addr, mask, and mflags all equal.
394
 * In order to use more common code for IPv4 and IPv6, this routine
395
 * requires the caller to populate a restrict_u with mflags and either
396
 * the v4 or v6 address and mask as appropriate.  Other fields in the
397
 * input restrict_u are ignored.
398
 */
399
static restrict_u *
400
match_restrict_entry(
401
  const restrict_u *  pmatch,
402
  int     v6
403
  )
404
2
{
405
2
  restrict_u *res;
406
2
  restrict_u *rlist;
407
2
  size_t cb;
408
409
2
  if (v6) {
410
0
    rlist = restrictlist6;
411
0
    cb = sizeof(pmatch->u.v6);
412
2
  } else {
413
2
    rlist = restrictlist4;
414
2
    cb = sizeof(pmatch->u.v4);
415
2
  }
416
417
5
  for (res = rlist; res != NULL; res = res->link) {
418
3
    if (res->mflags == pmatch->mflags &&
419
1
        !memcmp(&res->u, &pmatch->u, cb)) {
420
0
      break;
421
0
    }
422
3
  }
423
2
  return res;
424
2
}
425
426
427
/*
428
 * mflags_sorts_before - common mflags sorting code
429
 * 
430
 * See block comment in init_restrict() above for rationale.
431
 */
432
static inline int/*BOOL*/
433
mflags_sorts_before(
434
  u_short m1,
435
  u_short m2
436
  )
437
0
{
438
0
  if (    (RESM_INTERFACE & m1)
439
0
      && !(RESM_INTERFACE & m2)) {
440
0
    return TRUE;
441
0
  } else if (   !(RESM_SOURCE & m1)
442
0
       &&  (RESM_SOURCE & m2)) {
443
0
    return TRUE;
444
0
  } else {
445
0
    return FALSE;
446
0
  }
447
0
}
448
449
450
/*
451
 * res_sorts_before4 - compare IPv4 restriction entries
452
 *
453
 * Returns nonzero if r1 sorts before r2.  We sort by descending
454
 * address, then descending mask, then an intricate mflags sort
455
 * order explained in a block comment near the top of this file.
456
 */
457
static int/*BOOL*/
458
res_sorts_before4(
459
  restrict_u *r1,
460
  restrict_u *r2
461
  )
462
2
{
463
2
  int r1_before_r2;
464
465
2
  if (r1->u.v4.addr > r2->u.v4.addr) {
466
2
    r1_before_r2 = TRUE;
467
2
  } else if (r1->u.v4.addr < r2->u.v4.addr) {
468
0
    r1_before_r2 = FALSE;
469
0
  } else if (r1->u.v4.mask > r2->u.v4.mask) {
470
0
    r1_before_r2 = TRUE;
471
0
  } else if (r1->u.v4.mask < r2->u.v4.mask) {
472
0
    r1_before_r2 = FALSE;
473
0
  } else {
474
0
    r1_before_r2 = mflags_sorts_before(r1->mflags, r2->mflags);
475
0
  }
476
477
2
  return r1_before_r2;
478
2
}
479
480
481
/*
482
 * res_sorts_before6 - compare IPv6 restriction entries
483
 *
484
 * Returns nonzero if r1 sorts before r2.  We sort by descending
485
 * address, then descending mask, then an intricate mflags sort
486
 * order explained in a block comment near the top of this file.
487
 */
488
static int/*BOOL*/
489
res_sorts_before6(
490
  restrict_u* r1,
491
  restrict_u* r2
492
)
493
0
{
494
0
  int r1_before_r2;
495
0
  int cmp;
496
497
0
  cmp = ADDR6_CMP(&r1->u.v6.addr, &r2->u.v6.addr);
498
0
  if (cmp > 0) {   /* r1->addr > r2->addr */
499
0
    r1_before_r2 = TRUE;
500
0
  } else if (cmp < 0) { /* r2->addr > r1->addr */
501
0
    r1_before_r2 = FALSE;
502
0
  } else {
503
0
    cmp = ADDR6_CMP(&r1->u.v6.mask, &r2->u.v6.mask);
504
0
    if (cmp > 0) {   /* r1->mask > r2->mask*/
505
0
      r1_before_r2 = TRUE;
506
0
    } else if (cmp < 0) { /* r2->mask > r1->mask */
507
0
      r1_before_r2 = FALSE;
508
0
    } else {
509
0
      r1_before_r2 = mflags_sorts_before(r1->mflags,
510
0
                 r2->mflags);
511
0
    }
512
0
  }
513
514
0
  return r1_before_r2;
515
0
}
516
517
518
/*
519
 * restrictions - return restrictions for this host in *r4a
520
 */
521
void
522
restrictions(
523
  sockaddr_u *srcadr,
524
  r4addr *r4a
525
  )
526
2.20k
{
527
2.20k
  restrict_u *match;
528
2.20k
  struct in6_addr *pin6;
529
530
2.20k
  DEBUG_REQUIRE(NULL != r4a);
531
532
0
  res_calls++;
533
534
2.20k
  if (IS_IPV4(srcadr)) {
535
    /*
536
     * Ignore any packets with a multicast source address
537
     * (this should be done early in the receive process,
538
     * not later!)
539
     */
540
2.20k
    if (IN_CLASSD(SRCADR(srcadr))) {
541
0
      goto multicast;
542
0
    }
543
544
2.20k
    match = match_restrict4_addr(SRCADR(srcadr),
545
2.20k
               SRCPORT(srcadr));
546
2.20k
    DEBUG_INSIST(match != NULL);
547
0
    match->count++;
548
    /*
549
     * res_not_found counts only use of the final default
550
     * entry, not any "restrict default ntpport ...", which
551
     * would be just before the final default.
552
     */
553
2.20k
    if (&restrict_def4 == match)
554
0
      res_not_found++;
555
2.20k
    else
556
2.20k
      res_found++;
557
2.20k
    r4a->rflags = match->rflags;
558
2.20k
    r4a->ippeerlimit = match->ippeerlimit;
559
2.20k
  } else {
560
0
    DEBUG_REQUIRE(IS_IPV6(srcadr));
561
562
0
    pin6 = PSOCK_ADDR6(srcadr);
563
564
    /*
565
     * Ignore any packets with a multicast source address
566
     * (this should be done early in the receive process,
567
     * not later!)
568
     */
569
0
    if (IN6_IS_ADDR_MULTICAST(pin6)) {
570
0
      goto multicast;
571
0
    }
572
0
    match = match_restrict6_addr(pin6, SRCPORT(srcadr));
573
0
    DEBUG_INSIST(match != NULL);
574
0
    match->count++;
575
0
    if (&restrict_def6 == match)
576
0
      res_not_found++;
577
0
    else
578
0
      res_found++;
579
0
    r4a->rflags = match->rflags;
580
0
    r4a->ippeerlimit = match->ippeerlimit;
581
0
  }
582
583
2.20k
  return;
584
585
2.20k
    multicast:
586
0
  r4a->rflags = RES_IGNORE;
587
0
  r4a->ippeerlimit = 0;
588
0
}
589
590
591
#ifdef DEBUG
592
/* display string for restrict_op */
593
const char *
594
resop_str(restrict_op op)
595
0
{
596
0
  switch (op) {
597
0
      case RESTRICT_FLAGS:  return "RESTRICT_FLAGS";
598
0
      case RESTRICT_UNFLAG: return "RESTRICT_UNFLAG";
599
0
      case RESTRICT_REMOVE: return "RESTRICT_REMOVE";
600
0
      case RESTRICT_REMOVEIF: return "RESTRICT_REMOVEIF";
601
0
  }
602
0
  DEBUG_INVARIANT(!"bad restrict_op in resop_str");
603
0
  return "";  /* silence not all paths return value warning */
604
0
}
605
#endif  /* DEBUG */
606
607
608
/*
609
 * hack_restrict - add/subtract/manipulate entries on the restrict list
610
 */
611
int/*BOOL*/
612
hack_restrict(
613
  restrict_op op,
614
  sockaddr_u *  resaddr,
615
  sockaddr_u *  resmask,
616
  short   ippeerlimit,
617
  u_short   mflags,
618
  u_short   rflags,
619
  u_int32   expire
620
  )
621
2
{
622
2
  int   v6;
623
2
  int   bump_res_limited = FALSE;
624
2
  restrict_u  match;
625
2
  restrict_u *  res;
626
2
  restrict_u ** plisthead;
627
2
  res_sort_fn pfn_sort;
628
629
2
#ifdef DEBUG
630
2
  if (debug > 0) {
631
0
    printf("hack_restrict: op %s addr %s mask %s",
632
0
      resop_str(op), stoa(resaddr), stoa(resmask));
633
0
    if (ippeerlimit >= 0) {
634
0
      printf(" ippeerlimit %d", ippeerlimit);
635
0
    }
636
0
    printf(" mflags %s rflags %s", mflags_str(mflags),
637
0
           rflags_str(rflags));
638
0
    if (expire) {
639
0
      printf("lifetime %u\n",
640
0
             expire - (u_int32)current_time);
641
0
    } else {
642
0
      printf("\n");
643
0
    }
644
0
  }
645
2
#endif
646
647
2
  if (NULL == resaddr) {
648
0
    DEBUG_REQUIRE(NULL == resmask);
649
0
    DEBUG_REQUIRE(RESTRICT_FLAGS == op);
650
0
    DEBUG_REQUIRE(RESM_SOURCE & mflags);
651
0
    restrict_source_rflags = rflags;
652
0
    restrict_source_mflags = mflags;
653
0
    restrict_source_ippeerlimit = ippeerlimit;
654
0
    restrict_source_enabled = TRUE;
655
0
    DPRINTF(1, ("restrict source template saved\n"));
656
0
    return TRUE;
657
0
  }
658
659
2
  ZERO(match);
660
661
2
  if (IS_IPV4(resaddr)) {
662
2
    DEBUG_INVARIANT(IS_IPV4(resmask));
663
2
    v6 = FALSE;
664
    /*
665
     * Get address and mask in host byte order for easy
666
     * comparison as u_int32
667
     */
668
2
    match.u.v4.addr = SRCADR(resaddr);
669
2
    match.u.v4.mask = SRCADR(resmask);
670
2
    match.u.v4.addr &= match.u.v4.mask;
671
2
  } else {
672
0
    DEBUG_INVARIANT(IS_IPV6(resaddr));
673
0
    DEBUG_INVARIANT(IS_IPV6(resmask));
674
0
    v6 = TRUE;
675
    /*
676
     * Get address and mask in network byte order for easy
677
     * comparison as byte sequences (e.g. memcmp())
678
     */
679
0
    match.u.v6.mask = SOCK_ADDR6(resmask);
680
0
    MASK_IPV6_ADDR(&match.u.v6.addr, PSOCK_ADDR6(resaddr),
681
0
             &match.u.v6.mask);
682
0
  }
683
684
0
  match.mflags = mflags;
685
2
  res = match_restrict_entry(&match, v6);
686
687
2
  switch (op) {
688
689
2
  case RESTRICT_FLAGS:
690
    /*
691
     * Here we add bits to the rflags. If we already have
692
     * this restriction modify it.
693
     */
694
2
    if (NULL != res) {
695
0
      if (    (RES_LIMITED & rflags)
696
0
          && !(RES_LIMITED & res->rflags)) {
697
698
0
        bump_res_limited = TRUE;
699
0
      }
700
0
      res->rflags |= rflags;
701
0
      res->expire = expire;
702
2
    } else {
703
2
      match.rflags = rflags;
704
2
      match.expire = expire;
705
2
      match.ippeerlimit = ippeerlimit;
706
2
      if (v6) {
707
0
        res = alloc_res6();
708
0
        memcpy(res, &match, V6_SIZEOF_RESTRICT_U);
709
0
        plisthead = &restrictlist6;
710
0
        pfn_sort = &res_sorts_before6;
711
2
      } else {
712
2
        res = alloc_res4();
713
2
        memcpy(res, &match, V4_SIZEOF_RESTRICT_U);
714
2
        plisthead = &restrictlist4;
715
2
        pfn_sort = &res_sorts_before4;
716
2
      }
717
2
      LINK_SORT_SLIST(
718
2
        *plisthead, res,
719
2
        (*pfn_sort)(res, L_S_S_CUR()),
720
2
        link, restrict_u);
721
2
      restrictcount++;
722
2
      if (RES_LIMITED & rflags) {
723
0
        bump_res_limited = TRUE;
724
0
      }
725
2
    }
726
2
    if (bump_res_limited) {
727
0
      inc_res_limited();
728
0
    }
729
2
    return TRUE;
730
731
0
  case RESTRICT_UNFLAG:
732
    /*
733
     * Remove some bits from the rflags. If we didn't
734
     * find this one, just return.
735
     */
736
0
    if (NULL == res) {
737
0
      DPRINTF(1, ("No match for %s %s removing rflags %s\n",
738
0
            stoa(resaddr), stoa(resmask),
739
0
            rflags_str(rflags)));
740
0
      return FALSE;
741
0
    }
742
0
    if (   (RES_LIMITED & res->rflags)
743
0
        && (RES_LIMITED & rflags)) {
744
0
      dec_res_limited();
745
0
    }
746
0
    res->rflags &= ~rflags;
747
0
    return TRUE;
748
749
0
  case RESTRICT_REMOVE:
750
0
  case RESTRICT_REMOVEIF:
751
    /*
752
     * Remove an entry from the table entirely if we
753
     * found one. Don't remove the default entry and
754
     * don't remove an interface entry unless asked.
755
     */
756
0
    if (   res != NULL
757
0
        && (   RESTRICT_REMOVEIF == op
758
0
      || !(RESM_INTERFACE & res->mflags))
759
0
        && res != &restrict_def4
760
0
        && res != &restrict_def6) {
761
762
0
      free_res(res, v6);
763
0
      return TRUE;
764
0
    }
765
0
    DPRINTF(1, ("No match removing %s %s restriction\n",
766
0
          stoa(resaddr), stoa(resmask)));
767
0
    return FALSE;
768
2
  }
769
  /* notreached */
770
0
  return FALSE;
771
2
}
772
773
774
/*
775
 * restrict_source - maintains dynamic "restrict source ..." entries as
776
 *         peers come and go.
777
 */
778
void
779
restrict_source(
780
  sockaddr_u *  addr,
781
  int   farewell, /* TRUE to remove */
782
  u_int32   lifetime  /* seconds, 0 forever */
783
  )
784
0
{
785
0
  sockaddr_u  onesmask;
786
0
  int/*BOOL*/ success;
787
788
0
  if (   !restrict_source_enabled || SOCK_UNSPEC(addr)
789
0
      || IS_MCAST(addr) || ISREFCLOCKADR(addr)) {
790
0
    return;
791
0
  }
792
793
0
  REQUIRE(AF_INET == AF(addr) || AF_INET6 == AF(addr));
794
795
0
  SET_HOSTMASK(&onesmask, AF(addr));
796
0
  if (farewell) {
797
0
    success = hack_restrict(RESTRICT_REMOVE, addr, &onesmask,
798
0
          0, RESM_SOURCE, 0, 0);
799
0
    if (success) {
800
0
      DPRINTF(1, ("%s %s removed", __func__,
801
0
            stoa(addr)));
802
0
    } else {
803
0
      msyslog(LOG_ERR, "%s remove %s failed",
804
0
           __func__, stoa(addr));
805
0
    }
806
0
    return;
807
0
  }
808
809
0
  success = hack_restrict(RESTRICT_FLAGS, addr, &onesmask,
810
0
        restrict_source_ippeerlimit,
811
0
        restrict_source_mflags,
812
0
        restrict_source_rflags, 
813
0
        lifetime > 0
814
0
            ? lifetime + current_time
815
0
            : 0);
816
0
  if (success) {
817
0
    DPRINTF(1, ("%s %s add/upd\n", __func__,
818
0
          stoa(addr)));
819
0
  } else {
820
0
    msyslog(LOG_ERR, "%s %s failed", __func__, stoa(addr));
821
0
  }
822
0
}
823
824
825
#ifdef DEBUG
826
/* Convert restriction RES_ flag bits into a display string */
827
const char *
828
rflags_str(
829
  u_short rflags
830
  )
831
0
{
832
0
  const size_t  sz = LIB_BUFLENGTH;
833
0
  char *    rfs;
834
835
0
  LIB_GETBUF(rfs);
836
0
  rfs[0] = '\0';
837
838
0
  if (rflags & RES_FLAKE) {
839
0
    CLEAR_BIT_IF_DEBUG(RES_FLAKE, rflags);
840
0
    append_flagstr(rfs, sz, "flake");
841
0
  }
842
843
0
  if (rflags & RES_IGNORE) {
844
0
    CLEAR_BIT_IF_DEBUG(RES_IGNORE, rflags);
845
0
    append_flagstr(rfs, sz, "ignore");
846
0
  }
847
848
0
  if (rflags & RES_KOD) {
849
0
    CLEAR_BIT_IF_DEBUG(RES_KOD, rflags);
850
0
    append_flagstr(rfs, sz, "kod");
851
0
  }
852
853
0
  if (rflags & RES_MSSNTP) {
854
0
    CLEAR_BIT_IF_DEBUG(RES_MSSNTP, rflags);
855
0
    append_flagstr(rfs, sz, "mssntp");
856
0
  }
857
858
0
  if (rflags & RES_LIMITED) {
859
0
    CLEAR_BIT_IF_DEBUG(RES_LIMITED, rflags);
860
0
    append_flagstr(rfs, sz, "limited");
861
0
  }
862
863
0
  if (rflags & RES_LPTRAP) {
864
0
    CLEAR_BIT_IF_DEBUG(RES_LPTRAP, rflags);
865
0
    append_flagstr(rfs, sz, "lptrap");
866
0
  }
867
868
0
  if (rflags & RES_NOMODIFY) {
869
0
    CLEAR_BIT_IF_DEBUG(RES_NOMODIFY, rflags);
870
0
    append_flagstr(rfs, sz, "nomodify");
871
0
  }
872
873
0
  if (rflags & RES_NOMRULIST) {
874
0
    CLEAR_BIT_IF_DEBUG(RES_NOMRULIST, rflags);
875
0
    append_flagstr(rfs, sz, "nomrulist");
876
0
  }
877
878
0
  if (rflags & RES_NOEPEER) {
879
0
    CLEAR_BIT_IF_DEBUG(RES_NOEPEER, rflags);
880
0
    append_flagstr(rfs, sz, "noepeer");
881
0
  }
882
883
0
  if (rflags & RES_NOPEER) {
884
0
    CLEAR_BIT_IF_DEBUG(RES_NOPEER, rflags);
885
0
    append_flagstr(rfs, sz, "nopeer");
886
0
  }
887
888
0
  if (rflags & RES_NOQUERY) {
889
0
    CLEAR_BIT_IF_DEBUG(RES_NOQUERY, rflags);
890
0
    append_flagstr(rfs, sz, "noquery");
891
0
  }
892
893
0
  if (rflags & RES_DONTSERVE) {
894
0
    CLEAR_BIT_IF_DEBUG(RES_DONTSERVE, rflags);
895
0
    append_flagstr(rfs, sz, "dontserve");
896
0
  }
897
898
0
  if (rflags & RES_NOTRAP) {
899
0
    CLEAR_BIT_IF_DEBUG(RES_NOTRAP, rflags);
900
0
    append_flagstr(rfs, sz, "notrap");
901
0
  }
902
903
0
  if (rflags & RES_DONTTRUST) {
904
0
    CLEAR_BIT_IF_DEBUG(RES_DONTTRUST, rflags);
905
0
    append_flagstr(rfs, sz, "notrust");
906
0
  }
907
908
0
  if (rflags & RES_SRVRSPFUZ) {
909
0
    CLEAR_BIT_IF_DEBUG(RES_SRVRSPFUZ, rflags);
910
0
    append_flagstr(rfs, sz, "srvrspfuz");
911
0
  }
912
913
0
  if (rflags & RES_VERSION) {
914
0
    CLEAR_BIT_IF_DEBUG(RES_VERSION, rflags);
915
0
    append_flagstr(rfs, sz, "version");
916
0
  }
917
918
0
  DEBUG_INVARIANT(!rflags);
919
920
0
  if ('\0' == rfs[0]) {
921
0
    append_flagstr(rfs, sz, "(none)");
922
0
  }
923
924
0
  return rfs;
925
0
}
926
927
928
/* Convert restriction match RESM_ flag bits into a display string */
929
const char *
930
mflags_str(
931
  u_short mflags
932
  )
933
0
{
934
0
  const size_t  sz = LIB_BUFLENGTH;
935
0
  char *    mfs;
936
937
0
  LIB_GETBUF(mfs);
938
0
  mfs[0] = '\0';
939
940
0
  if (mflags & RESM_NTPONLY) {
941
0
    CLEAR_BIT_IF_DEBUG(RESM_NTPONLY, mflags);
942
0
    append_flagstr(mfs, sz, "ntponly");
943
0
  }
944
945
0
  if (mflags & RESM_SOURCE) {
946
0
    CLEAR_BIT_IF_DEBUG(RESM_SOURCE, mflags);
947
0
    append_flagstr(mfs, sz, "source");
948
0
  }
949
950
0
  if (mflags & RESM_INTERFACE) {
951
0
    CLEAR_BIT_IF_DEBUG(RESM_INTERFACE, mflags);
952
0
    append_flagstr(mfs, sz, "interface");
953
0
  }
954
955
0
  DEBUG_INVARIANT(!mflags);
956
957
0
  return mfs;
958
0
}
959
#endif  /* DEBUG */