Coverage Report

Created: 2026-02-26 06:20

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