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