2 * ntp_restrict.c - find out what restrictions this host is running under
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
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 match's
27 * flags instead. When you hit the point where the sorted address is
28 * greater than the target, you return with the last set of flags you
29 * found. Because of the ordering of the list, the most specific match
30 * 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
34 * from your own interfaces. It was also thought it would sometimes
35 * be useful to keep a misbehaving host or two from abusing your primary
36 * clock. It has been expanded, however, to suit the needs of those
37 * with more restrictive access policies.
41 * Memory allocation parameters. We allocate INITRESLIST entries
42 * initially, and add INCRESLIST entries to the free list whenever
45 #define INITRESLIST 10
49 * The restriction list
51 struct restrictlist *restrictlist;
52 static int restrictcount; /* count of entries in the restriction list */
55 * The free list and associated counters. Also some uninteresting
58 static struct restrictlist *resfree;
59 static int numresfree; /* number of structures on free list */
61 static u_long res_calls;
62 static u_long res_found;
63 static u_long res_not_found;
64 /* static u_long res_timereset; */
67 * Parameters of the RES_LIMITED restriction option.
68 * client_limit is the number of hosts allowed per source net
69 * client_limit_period is the number of seconds after which an entry
70 * is no longer considered for client limit determination
73 u_long client_limit_period;
75 * count number of restriction entries referring to RES_LIMITED
76 * controls activation/deactivation of monitoring
77 * (with respect to RES_LIMITED control)
79 static u_long res_limited_refcnt;
82 * Our initial allocation of list entries.
84 static struct restrictlist resinit[INITRESLIST];
87 * init_restrict - initialize the restriction data structures
96 * Zero the list and put all but one on the free list
99 memset((char *)resinit, 0, sizeof resinit);
101 for (i = 1; i < INITRESLIST; i++) {
102 resinit[i].next = resfree;
103 resfree = &resinit[i];
106 numresfree = INITRESLIST-1;
109 * Put the remaining item at the head of the
110 * list as our default entry. Everything in here
111 * should be zero for now.
113 resinit[0].addr = htonl(INADDR_ANY);
115 restrictlist = &resinit[0];
120 * fix up stat counters
125 /* res_timereset = 0; */
128 * set default values for RES_LIMIT functionality
131 client_limit_period = 3600;
132 res_limited_refcnt = 0;
134 sprintf(bp, "client_limit=%ld", client_limit);
135 set_sys_var(bp, strlen(bp)+1, RO);
136 sprintf(bp, "client_limit_period=%ld", client_limit_period);
137 set_sys_var(bp, strlen(bp)+1, RO);
142 * restrictions - return restrictions for this host
146 struct sockaddr_in *srcadr
149 register struct restrictlist *rl;
150 register struct restrictlist *match;
151 register u_int32 hostaddr;
152 register int isntpport;
156 * We need the host address in host order. Also need to know
157 * whether this is from the ntp port or not.
159 hostaddr = SRCADR(srcadr);
160 isntpport = (SRCPORT(srcadr) == NTP_PORT);
163 * Ignore any packets with a multicast source address
164 * (this should be done early in the receive process, later!)
166 if (IN_CLASSD(ntohl(srcadr->sin_addr.s_addr)))
167 return (int)RES_IGNORE;
170 * Set match to first entry, which is default entry. Work our
171 * way down from there.
173 match = restrictlist;
175 for (rl = match->next; rl != 0 && rl->addr <= hostaddr; rl = rl->next)
176 if ((hostaddr & rl->mask) == rl->addr) {
177 if ((rl->mflags & RESM_NTPONLY) && !isntpport)
183 if (match == restrictlist)
189 * The following implements limiting the number of clients
190 * accepted from a given network. The notion of "same network"
191 * is determined by the mask and addr fields of the restrict
192 * list entry. The monitor mechanism has to be enabled for
193 * collecting info on current clients.
195 * The policy is as follows:
196 * - take the list of clients recorded
197 * from the given "network" seen within the last
198 * client_limit_period seconds
199 * - if there are at most client_limit entries:
201 * - otherwise sort by time first seen
202 * - current client among the first client_limit seen
204 * if yes: access allowed
205 * else: eccess denied
207 if (match->flags & RES_LIMITED) {
209 struct mon_data *md, *this_client;
213 printf("limited clients check: %ld clients, period %ld seconds, net is 0x%lX\n",
214 client_limit, client_limit_period,
215 (u_long)netof(hostaddr));
217 if (mon_enabled == MON_OFF) {
220 printf("no limit - monitoring is off\n");
222 return (int)(match->flags & ~RES_LIMITED);
226 * How nice, MRU list provides our current client as the
227 * first entry in the list.
228 * Monitoring was verified to be active above, thus we
229 * know an entry for our client must exist, or some
230 * brain dead set the memory limit for mon entries to ZERO!!!
232 this_client = mon_mru_list.mru_next;
234 for (md = mon_fifo_list.fifo_next,lcnt = 0;
235 md != &mon_fifo_list;
236 md = md->fifo_next) {
237 if ((current_time - md->lasttime)
238 > client_limit_period) {
241 printf("checking: %s: ignore: too old: %ld\n",
243 current_time - md->lasttime);
247 if (md->mode == MODE_BROADCAST ||
248 md->mode == MODE_CONTROL ||
249 md->mode == MODE_PRIVATE) {
252 printf("checking: %s: ignore mode %d\n",
258 if (netof(md->rmtadr) !=
262 printf("checking: %s: different net 0x%lX\n",
264 (u_long)netof(md->rmtadr));
269 if (lcnt > (int) client_limit ||
270 md->rmtadr == hostaddr) {
273 printf("considering %s: found host\n",
281 printf("considering %s: same net\n",
289 printf("this one is rank %d in list, limit is %lu: %s\n",
291 (lcnt <= (int) client_limit) ? "ALLOW" : "REJECT");
293 if (lcnt <= (int) client_limit) {
294 this_client->lastdrop = 0;
295 return (int)(match->flags & ~RES_LIMITED);
297 this_client->lastdrop = current_time;
300 return (int)match->flags;
305 * hack_restrict - add/subtract/manipulate entries on the restrict list
310 struct sockaddr_in *resaddr,
311 struct sockaddr_in *resmask,
316 register u_int32 addr;
317 register u_int32 mask;
318 register struct restrictlist *rl;
319 register struct restrictlist *rlprev;
323 * Get address and mask in host byte order
325 addr = SRCADR(resaddr);
326 mask = SRCADR(resmask);
327 addr &= mask; /* make sure low bits are zero */
330 * If this is the default address, point at first on list. Else
331 * go searching for it.
333 if (addr == htonl(INADDR_ANY)) {
337 rlprev = restrictlist;
340 if (rl->addr > addr) {
343 } else if (rl->addr == addr) {
344 if (rl->mask == mask) {
345 if ((mflags & RESM_NTPONLY)
346 == (rl->mflags & RESM_NTPONLY))
347 break; /* exact match */
348 if (!(mflags & RESM_NTPONLY)) {
350 * No flag fits before flag
356 } else if (rl->mask > mask) {
366 * In case the above wasn't clear :-), either rl now points
367 * at the entry this call refers to, or rl is zero and rlprev
368 * points to the entry prior to where this one should go in
373 * Switch based on operation
378 * Here we add bits to the flags. If this is a new
379 * restriction add it.
382 if (numresfree == 0) {
383 rl = (struct restrictlist *) emalloc(
384 INCRESLIST*sizeof(struct restrictlist));
385 memset((char *)rl, 0,
386 INCRESLIST*sizeof(struct restrictlist));
388 for (i = 0; i < INCRESLIST; i++) {
393 numresfree = INCRESLIST;
402 rl->mflags = (u_short)mflags;
404 rl->next = rlprev->next;
408 if ((rl->flags ^ (u_short)flags) & RES_LIMITED) {
409 res_limited_refcnt++;
410 mon_start(MON_RES); /* ensure data gets collected */
412 rl->flags |= (u_short)flags;
415 case RESTRICT_UNFLAG:
417 * Remove some bits from the flags. If we didn't
418 * find this one, just return.
421 if ((rl->flags ^ (u_short)flags) & RES_LIMITED) {
422 res_limited_refcnt--;
423 if (res_limited_refcnt == 0)
426 rl->flags &= (u_short)~flags;
430 case RESTRICT_REMOVE:
432 * Remove an entry from the table entirely if we found one.
433 * Don't remove the default entry and don't remove an
437 && rl->addr != htonl(INADDR_ANY)
438 && !(rl->mflags & RESM_INTERFACE)) {
439 rlprev->next = rl->next;
441 if (rl->flags & RES_LIMITED) {
442 res_limited_refcnt--;
443 if (res_limited_refcnt == 0)
446 memset((char *)rl, 0, sizeof(struct restrictlist));