ntp_restrict.c revision 7c478bd95313f5f23a4c958a745db2134aa03244
/*
* Copyright (c) 1996 by Sun Microsystems, Inc.
* All Rights Reserved.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
/*
* ntp_restrict.c - find out what restrictions this host is running under
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <stdio.h>
#include "ntpd.h"
#include "ntp_if.h"
#include "ntp_stdlib.h"
/*
* This code keeps a simple address-and-mask list of hosts we want
* to place restrictions on (or remove them from). The restrictions
* are implemented as a set of flags which tell you what the host
* can't do. There is a subroutine entry to return the flags. The
* list is kept sorted to reduce the average number of comparisons
* and make sure you get the set of restrictions most specific to
* the address.
*
* The algorithm is that, when looking up a host, it is first assumed
* that the default set of restrictions will apply. It then searches
* down through the list. Whenever it finds a match it adopts the match's
* flags instead. When you hit the point where the sorted address is
* greater than the target, you return with the last set of flags you
* found. Because of the ordering of the list, the most specific match
* will provide the final set of flags.
*
* This was originally intended to restrict you from sync'ing to your
* own broadcasts when you are doing that, by restricting yourself
* from your own interfaces. It was also thought it would sometimes
* be useful to keep a misbehaving host or two from abusing your primary
* clock. It has been expanded, however, to suit the needs of those
* with more restrictive access policies.
*/
/*
* Memory allocation parameters. We allocate INITRESLIST entries
* initially, and add INCRESLIST entries to the free list whenever
* we run out.
*/
#define INITRESLIST 10
#define INCRESLIST 5
/*
* The restriction list
*/
struct restrictlist *restrictlist;
static int restrictcount; /* count of entries in the restriction list */
/*
* The free list and associated counters. Also some uninteresting
* stat counters.
*/
static struct restrictlist *resfree;
static int numresfree; /* number of structures on free list */
/*
* Parameters of the RES_LIMITED restriction option.
* client_limit is the number of hosts allowed per source net
* client_limit_period is the number of seconds after which an entry
* is no longer considered for client limit determination
*/
/*
* count number of restriction entries referring to RES_LIMITED
* controls activation/deactivation of monitoring
* (with respect ro RES_LIMITED control)
*/
/*
* Our initial allocation of list entries.
*/
/*
* Imported from the timer module
*/
extern u_long current_time;
/*
* debug flag
*/
extern int debug;
/*
* init_restrict - initialize the restriction data structures
*/
void
{
register int i;
char bp[80];
/*
* Zero the list and put all but one on the free list
*/
resfree = 0;
for (i = 1; i < INITRESLIST; i++) {
}
/*
* Put the remaining item at the head of the
* list as our default entry. Everything in here
* should be zero for now.
*/
restrictlist = &resinit[0];
restrictcount = 1;
/*
* fix up stat counters
*/
res_calls = 0;
res_found = 0;
res_not_found = 0;
res_timereset = 0;
/*
* set default values for RES_LIMIT functionality
*/
client_limit = 3;
client_limit_period = 3600;
res_limited_refcnt = 0;
}
/*
* restrictions - return restrictions for this host
*/
int
struct sockaddr_in *srcadr;
{
register struct restrictlist *rl;
register struct restrictlist *match;
register int isntpport;
res_calls++;
/*
* We need the host address in host order. Also need to know
* whether this is from the ntp port or not.
*/
/*
* Set match to first entry, which is default entry. Work our
* way down from there.
*/
continue;
}
if (match == restrictlist)
else
res_found++;
/*
* The following implements limiting the number of clients
* accepted from a given network. The notion of "same network"
* is determined by the mask and addr fields of the restrict
* list entry. The monitor mechanism has to be enabled for
* collecting info on current clients.
*
* The policy is as follows:
* - take the list of clients recorded
* from the given "network" seen within the last
* client_limit_period seconds
* - if there are at most client_limit entries:
* --> access allowed
* - otherwise sort by time first seen
* - current client among the first client_limit seen
* hosts?
* if yes: access allowed
* else: eccess denied
*/
int lcnt;
extern int mon_enabled;
#ifdef DEBUG
if (debug > 2)
printf("limited clients check: %ld clients, period %ld seconds, net is 0x%lX\n",
#endif /*DEBUG*/
if (mon_enabled == MON_OFF) {
#ifdef DEBUG
if (debug > 4)
printf("no limit - monitoring is off\n");
#endif
}
/*
* How nice, MRU list provides our current client as the
* first entry in the list.
* Monitoring was verified to be active above, thus we
* know an entry for our client must exist, or some
* brain dead set the memory limit for mon entries to ZERO!!!
*/
md != &mon_fifo_list;
> client_limit_period) {
#ifdef DEBUG
if (debug > 5)
printf("checking: %s: ignore: too old: %ld\n",
#endif
continue;
}
#ifdef DEBUG
if (debug > 5)
printf("checking: %s: ignore mode %d\n",
#endif
continue;
}
#ifdef DEBUG
if (debug > 5)
printf("checking: %s: different net 0x%lX\n",
#endif
continue;
}
lcnt++;
if (lcnt > (int) client_limit ||
#ifdef DEBUG
if (debug > 5)
printf("considering %s: found host\n",
#endif
break;
}
#ifdef DEBUG
else {
if (debug > 5)
printf("considering %s: same net\n",
}
#endif
}
#ifdef DEBUG
if (debug > 4)
printf("this one is rank %d in list, limit is %lu: %s\n",
#endif
if (lcnt <= (int) client_limit) {
this_client->lastdrop = 0;
} else {
}
}
}
/*
* hack_restrict - add/subtract/manipulate entries on the restrict list
*/
void
int op;
struct sockaddr_in *resaddr;
struct sockaddr_in *resmask;
int mflags;
int flags;
{
register struct restrictlist *rl;
register struct restrictlist *rlprev;
int i;
/*
* Get address and mask in host byte order
*/
/*
* If this is the default address, point at first on list. Else
* go searching for it.
*/
rlprev = 0;
rl = restrictlist;
} else {
while (rl != 0) {
rl = 0;
break;
if ((mflags & RESM_NTPONLY)
break; /* exact match */
if (!(mflags & RESM_NTPONLY)) {
/*
* No flag fits before flag
*/
rl = 0;
break;
}
/* continue on */
rl = 0;
break;
}
}
}
}
/*
* In case the above wasn't clear :-), either rl now points
* at the entry this call refers to, or rl is zero and rlprev
* points to the entry prior to where this one should go in
* the sort.
*/
/*
* Switch based on operation
*/
switch (op) {
case RESTRICT_FLAGS:
/*
* Here we add bits to the flags. If this is a new
* restriction add it.
*/
if (rl == 0) {
if (numresfree == 0) {
INCRESLIST*sizeof(struct restrictlist));
INCRESLIST*sizeof(struct restrictlist));
for (i = 0; i < INCRESLIST; i++) {
rl++;
}
}
numresfree--;
}
}
break;
case RESTRICT_UNFLAG:
/*
* Remove some bits from the flags. If we didn't
* find this one, just return.
*/
if (rl != 0) {
if (res_limited_refcnt == 0)
}
}
break;
case RESTRICT_REMOVE:
/*
* Remove an entry from the table entirely if we found one.
* Don't remove the default entry and don't remove an
* interface entry.
*/
if (rl != 0
if (res_limited_refcnt == 0)
}
numresfree++;
}
break;
default:
/* Oh, well */
break;
}
/* done! */
}