Coverage Report

Created: 2023-05-19 06:16

/src/ntp-dev/ntpd/ntp_restrict.c
Line
Count
Source (jump to first uncovered line)
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 hosts we want
19
 * to place restrictions on (or remove them from). The restrictions
20
 * are implemented as a set of flags which tell you what the host
21
 * can't do. There is a subroutine entry to return the flags. The
22
 * list is kept sorted to reduce the average number of comparisons
23
 * and make sure you get the set of restrictions most specific to
24
 * the address.
25
 *
26
 * The algorithm is that, when looking up a host, it is first assumed
27
 * that the default set of restrictions will apply. It then searches
28
 * down through the list. Whenever it finds a match it adopts the
29
 * match's flags instead. When you hit the point where the sorted
30
 * address is greater than the target, you return with the last set of
31
 * flags you found. Because of the ordering of the list, the most
32
 * specific match will provide the final set of flags.
33
 *
34
 * This was originally intended to restrict you from sync'ing to your
35
 * own broadcasts when you are doing that, by restricting yourself from
36
 * your own interfaces. It was also thought it would sometimes be useful
37
 * to keep a misbehaving host or two from abusing your primary clock. It
38
 * has been expanded, however, to suit the needs of those with more
39
 * restrictive access policies.
40
 */
41
/*
42
 * We will use two lists, one for IPv4 addresses and one for IPv6
43
 * addresses. This is not protocol-independant but for now I can't
44
 * find a way to respect this. We'll check this later... JFB 07/2001
45
 */
46
#define MASK_IPV6_ADDR(dst, src, msk)         \
47
1.01k
  do {               \
48
1.01k
    int idx;            \
49
17.2k
    for (idx = 0; idx < (int)COUNTOF((dst)->s6_addr); idx++) { \
50
16.2k
      (dst)->s6_addr[idx] = (src)->s6_addr[idx] \
51
16.2k
                & (msk)->s6_addr[idx];  \
52
16.2k
    }              \
53
1.01k
  } while (0)
54
55
/*
56
 * We allocate INC_RESLIST{4|6} entries to the free list whenever empty.
57
 * Auto-tune these to be just less than 1KB (leaving at least 16 bytes
58
 * for allocator overhead).
59
 */
60
2
#define INC_RESLIST4  ((1024 - 16) / V4_SIZEOF_RESTRICT_U)
61
0
#define INC_RESLIST6  ((1024 - 16) / V6_SIZEOF_RESTRICT_U)
62
63
/*
64
 * The restriction list
65
 */
66
restrict_u *restrictlist4;
67
restrict_u *restrictlist6;
68
static int restrictcount; /* count in the restrict lists */
69
70
/*
71
 * The free list and associated counters.  Also some uninteresting
72
 * stat counters.
73
 */
74
static restrict_u *resfree4;  /* available entries (free list) */
75
static restrict_u *resfree6;
76
77
static u_long res_calls;
78
static u_long res_found;
79
static u_long res_not_found;
80
81
/*
82
 * Count number of restriction entries referring to RES_LIMITED, to
83
 * control implicit activation/deactivation of the MRU monlist.
84
 */
85
static  u_long res_limited_refcnt;
86
87
/*
88
 * Our default entries.
89
 *
90
 * We can make this cleaner with c99 support: see init_restrict().
91
 */
92
static  restrict_u  restrict_def4;
93
static  restrict_u  restrict_def6;
94
95
/*
96
 * "restrict source ..." enabled knob and restriction bits.
97
 */
98
static  int   restrict_source_enabled;
99
static  u_short   restrict_source_rflags;
100
static  u_short   restrict_source_mflags;
101
static  short   restrict_source_ippeerlimit;
102
103
/*
104
 * private functions
105
 */
106
static restrict_u * alloc_res4(void);
107
static restrict_u * alloc_res6(void);
108
static void   free_res(restrict_u *, int);
109
static void   inc_res_limited(void);
110
static void   dec_res_limited(void);
111
static restrict_u * match_restrict4_addr(u_int32, u_short);
112
static restrict_u * match_restrict6_addr(const struct in6_addr *,
113
               u_short);
