turns printfs back on
[freebsd-src/fkvm-freebsd.git] / contrib / ntp / ntpd / ntp_restrict.c
blob473e2ce81d4a58795aa2cee5e7bf0becfa4905f3
1 /*
2 * ntp_restrict.c - determine host restrictions
3 */
4 #ifdef HAVE_CONFIG_H
5 #include <config.h>
6 #endif
8 #include <stdio.h>
9 #include <sys/types.h>
11 #include "ntpd.h"
12 #include "ntp_if.h"
13 #include "ntp_stdlib.h"
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.
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.
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.
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
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)
54 * Memory allocation parameters. We allocate INITRESLIST entries
55 * initially, and add INCRESLIST entries to the free list whenever
56 * we run out.
58 #define INITRESLIST 10
59 #define INCRESLIST 5
61 #define RES_AVG 8. /* interpacket averaging factor */
64 * The restriction list
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*/
72 * The free list and associated counters. Also some uninteresting
73 * stat counters.
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 */
80 static u_long res_calls;
81 static u_long res_found;
82 static u_long res_not_found;
85 * Parameters of the RES_LIMITED restriction option.
87 u_long res_avg_interval = 5; /* min average interpacket interval */
88 u_long res_min_interval = 1; /* min interpacket interval */
91 * Count number of restriction entries referring to RES_LIMITED controls
92 * activation/deactivation of monitoring (with respect to RES_LIMITED
93 * control)
95 static u_long res_limited_refcnt;
96 static u_long res_limited_refcnt6;
99 * Our initial allocation of lists entries.
101 static struct restrictlist resinit[INITRESLIST];
102 static struct restrictlist6 resinit6[INITRESLIST];
105 * init_restrict - initialize the restriction data structures
107 void
108 init_restrict(void)
110 register int i;
113 * Zero the list and put all but one on the free list
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];
125 numresfree = INITRESLIST-1;
126 numresfree6 = INITRESLIST-1;
129 * Put the remaining item at the head of the list as our default
130 * entry. Everything in here should be zero for now.
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;
142 * fix up stat counters
144 res_calls = 0;
145 res_found = 0;
146 res_not_found = 0;
149 * set default values for RES_LIMIT functionality
151 res_limited_refcnt = 0;
152 res_limited_refcnt6 = 0;
157 * restrictions - return restrictions for this host
160 restrictions(
161 struct sockaddr_storage *srcadr,
162 int at_listhead
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;
175 res_calls++;
176 if (srcadr->ss_family == AF_INET) {
178 * We need the host address in host order. Also need to
179 * know whether this is from the ntp port or not.
181 hostaddr = SRCADR(srcadr);
182 isntpport = (SRCPORT(srcadr) == NTP_PORT);
185 * Ignore any packets with a multicast source address
186 * (this should be done early in the receive process,
187 * later!)
189 if (IN_CLASSD(SRCADR(srcadr)))
190 return (int)RES_IGNORE;
193 * Set match to first entry, which is default entry.
194 * Work our way down from there.
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;
205 match->count++;
206 if (match == restrictlist)
207 res_not_found++;
208 else
209 res_found++;
210 flags = match->flags;
213 /* IPv6 source address */
214 if (srcadr->ss_family == AF_INET6) {
216 * Need to know whether this is from the ntp port or
217 * not.
219 hostaddr6 = GET_INADDR6(*srcadr);
220 isntpport = (ntohs((
221 (struct sockaddr_in6 *)srcadr)->sin6_port) ==
222 NTP_PORT);
225 * Ignore any packets with a multicast source address
226 * (this should be done early in the receive process,
227 * later!)
229 if (IN6_IS_ADDR_MULTICAST(&hostaddr6))
230 return (int)RES_IGNORE;
233 * Set match to first entry, which is default entry.
234 * Work our way down from there.
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;
250 match6->count++;
251 if (match6 == restrictlist6)
252 res_not_found++;
253 else
254 res_found++;
255 flags = match6->flags;
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.
264 if (!at_listhead || mon_enabled == MON_OFF) {
265 flags &= ~RES_LIMITED;
266 } else {
267 struct mon_data *md;
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.
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;
286 return (flags);
291 * hack_restrict - add/subtract/manipulate entries on the restrict list
293 void
294 hack_restrict(
295 int op,
296 struct sockaddr_storage *resaddr,
297 struct sockaddr_storage *resmask,
298 int mflags,
299 int flags
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));
314 if (resaddr->ss_family == AF_INET) {
316 * Get address and mask in host byte order
318 addr = SRCADR(resaddr);
319 mask = SRCADR(resmask);
320 addr &= mask; /* make sure low bits zero */
323 * If this is the default address, point at first on
324 * list. Else go searching for it.
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;
344 if (!(mflags &
345 RESM_NTPONLY)) {
346 rl = NULL;
347 break;
349 } else if (rl->mask > mask) {
350 rl = NULL;
351 break;
354 rlprev = rl;
355 rl = rl->next;
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;
386 if (!(mflags &
387 RESM_NTPONLY)) {
388 rl6 = NULL;
389 break;
391 } else if (mask_cmp > 0) {
392 rl6 = NULL;
393 break;
396 rlprev6 = rl6;
397 rl6 = rl6->next;
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.
410 * Switch based on operation
412 if (resaddr->ss_family == AF_INET) {
413 switch (op) {
414 case RESTRICT_FLAGS:
416 * Here we add bits to the flags. If this is a
417 * new restriction add it.
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++;
433 numresfree = INCRESLIST;
436 rl = resfree;
437 resfree = rl->next;
438 numresfree--;
440 rl->addr = addr;
441 rl->mask = mask;
442 rl->mflags = (u_short)mflags;
444 if (rlprev == NULL) {
445 rl->next = restrictlist;
446 restrictlist = rl;
447 } else {
448 rl->next = rlprev->next;
449 rlprev->next = rl;
451 restrictcount++;
453 if ((rl->flags ^ (u_short)flags) &
454 RES_LIMITED) {
455 res_limited_refcnt++;
456 mon_start(MON_RES);
458 rl->flags |= (u_short)flags;
459 break;
461 case RESTRICT_UNFLAG:
463 * Remove some bits from the flags. If we didn't
464 * find this one, just return.
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);
473 rl->flags &= (u_short)~flags;
475 break;
477 case RESTRICT_REMOVE:
478 case RESTRICT_REMOVEIF:
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.
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;
492 restrictcount--;
493 if (rl->flags & RES_LIMITED) {
494 res_limited_refcnt--;
495 if (res_limited_refcnt == 0)
496 mon_stop(MON_RES);
498 memset((char *)rl, 0,
499 sizeof(struct restrictlist));
501 rl->next = resfree;
502 resfree = rl;
503 numresfree++;
505 break;
507 default:
508 break;
510 } else if (resaddr->ss_family == AF_INET6) {
511 switch (op) {
512 case RESTRICT_FLAGS:
514 * Here we add bits to the flags. If this is a
515 * new restriction add it.
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));
527 for (i = 0; i < INCRESLIST;
528 i++) {
529 rl6->next = resfree6;
530 resfree6 = rl6;
531 rl6++;
533 numresfree6 = INCRESLIST;
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;
548 restrictcount6++;
550 if ((rl6->flags ^ (u_short)flags) &
551 RES_LIMITED) {
552 res_limited_refcnt6++;
553 mon_start(MON_RES);
555 rl6->flags |= (u_short)flags;
556 break;
558 case RESTRICT_UNFLAG:
560 * Remove some bits from the flags. If we didn't
561 * find this one, just return.
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);
570 rl6->flags &= (u_short)~flags;
572 break;
574 case RESTRICT_REMOVE:
575 case RESTRICT_REMOVEIF:
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.
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;
589 restrictcount6--;
590 if (rl6->flags & RES_LIMITED) {
591 res_limited_refcnt6--;
592 if (res_limited_refcnt6 == 0)
593 mon_stop(MON_RES);
595 memset((char *)rl6, 0,
596 sizeof(struct restrictlist6));
597 rl6->next = resfree6;
598 resfree6 = rl6;
599 numresfree6++;
601 break;
603 default:
604 break;