Home | History | Annotate | Line # | Download | only in ntpd
      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
    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
    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
    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
    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
    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 *
    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 *
    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
    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
    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
    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
    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 *
    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 *
    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 *
    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 *
    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*/
    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*/
    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*/
    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
    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 *
    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*/
    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
    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 *
    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 *
    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