xref: /freebsd/contrib/ntp/ntpd/ntp_restrict.c (revision 39beb93c3f8bdbf72a61fda42300b5ebed7390c8)
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_stdlib.h"
14 
15 /*
16  * This code keeps a simple address-and-mask list of hosts we want
17  * to place restrictions on (or remove them from). The restrictions
18  * are implemented as a set of flags which tell you what the host
19  * can't do. There is a subroutine entry to return the flags. The
20  * list is kept sorted to reduce the average number of comparisons
21  * and make sure you get the set of restrictions most specific to
22  * the address.
23  *
24  * The algorithm is that, when looking up a host, it is first assumed
25  * that the default set of restrictions will apply. It then searches
26  * down through the list. Whenever it finds a match it adopts the
27  * match's flags instead. When you hit the point where the sorted
28  * address is greater than the target, you return with the last set of
29  * flags you found. Because of the ordering of the list, the most
30  * specific match will provide the final set of flags.
31  *
32  * This was originally intended to restrict you from sync'ing to your
33  * own broadcasts when you are doing that, by restricting yourself from
34  * your own interfaces. It was also thought it would sometimes be useful
35  * to keep a misbehaving host or two from abusing your primary clock. It
36  * has been expanded, however, to suit the needs of those with more
37  * restrictive access policies.
38  */
39 /*
40  * We will use two lists, one for IPv4 addresses and one for IPv6
41  * addresses. This is not protocol-independant but for now I can't
42  * find a way to respect this. We'll check this later... JFB 07/2001
43  */
44 #define SET_IPV6_ADDR_MASK(dst, src, msk) \
45 	do { \
46 		int idx; \
47 		for (idx = 0; idx < 16; idx++) { \
48 			(dst)->s6_addr[idx] = \
49 			    (u_char) ((src)->s6_addr[idx] & (msk)->s6_addr[idx]); \
50 		} \
51 	} while (0)
52 
53 /*
54  * Memory allocation parameters.  We allocate INITRESLIST entries
55  * initially, and add INCRESLIST entries to the free list whenever
56  * we run out.
57  */
58 #define	INITRESLIST	10
59 #define	INCRESLIST	5
60 
61 #define RES_AVG		8.	/* interpacket averaging factor */
62 
63 /*
64  * The restriction list
65  */
66 struct restrictlist *restrictlist;
67 struct restrictlist6 *restrictlist6;
68 static	int restrictcount;	/* count of entries in the res list */
69 static	int restrictcount6;	/* count of entries in the res list 2*/
70 
71 /*
72  * The free list and associated counters.  Also some uninteresting
73  * stat counters.
74  */
75 static	struct restrictlist *resfree;
76 static	struct restrictlist6 *resfree6;
77 static	int numresfree;		/* number of structures on free list */
78 static	int numresfree6;	/* number of structures on free list 2 */
79 
80 static	u_long res_calls;
81 static	u_long res_found;
82 static	u_long res_not_found;
83 
84 /*
85  * Parameters of the RES_LIMITED restriction option.
86  */
87 u_long res_avg_interval = 5;	/* min average interpacket interval */
88 u_long res_min_interval = 1;	/* min interpacket interval */
89 
90 /*
91  * Count number of restriction entries referring to RES_LIMITED controls
92  * activation/deactivation of monitoring (with respect to RES_LIMITED
93  * control)
94  */
95 static	u_long res_limited_refcnt;
96 static	u_long res_limited_refcnt6;
97 
98 /*
99  * Our initial allocation of lists entries.
100  */
101 static	struct restrictlist resinit[INITRESLIST];
102 static	struct restrictlist6 resinit6[INITRESLIST];
103 
104 /*
105  * init_restrict - initialize the restriction data structures
106  */
107 void
108 init_restrict(void)
109 {
110 	register int i;
111 
112 	/*
113 	 * Zero the list and put all but one on the free list
114 	 */
115 	resfree = NULL;
116 	memset((char *)resinit, 0, sizeof resinit);
117 	resfree6 = NULL;
118 	memset((char *)resinit6, 0, sizeof resinit6);
119 	for (i = 1; i < INITRESLIST; i++) {
120 		resinit[i].next = resfree;
121 		resinit6[i].next = resfree6;
122 		resfree = &resinit[i];
123 		resfree6 = &resinit6[i];
124 	}
125 	numresfree = INITRESLIST-1;
126 	numresfree6 = INITRESLIST-1;
127 
128 	/*
129 	 * Put the remaining item at the head of the list as our default
130 	 * entry. Everything in here should be zero for now.
131 	 */
132 	resinit[0].addr = htonl(INADDR_ANY);
133 	resinit[0].mask = 0;
134 	memset(&resinit6[0].addr6, 0, sizeof(struct in6_addr));
135 	memset(&resinit6[0].mask6, 0, sizeof(struct in6_addr));
136 	restrictlist = &resinit[0];
137 	restrictlist6 = &resinit6[0];
138 	restrictcount = 1;
139 	restrictcount = 2;
140 
141 	/*
142 	 * fix up stat counters
143 	 */
144 	res_calls = 0;
145 	res_found = 0;
146 	res_not_found = 0;
147 
148 	/*
149 	 * set default values for RES_LIMIT functionality
150 	 */
151 	res_limited_refcnt = 0;
152 	res_limited_refcnt6 = 0;
153 }
154 
155 
156 /*
157  * restrictions - return restrictions for this host
158  */
159 int
160 restrictions(
161 	struct sockaddr_storage *srcadr,
162 	int at_listhead
163 	)
164 {
165 	struct restrictlist *rl;
166 	struct restrictlist *match = NULL;
167 	struct restrictlist6 *rl6;
168 	struct restrictlist6 *match6 = NULL;
169 	struct in6_addr hostaddr6;
170 	struct in6_addr hostservaddr6;
171 	u_int32	hostaddr;
172 	int	flags = 0;
173 	int	isntpport;
174 
175 	res_calls++;
176 	if (srcadr->ss_family == AF_INET) {
177 		/*
178 		 * We need the host address in host order.  Also need to
179 		 * know whether this is from the ntp port or not.
180 		 */
181 		hostaddr = SRCADR(srcadr);
182 		isntpport = (SRCPORT(srcadr) == NTP_PORT);
183 
184 		/*
185 		 * Ignore any packets with a multicast source address
186 		 * (this should be done early in the receive process,
187 		 * later!)
188 		 */
189 		if (IN_CLASSD(SRCADR(srcadr)))
190 			return (int)RES_IGNORE;
191 
192 		/*
193 		 * Set match to first entry, which is default entry.
194 		 * Work our way down from there.
195 		 */
196 		match = restrictlist;
197 		for (rl = match->next; rl != NULL && rl->addr <= hostaddr;
198 		    rl = rl->next)
199 			if ((hostaddr & rl->mask) == rl->addr) {
200 				if ((rl->mflags & RESM_NTPONLY) &&
201 				    !isntpport)
202 					continue;
203 				match = rl;
204 			}
205 		match->count++;
206 		if (match == restrictlist)
207 			res_not_found++;
208 		else
209 			res_found++;
210 		flags = match->flags;
211 	}
212 
213 	/* IPv6 source address */
214 	if (srcadr->ss_family == AF_INET6) {
215 		/*
216 		 * Need to know whether this is from the ntp port or
217 		 * not.
218 		 */
219 		hostaddr6 = GET_INADDR6(*srcadr);
220 		isntpport = (ntohs((
221 		    (struct sockaddr_in6 *)srcadr)->sin6_port) ==
222 		    NTP_PORT);
223 
224 		/*
225 		 * Ignore any packets with a multicast source address
226 		 * (this should be done early in the receive process,
227 		 * later!)
228 		 */
229 		if (IN6_IS_ADDR_MULTICAST(&hostaddr6))
230 			return (int)RES_IGNORE;
231 
232 		/*
233 		 * Set match to first entry, which is default entry.
234 		 *  Work our way down from there.
235 		 */
236 		match6 = restrictlist6;
237 		for (rl6 = match6->next; rl6 != NULL &&
238 		    (memcmp(&(rl6->addr6), &hostaddr6,
239 		    sizeof(hostaddr6)) <= 0); rl6 = rl6->next) {
240 			SET_IPV6_ADDR_MASK(&hostservaddr6, &hostaddr6,
241 			    &rl6->mask6);
242 			if (memcmp(&hostservaddr6, &(rl6->addr6),
243 			    sizeof(hostservaddr6)) == 0) {
244 				if ((rl6->mflags & RESM_NTPONLY) &&
245 				    !isntpport)
246 					continue;
247 				match6 = rl6;
248 			}
249 		}
250 		match6->count++;
251 		if (match6 == restrictlist6)
252 			res_not_found++;
253 		else
254 			res_found++;
255 		flags = match6->flags;
256 	}
257 
258 	/*
259 	 * The following implements a generalized call gap facility.
260 	 * Douse the RES_LIMITED bit only if the interval since the last
261 	 * packet is greater than res_min_interval and the average is
262 	 * greater thatn res_avg_interval.
263 	 */
264 	if (!at_listhead || mon_enabled == MON_OFF) {
265 		flags &= ~RES_LIMITED;
266 	} else {
267 		struct mon_data *md;
268 
269 		/*
270 		 * At this poin the most recent arrival is first in the
271 		 * MRU list. Let the first 10 packets in for free until
272 		 * the average stabilizes.
273 		 */
274 		md = mon_mru_list.mru_next;
275 		if (md->avg_interval == 0)
276 			md->avg_interval = md->drop_count;
277 		else
278 			md->avg_interval += (md->drop_count -
279 			    md->avg_interval) / RES_AVG;
280 		if (md->count < 10 || (md->drop_count >
281 		    res_min_interval && md->avg_interval >
282 		    res_avg_interval))
283 			flags &= ~RES_LIMITED;
284 		md->drop_count = flags;
285 	}
286 	return (flags);
287 }
288 
289 
290 /*
291  * hack_restrict - add/subtract/manipulate entries on the restrict list
292  */
293 void
294 hack_restrict(
295 	int op,
296 	struct sockaddr_storage *resaddr,
297 	struct sockaddr_storage *resmask,
298 	int mflags,
299 	int flags
300 	)
301 {
302 	register u_int32 addr = 0;
303 	register u_int32 mask = 0;
304 	struct in6_addr addr6;
305 	struct in6_addr mask6;
306 	register struct restrictlist *rl = NULL;
307 	register struct restrictlist *rlprev = NULL;
308 	register struct restrictlist6 *rl6 = NULL;
309 	register struct restrictlist6 *rlprev6 = NULL;
310 	int i, addr_cmp, mask_cmp;
311 	memset(&addr6, 0, sizeof(struct in6_addr));
312 	memset(&mask6, 0, sizeof(struct in6_addr));
313 
314 	if (resaddr->ss_family == AF_INET) {
315 		/*
316 		 * Get address and mask in host byte order
317 		 */
318 		addr = SRCADR(resaddr);
319 		mask = SRCADR(resmask);
320 		addr &= mask;		/* make sure low bits zero */
321 
322 		/*
323 		 * If this is the default address, point at first on
324 		 * list. Else go searching for it.
325 		 */
326 		if (addr == 0) {
327 			rlprev = NULL;
328 			rl = restrictlist;
329 		} else {
330 			rlprev = restrictlist;
331 			rl = rlprev->next;
332 			while (rl != NULL) {
333 				if (rl->addr > addr) {
334 					rl = NULL;
335 					break;
336 				} else if (rl->addr == addr) {
337 					if (rl->mask == mask) {
338 						if ((mflags &
339 						    RESM_NTPONLY) ==
340 						    (rl->mflags &
341 						    RESM_NTPONLY))
342 							break;
343 
344 						if (!(mflags &
345 						    RESM_NTPONLY)) {
346 							rl = NULL;
347 							break;
348 						}
349 					} else if (rl->mask > mask) {
350 						rl = NULL;
351 						break;
352 					}
353 				}
354 				rlprev = rl;
355 				rl = rl->next;
356 			}
357 		}
358 	}
359 
360 	if (resaddr->ss_family == AF_INET6) {
361 		mask6 = GET_INADDR6(*resmask);
362 		SET_IPV6_ADDR_MASK(&addr6,
363 		    &GET_INADDR6(*resaddr), &mask6);
364 		if (IN6_IS_ADDR_UNSPECIFIED(&addr6)) {
365 			rlprev6 = NULL;
366 			rl6 = restrictlist6;
367 		} else {
368 			rlprev6 = restrictlist6;
369 			rl6 = rlprev6->next;
370 			while (rl6 != NULL) {
371 				addr_cmp = memcmp(&rl6->addr6, &addr6,
372 				    sizeof(addr6));
373 				if (addr_cmp > 0) {
374 					rl6 = NULL;
375 					break;
376 				} else if (addr_cmp == 0) {
377 					mask_cmp = memcmp(&rl6->mask6,
378 					    &mask6, sizeof(mask6));
379 					if (mask_cmp == 0) {
380 						if ((mflags &
381 						    RESM_NTPONLY) ==
382 						    (rl6->mflags &
383 						    RESM_NTPONLY))
384 							break;
385 
386 						if (!(mflags &
387 						    RESM_NTPONLY)) {
388 							rl6 = NULL;
389 							break;
390 						}
391 					} else if (mask_cmp > 0) {
392 						rl6 = NULL;
393 						break;
394 					}
395 				}
396 				rlprev6 = rl6;
397 				rl6 = rl6->next;
398 			}
399 		}
400 	}
401 
402 	/*
403 	 * In case the above wasn't clear :-), either rl now points
404 	 * at the entry this call refers to, or rl is zero and rlprev
405 	 * points to the entry prior to where this one should go in
406 	 * the sort.
407 	 */
408 
409 	/*
410 	 * Switch based on operation
411 	 */
412 	if (resaddr->ss_family == AF_INET) {
413 		switch (op) {
414 		case RESTRICT_FLAGS:
415 			/*
416 			 * Here we add bits to the flags. If this is a
417 			 * new restriction add it.
418 			 */
419 			if (rl == NULL) {
420 				if (resfree == NULL) {
421 					rl = (struct restrictlist *)
422 					    emalloc(INCRESLIST *
423 					    sizeof(struct
424 					    restrictlist));
425 					memset((char *)rl, 0,
426 					    INCRESLIST * sizeof(struct
427 					    restrictlist));
428 					for (i = 0; i < INCRESLIST; i++) {
429 						rl->next = resfree;
430 						resfree = rl;
431 						rl++;
432 					}
433 					numresfree = INCRESLIST;
434 				}
435 
436 				rl = resfree;
437 				resfree = rl->next;
438 				numresfree--;
439 
440 				rl->addr = addr;
441 				rl->mask = mask;
442 				rl->mflags = (u_short)mflags;
443 
444 				if (rlprev == NULL) {
445 					rl->next = restrictlist;
446 					restrictlist = rl;
447 				} else {
448 					rl->next = rlprev->next;
449 					rlprev->next = rl;
450 				}
451 				restrictcount++;
452 			}
453 			if ((rl->flags ^ (u_short)flags) &
454 			    RES_LIMITED) {
455 				res_limited_refcnt++;
456 				mon_start(MON_RES);
457 			}
458 			rl->flags |= (u_short)flags;
459 			break;
460 
461 		case RESTRICT_UNFLAG:
462 			/*
463 			 * Remove some bits from the flags. If we didn't
464 			 * find this one, just return.
465 			 */
466 			if (rl != NULL) {
467 				if ((rl->flags ^ (u_short)flags) &
468 				    RES_LIMITED) {
469 					res_limited_refcnt--;
470 					if (res_limited_refcnt == 0)
471 						mon_stop(MON_RES);
472 				}
473 				rl->flags &= (u_short)~flags;
474 			}
475 			break;
476 
477 		case RESTRICT_REMOVE:
478 		case RESTRICT_REMOVEIF:
479 			/*
480 			 * Remove an entry from the table entirely if we
481 			 * found one. Don't remove the default entry and
482 			 * don't remove an interface entry.
483 			 */
484 			if (rl != NULL
485 			    && rl->addr != htonl(INADDR_ANY)
486 			    && !(rl->mflags & RESM_INTERFACE && op != RESTRICT_REMOVEIF)) {
487 				if (rlprev != NULL) {
488 					rlprev->next = rl->next;
489 				} else {
490 					restrictlist = rl->next;
491 				}
492 				restrictcount--;
493 				if (rl->flags & RES_LIMITED) {
494 					res_limited_refcnt--;
495 					if (res_limited_refcnt == 0)
496 						mon_stop(MON_RES);
497 				}
498 				memset((char *)rl, 0,
499 				    sizeof(struct restrictlist));
500 
501 				rl->next = resfree;
502 				resfree = rl;
503 				numresfree++;
504 			}
505 			break;
506 
507 		default:
508 			break;
509 		}
510 	} else if (resaddr->ss_family == AF_INET6) {
511 		switch (op) {
512 		case RESTRICT_FLAGS:
513 			/*
514 			 * Here we add bits to the flags. If this is a
515 			 * new restriction add it.
516 			 */
517 			if (rl6 == NULL) {
518 				if (resfree6 == NULL) {
519 					rl6 = (struct
520 					    restrictlist6 *)emalloc(
521 					    INCRESLIST * sizeof(struct
522 					    restrictlist6));
523 					memset((char *)rl6, 0,
524 					    INCRESLIST * sizeof(struct
525 					    restrictlist6));
526 
527 					for (i = 0; i < INCRESLIST;
528 					    i++) {
529 						rl6->next = resfree6;
530 						resfree6 = rl6;
531 						rl6++;
532 					}
533 					numresfree6 = INCRESLIST;
534 				}
535 				rl6 = resfree6;
536 				resfree6 = rl6->next;
537 				numresfree6--;
538 				rl6->addr6 = addr6;
539 				rl6->mask6 = mask6;
540 				rl6->mflags = (u_short)mflags;
541 				if (rlprev6 != NULL) {
542 					rl6->next = rlprev6->next;
543 					rlprev6->next = rl6;
544 				} else {
545 					rl6->next = restrictlist6;
546 					restrictlist6 = rl6;
547 				}
548 				restrictcount6++;
549 			}
550 			if ((rl6->flags ^ (u_short)flags) &
551 			    RES_LIMITED) {
552 				res_limited_refcnt6++;
553 				mon_start(MON_RES);
554 			}
555 			rl6->flags |= (u_short)flags;
556 			break;
557 
558 		case RESTRICT_UNFLAG:
559 			/*
560 			 * Remove some bits from the flags. If we didn't
561 			 * find this one, just return.
562 			 */
563 			if (rl6 != NULL) {
564 				if ((rl6->flags ^ (u_short)flags) &
565 				    RES_LIMITED) {
566 					res_limited_refcnt6--;
567 					if (res_limited_refcnt6 == 0)
568 						mon_stop(MON_RES);
569 				}
570 				rl6->flags &= (u_short)~flags;
571 			}
572 			break;
573 
574 		case RESTRICT_REMOVE:
575 		case RESTRICT_REMOVEIF:
576 			/*
577 			 * Remove an entry from the table entirely if we
578 			 * found one. Don't remove the default entry and
579 			 * don't remove an interface entry.
580 			 */
581 			if (rl6 != NULL &&
582 			    !IN6_IS_ADDR_UNSPECIFIED(&rl6->addr6)
583 			    && !(rl6->mflags & RESM_INTERFACE && op != RESTRICT_REMOVEIF)) {
584 				if (rlprev6 != NULL) {
585 					rlprev6->next = rl6->next;
586 				} else {
587 					restrictlist6 = rl6->next;
588 				}
589 				restrictcount6--;
590 				if (rl6->flags & RES_LIMITED) {
591 					res_limited_refcnt6--;
592 					if (res_limited_refcnt6 == 0)
593 						mon_stop(MON_RES);
594 				}
595 				memset((char *)rl6, 0,
596 				    sizeof(struct restrictlist6));
597 				rl6->next = resfree6;
598 				resfree6 = rl6;
599 				numresfree6++;
600 			}
601 			break;
602 
603 		default:
604 			break;
605 		}
606 	}
607 }
608