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