114
static restrict_u * match_restrict_entry(const restrict_u *, int);
115
static int    res_sorts_before4(restrict_u *, restrict_u *);
116
static int    res_sorts_before6(restrict_u *, restrict_u *);
117
static char *   roptoa(restrict_op op);
118
119
120
void  dump_restricts(void);
121
122
/*
123
 * dump_restrict - spit out a restrict_u
124
 */
125
static void
126
dump_restrict(
127
  restrict_u *  res,
128
  int   is_ipv6
129
  )
130
0
{
131
0
  char as[INET6_ADDRSTRLEN];
132
0
  char ms[INET6_ADDRSTRLEN];
133
134
0
  if (is_ipv6) {
135
0
    inet_ntop(AF_INET6, &res->u.v6.addr, as, sizeof as);
136
0
    inet_ntop(AF_INET6, &res->u.v6.mask, ms, sizeof ms);
137
0
  } else {
138
0
    struct in_addr  sia = { htonl(res->u.v4.addr) };
139
0
    struct in_addr  sim = { htonl(res->u.v4.mask) };
140
141
0
    inet_ntop(AF_INET, &sia, as, sizeof as);
142
0
    inet_ntop(AF_INET, &sim, ms, sizeof ms);
143
0
  }
144
0
  mprintf("restrict node at %p: %s/%s count %d, rflags %05x, mflags %05x, ippeerlimit %d, expire %lu, next %p\n",
145
0
    res, as, ms, res->count, res->rflags, res->mflags,
146
0
    res->ippeerlimit, res->expire, res->link);
147
0
  return;
148
0
}
149
150
151
/*
152
 * dump_restricts - spit out the 'restrict' lines
153
 */
154
void
155
dump_restricts(void)
156
0
{
157
0
  int   defaultv4_done = 0;
158
0
  int   defaultv6_done = 0;
159
0
  restrict_u *  res;
160
0
  restrict_u *  next;
161
162
0
  mprintf("dump_restrict: restrict_def4: %p\n", &restrict_def4);
163
  /* Spit out 'restrict {,-4,-6} default ...' lines, if needed */
164
0
  for (res = &restrict_def4; res != NULL; res = next) {
165
0
    dump_restrict(res, 0);
166
0
    next = res->link;
167
0
  }
168
169
0
  mprintf("dump_restrict: restrict_def6: %p\n", &restrict_def6);
170
0
  for (res = &restrict_def6; res != NULL; res = next) {
171
0
    dump_restrict(res, 1);
172
0
    next = res->link;
173
0
  }
174
175
  /* Spit out the IPv4 list */
176
0
  mprintf("dump_restrict: restrictlist4: %p\n", &restrictlist4);
177
0
  for (res = restrictlist4; res != NULL; res = next) {
178
0
    dump_restrict(res, 0);
179
0
    next = res->link;
180
0
  }
181
182
  /* Spit out the IPv6 list */
183
0
  mprintf("dump_restrict: restrictlist6: %p\n", &restrictlist6);
184
0
  for (res = restrictlist6; res != NULL; res = next) {
185
0
    dump_restrict(res, 1);
186
0
    next = res->link;
187
0
  }
188
189
0
  return;
190
0
}
191
192
/*
193
 * init_restrict - initialize the restriction data structures
194
 */
