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