195
void
196
init_restrict(void)
197
1
{
198
  /*
199
   * The restriction lists begin with a default entry with address
200
   * and mask 0, which will match any entry.  The lists are kept
201
   * sorted by descending address followed by descending mask:
202
   *
203
   *   address    mask
204
   * 192.168.0.0  255.255.255.0 kod limited noquery nopeer
205
   * 192.168.0.0  255.255.0.0 kod limited
206
   * 0.0.0.0  0.0.0.0   kod limited noquery
207
   *
208
   * The first entry which matches an address is used.  With the
209
   * example restrictions above, 192.168.0.0/24 matches the first
210
   * entry, the rest of 192.168.0.0/16 matches the second, and
211
   * everything else matches the third (default).
212
   *
213
   * Note this achieves the same result a little more efficiently
214
   * than the documented behavior, which is to keep the lists
215
   * sorted by ascending address followed by ascending mask, with
216
   * the _last_ matching entry used.
217
   *
218
   * An additional wrinkle is we may have multiple entries with
219
   * the same address and mask but differing match flags (mflags).
220
   * At present there is only one, RESM_NTPONLY.  Entries with
221
   * RESM_NTPONLY are sorted earlier so they take precedence over
222
   * any otherwise similar entry without.  Again, this is the same
223
   * behavior as but reversed implementation compared to the docs.
224
   * 
225
   */
226
227
1
  restrict_def4.ippeerlimit = -1;   /* Cleaner if we have C99 */
228
1
  restrict_def6.ippeerlimit = -1;   /* Cleaner if we have C99 */
229
230
1
  LINK_SLIST(restrictlist4, &restrict_def4, link);
231
1
  LINK_SLIST(restrictlist6, &restrict_def6, link);
232
1
  restrictcount = 2;
233
1
}
234
235
236
static restrict_u *
237
alloc_res4(void)
238
2
{
239
2
  const size_t  cb = V4_SIZEOF_RESTRICT_U;
240
2
  const size_t  count = INC_RESLIST4;
241
2
  restrict_u *  rl;
242
2
  restrict_u *  res;
243
2
  size_t    i;
244
245
2
  UNLINK_HEAD_SLIST(res, resfree4, link);
246
2
  if (res != NULL)
247
1
    return res;
248
249
1
  rl = eallocarray(count, cb);
250
  /* link all but the first onto free list */
251
1
  res = (void *)((char *)rl + (count - 1) * cb);
252
25
  for (i = count - 1; i > 0; i--) {
253
24
    LINK_SLIST(resfree4, res, link);
254
24
    res = (void *)((char *)res - cb);
255
24
  }
256
1
  INSIST(rl == res);
257
  /* allocate the first */
258
0
  return res;
259
2
}
260
261
262
static restrict_u *
263
alloc_res6(void)
264
0
{
265
0
  const size_t  cb = V6_SIZEOF_RESTRICT_U;
266
0
  const size_t  count = INC_RESLIST6;
267
0
  restrict_u *  rl;
268
0
  restrict_u *  res;
269
0
  size_t    i;
270
271
0
  UNLINK_HEAD_SLIST(res, resfree6, link);
272
0
  if (res != NULL)
273
0
    return res;
274
275
0
  rl = eallocarray(count, cb);
276
  /* link all but the first onto free list */
277
0
  res = (void *)((char *)rl + (count - 1) * cb);
278
0
  for (i = count - 1; i > 0; i--) {
279
0
    LINK_SLIST(resfree6, res, link);
280
0
    res = (void *)((char *)res - cb);
281
0
  }
282
0
  INSIST(rl == res);
283
  /* allocate the first */
284
0
  return res;
285
0
}
286
287
288
static void
289
free_res(
290
  restrict_u *  res,
291
  int   v6
292
  )
293
0
{
294
0
  restrict_u ** plisthead;
295
0
  restrict_u *  unlinked;
296
297
0
  restrictcount--;
298
0
  if (RES_LIMITED & res->rflags)
299
0
    dec_res_limited();
300
301
0
  if (v6)
302
0
    plisthead = &restrictlist6;
303
0
  else
304
0
    plisthead = &restrictlist4;
305
0
  UNLINK_SLIST(unlinked, *plisthead, res, link, restrict_u);
306
0
  INSIST(unlinked == res);
307
308
0
  if (v6) {
309
0
    zero_mem(res, V6_SIZEOF_RESTRICT_U);
310
0
    plisthead = &resfree6;
311
0
  } else {
312
0
    zero_mem(res, V4_SIZEOF_RESTRICT_U);
313
0
    plisthead = &resfree4;
314
0
  }
315
0
  LINK_SLIST(*plisthead, res, link);
316
0
}
317
318
319
static void
320
inc_res_limited(void)
321
0
{
322
0
  if (!res_limited_refcnt)
323
0
    mon_start(MON_RES);
324
0
  res_limited_refcnt++;
325
0
}
326
327
328
static void
329
dec_res_limited(void)
330
0
{
331
0
  res_limited_refcnt--;
332
0
  if (!res_limited_refcnt)
333
0
    mon_stop(MON_RES);
334
0
}
335
336
337
static restrict_u *
338
match_restrict4_addr(
339
  u_int32 addr,
340
  u_short port
341
  )
342
702
{
343
702
  const int v6 = 0;
344
702
  restrict_u *  res;
345
702
  restrict_u *  next;
346
347
2.10k
  for (res = restrictlist4; res != NULL; res = next) {
348
2.10k
    struct in_addr  sia = { htonl(res->u.v4.addr) };
349
350
2.10k
    next = res->link;
351
2.10k
    DPRINTF(2, ("match_restrict4_addr: Checking %s, port %d ... ",
352
2.10k
          inet_ntoa(sia), port));
353
2.10k
    if (   res->expire
354
2.10k
        && res->expire <= current_time)
355
0
      free_res(res, v6); /* zeroes the contents */
356
2.10k
    if (   res->u.v4.addr == (addr & res->u.v4.mask)
357
2.10k
        && (   !(RESM_NTPONLY & res->mflags)
358
703
      || NTP_PORT == port)) {
359
702
      DPRINTF(2, ("MATCH: ippeerlimit %d\n", res->ippeerlimit));
360
702
      break;
361
702
    }
362
1.40k
    DPRINTF(2, ("doesn't match: ippeerlimit %d\n", res->ippeerlimit));
363
1.40k
  }
364
702
  return res;
365
702
}
366
367
368
static restrict_u *
369
match_restrict6_addr(
370
  const struct in6_addr * addr,
371
  u_short     port
372
  )
373
1.01k
{
374
1.01k
  const int v6 = 1;
375
1.01k
  restrict_u *  res;
376
1.01k
  restrict_u *  next;
377
1.01k
  struct in6_addr masked;
378
379
1.01k
  for (res = restrictlist6; res != NULL; res = next) {
380
1.01k
    next = res->link;
381
1.01k
    INSIST(next != res);
382
1.01k
    if (res->expire &&
383
1.01k
        res->expire <= current_time)
384
0
      free_res(res, v6);
385
1.01k
    MASK_IPV6_ADDR(&masked, addr, &res->u.v6.mask);
386
1.01k
    if (ADDR6_EQ(&masked, &res->u.v6.addr)
387
1.01k
        && (!(RESM_NTPONLY & res->mflags)
388
1.01k
      || NTP_PORT == (int)port))
389
1.01k
      break;
390
1.01k
  }
391
1.01k
  return res;
392
1.01k
}
393
394
395
/*
396
 * match_restrict_entry - find an exact match on a restrict list.
397
 *
398
 * Exact match is addr, mask, and mflags all equal.
399
 * In order to use more common code for IPv4 and IPv6, this routine
400
 * requires the caller to populate a restrict_u with mflags and either
401
 * the v4 or v6 address and mask as appropriate.  Other fields in the
402
 * input restrict_u are ignored.
403
 */
404
static restrict_u *
405
match_restrict_entry(
406
  const restrict_u *  pmatch,
407
  int     v6
408
  )
409
2
{
410
2
  restrict_u *res;
411
2
  restrict_u *rlist;
412
2
  size_t cb;
413
414
2
  if (v6) {
415
0
    rlist = restrictlist6;
416
0
    cb = sizeof(pmatch->u.v6);
417
2
  } else {
418
2
    rlist = restrictlist4;
419
2
    cb = sizeof(pmatch->u.v4);
420
2
  }
421
422
5
  for (res = rlist; res != NULL; res = res->link)
423
3
    if (res->mflags == pmatch->mflags &&
424
3
        !memcmp(&res->u, &pmatch->u, cb))
425
0
      break;
426
2
  return res;
427
2
}
428
429
430
/*
431
 * res_sorts_before4 - compare two restrict4 entries
432
 *
433
 * Returns nonzero if r1 sorts before r2.  We sort by descending
434
 * address, then descending mask, then descending mflags, so sorting
435
 * before means having a higher value.
436
 */
437
static int
438
res_sorts_before4(
439
  restrict_u *r1,
440
  restrict_u *r2
441
  )
442
2
{
443
2
  int r1_before_r2;
444
445
2
  if (r1->u.v4.addr > r2->u.v4.addr)
446
2
    r1_before_r2 = 1;
447
0
  else if (r1->u.v4.addr < r2->u.v4.addr)
448
0
    r1_before_r2 = 0;
449
0
  else if (r1->u.v4.mask > r2->u.v4.mask)
450
0
    r1_before_r2 = 1;
451
0
  else if (r1->u.v4.mask < r2->u.v4.mask)
452
0
    r1_before_r2 = 0;
453
0
  else if (r1->mflags > r2->mflags)
454
0
    r1_before_r2 = 1;
455
0
  else
456
0
    r1_before_r2 = 0;
457
458
2
  return r1_before_r2;
459
2
}
460
461
462
/*
463
 * res_sorts_before6 - compare two restrict6 entries
464
 *
465
 * Returns nonzero if r1 sorts before r2.  We sort by descending
466
 * address, then descending mask, then descending mflags, so sorting
467
 * before means having a higher value.
468
 */
469
static int
470
res_sorts_before6(
471
  restrict_u *r1,
472
  restrict_u *r2
473
  )
474
0
{
475
0
  int r1_before_r2;
476
0
  int cmp;
477
478
0
  cmp = ADDR6_CMP(&r1->u.v6.addr, &r2->u.v6.addr);
479
0
  if (cmp > 0)   /* r1->addr > r2->addr */
480
0
    r1_before_r2 = 1;
481
0
  else if (cmp < 0) /* r2->addr > r1->addr */
482
0
    r1_before_r2 = 0;
483
0
  else {
484
0
    cmp = ADDR6_CMP(&r1->u.v6.mask, &r2->u.v6.mask);
485
0
    if (cmp > 0)   /* r1->mask > r2->mask*/
486
0
      r1_before_r2 = 1;
487
0
    else if (cmp < 0) /* r2->mask > r1->mask */
488
0
      r1_before_r2 = 0;
489
0
    else if (r1->mflags > r2->mflags)
490
0
      r1_before_r2 = 1;
491
0
    else
492
0
      r1_before_r2 = 0;
493
0
  }
494
495
0
  return r1_before_r2;
496
0
}
497
498
499
/*
500
 * restrictions - return restrictions for this host in *r4a
501
 */
502
void
503
restrictions(
504
  sockaddr_u *srcadr,
505
  r4addr *r4a
506
  )
507
1.74k
{
508
1.74k
  restrict_u *match;
509
1.74k
  struct in6_addr *pin6;
510
511
1.74k
  REQUIRE(NULL != r4a);
512
513
0
  res_calls++;
514
1.74k
  r4a->rflags = RES_IGNORE;
515
1.74k
  r4a->ippeerlimit = 0;
516
517
1.74k
  DPRINTF(1, ("restrictions: looking up %s\n", stoa(srcadr)));
518
519
  /* IPv4 source address */
520
1.74k
  if (IS_IPV4(srcadr)) {
521
    /*
522
     * Ignore any packets with a multicast source address
523
     * (this should be done early in the receive process,
524
     * not later!)
525
     */
526
703
    if (IN_CLASSD(SRCADR(srcadr))) {
527
1
      DPRINTF(1, ("restrictions: srcadr %s is multicast\n", stoa(srcadr)));
528
1
      r4a->ippeerlimit = 2; /* XXX: we should use a better value */
529
1
      return;
530
1
    }
531
532
702
    match = match_restrict4_addr(SRCADR(srcadr),
533
702
               SRCPORT(srcadr));
534
535
702
    INSIST(match != NULL);
536
537
0
    match->count++;
538
    /*
539
     * res_not_found counts only use of the final default
540
     * entry, not any "restrict default ntpport ...", which
541
     * would be just before the final default.
542
     */
543
702
    if (&restrict_def4 == match)
544
702
      res_not_found++;
545
0
    else
546
0
      res_found++;
547
702
    r4a->rflags = match->rflags;
548
702
    r4a->ippeerlimit = match->ippeerlimit;
549
702
  }
550
551
  /* IPv6 source address */
552
1.74k
  if (IS_IPV6(srcadr)) {
553
1.01k
    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
1.01k
    if (IN6_IS_ADDR_MULTICAST(pin6))
561
1
      return;
562
563
1.01k
    match = match_restrict6_addr(pin6, SRCPORT(srcadr));
564
1.01k
    INSIST(match != NULL);
565
0
    match->count++;
566
1.01k
    if (&restrict_def6 == match)
567
1.01k
      res_not_found++;
568
0
    else
569
0
      res_found++;
570
1.01k
    r4a->rflags = match->rflags;
571
1.01k
    r4a->ippeerlimit = match->ippeerlimit;
572
1.01k
  }
573
1.74k
  return;
574
1.74k
}
575
576
577
/*
578
 * roptoa - convert a restrict_op to a string
579
 */
580
char *
581
0
roptoa(restrict_op op) {
582
0
  static char sb[30];
583
584
0
  switch(op) {
585
0
      case RESTRICT_FLAGS:  return "RESTRICT_FLAGS";
586
0
      case RESTRICT_UNFLAG: return "RESTRICT_UNFLAGS";
587
0
      case RESTRICT_REMOVE: return "RESTRICT_REMOVE";
588
0
      case RESTRICT_REMOVEIF: return "RESTRICT_REMOVEIF";
589
0
      default:
590
0
    snprintf(sb, sizeof sb, "**RESTRICT_#%d**", op);
591
0
    return sb;
592
0
  }
593
0
}
594
595
596
/*
597
 * hack_restrict - add/subtract/manipulate entries on the restrict list
598
 */
599
void
600
hack_restrict(
601
  restrict_op op,
602
  sockaddr_u *  resaddr,
603
  sockaddr_u *  resmask,
604
  short   ippeerlimit,
605
  u_short   mflags,
606
  u_short   rflags,
607
  u_long    expire
608
  )
609
2
{
610
2
  int   v6;
611
2
  restrict_u  match;
612
2
  restrict_u *  res;
613
2
  restrict_u ** plisthead;
614
615
2
  DPRINTF(1, ("hack_restrict: op %s addr %s mask %s ippeerlimit %d mflags %08x rflags %08x\n",
616
2
        roptoa(op), stoa(resaddr), stoa(resmask), ippeerlimit, mflags, rflags));
617
618
2
  if (NULL == resaddr) {
619
0
    REQUIRE(NULL == resmask);
620
0
    REQUIRE(RESTRICT_FLAGS == op);
621
0
    restrict_source_rflags = rflags;
622
0
    restrict_source_mflags = mflags;
623
0
    restrict_source_ippeerlimit = ippeerlimit;
624
0
    restrict_source_enabled = 1;
625
0
    return;
626
0
  }
627
628
2
  ZERO(match);
629
630
#if 0
631
  /* silence VC9 potentially uninit warnings */
632
  // HMS: let's use a compiler-specific "enable" for this.
633
  res = NULL;
634
  v6 = 0;
635
#endif
636
637
2
  if (IS_IPV4(resaddr)) {
638
2
    v6 = 0;
639
    /*
640
     * Get address and mask in host byte order for easy
641
     * comparison as u_int32
642
     */
643
2
    match.u.v4.addr = SRCADR(resaddr);
644
2
    match.u.v4.mask = SRCADR(resmask);
645
2
    match.u.v4.addr &= match.u.v4.mask;
646
647
2
  } else if (IS_IPV6(resaddr)) {
648
0
    v6 = 1;
649
    /*
650
     * Get address and mask in network byte order for easy
651
     * comparison as byte sequences (e.g. memcmp())
652
     */
653
0
    match.u.v6.mask = SOCK_ADDR6(resmask);
654
0
    MASK_IPV6_ADDR(&match.u.v6.addr, PSOCK_ADDR6(resaddr),
655
0
             &match.u.v6.mask);
656
657
0
  } else  /* not IPv4 nor IPv6 */
658
0
    REQUIRE(0);
659
660
0
  match.rflags = rflags;
661
2
  match.mflags = mflags;
662
2
  match.ippeerlimit = ippeerlimit;
663
2
  match.expire = expire;
664
2
  res = match_restrict_entry(&match, v6);
665
666
2
  switch (op) {
667
668
2
  case RESTRICT_FLAGS:
669
    /*
670
     * Here we add bits to the rflags. If this is a
671
     * new restriction add it.
672
     */
673
2
    if (NULL == res) {
674
2
      if (v6) {
675
0
        res = alloc_res6();
676
0
        memcpy(res, &match,
677
0
               V6_SIZEOF_RESTRICT_U);
678
0
        plisthead = &restrictlist6;
679
2
      } else {
680
2
        res = alloc_res4();
681
2
        memcpy(res, &match,
682
2
               V4_SIZEOF_RESTRICT_U);
683
2
        plisthead = &restrictlist4;
684
2
      }
685
2
      LINK_SORT_SLIST(
686
2
        *plisthead, res,
687
2
        (v6)
688
2
          ? res_sorts_before6(res, L_S_S_CUR())
689
2
          : res_sorts_before4(res, L_S_S_CUR()),
690
2
        link, restrict_u);
691
2
      restrictcount++;
692
2
      if (RES_LIMITED & rflags)
693
0
        inc_res_limited();
694
2
    } else {
695
0
      if (   (RES_LIMITED & rflags)
696
0
          && !(RES_LIMITED & res->rflags))
697
0
        inc_res_limited();
698
0
      res->rflags |= rflags;
699
0
    }
700
701
2
    res->ippeerlimit = match.ippeerlimit;
702
703
2
    break;
704
705
0
  case RESTRICT_UNFLAG:
706
    /*
707
     * Remove some bits from the rflags. If we didn't
708
     * find this one, just return.
709
     */
710
0
    if (res != NULL) {
711
0
      if (   (RES_LIMITED & res->rflags)
712
0
          && (RES_LIMITED & rflags))
713
0
        dec_res_limited();
714
0
      res->rflags &= ~rflags;
715
0
    }
716
0
    break;
717
718
0
  case RESTRICT_REMOVE:
719
0
  case RESTRICT_REMOVEIF:
720
    /*
721
     * Remove an entry from the table entirely if we
722
     * found one. Don't remove the default entry and
723
     * don't remove an interface entry.
724
     */
725
0
    if (res != NULL
726
0
        && (RESTRICT_REMOVEIF == op
727
0
      || !(RESM_INTERFACE & res->mflags))
728
0
        && res != &restrict_def4
729
0
        && res != &restrict_def6)
730
0
      free_res(res, v6);
731
0
    break;
732
733
0
  default:  /* unknown op */
734
0
    INSIST(0);
735
0
    break;
736
2
  }
737
738
2
}
739
740
741
/*
742
 * restrict_source - maintains dynamic "restrict source ..." entries as
743
 *         peers come and go.
744
 */
745
void
746
restrict_source(
747
  sockaddr_u *  addr,
748
  int   farewell, /* 0 to add, 1 to remove */
749
  u_long    expire    /* 0 is infinite, valid until */
750
  )
751
0
{
752
0
  sockaddr_u  onesmask;
753
0
  restrict_u *  res;
754
0
  int   found_specific;
755
756
0
  if (!restrict_source_enabled || SOCK_UNSPEC(addr) ||
757
0
      IS_MCAST(addr) || ISREFCLOCKADR(addr))
758
0
    return;
759
760
0
  REQUIRE(AF_INET == AF(addr) || AF_INET6 == AF(addr));
761
762
0
  SET_HOSTMASK(&onesmask, AF(addr));
763
0
  if (farewell) {
764
0
    hack_restrict(RESTRICT_REMOVE, addr, &onesmask,
765
0
            -2, 0, 0, 0);
766
0
    DPRINTF(1, ("restrict_source: %s removed", stoa(addr)));
767
0
    return;
768
0
  }
769
770
  /*
771
   * If there is a specific entry for this address, hands
772
   * off, as it is condidered more specific than "restrict
773
   * server ...".
774
   * However, if the specific entry found is a fleeting one
775
   * added by pool_xmit() before soliciting, replace it
776
   * immediately regardless of the expire value to make way
777
   * for the more persistent entry.
778
   */
779
0
  if (IS_IPV4(addr)) {
780
0
    res = match_restrict4_addr(SRCADR(addr), SRCPORT(addr));
781
0
    INSIST(res != NULL);
782
0
    found_specific = (SRCADR(&onesmask) == res->u.v4.mask);
783
0
  } else {
784
0
    res = match_restrict6_addr(&SOCK_ADDR6(addr),
785
0
             SRCPORT(addr));
786
0
    INSIST(res != NULL);
787
0
    found_specific = ADDR6_EQ(&res->u.v6.mask,
788
0
            &SOCK_ADDR6(&onesmask));
789
0
  }
790
0
  if (!expire && found_specific && res->expire) {
791
0
    found_specific = 0;
792
0
    free_res(res, IS_IPV6(addr));
793
0
  }
794
0
  if (found_specific)
795
0
    return;
796
797
0
  hack_restrict(RESTRICT_FLAGS, addr, &onesmask,
798
0
          restrict_source_ippeerlimit, restrict_source_mflags,
799
0
          restrict_source_rflags, expire);
800
0
  DPRINTF(1, ("restrict_source: %s host restriction added\n", 
801
0
        stoa(addr)));
802
0
}