Пример #1
0
/*
 * restrictions - return restrictions for this host
 */
u_short
restrictions(
	sockaddr_u *srcadr
	)
{
	restrict_u *match;
	struct in6_addr *pin6;
	u_short flags;

	res_calls++;
	flags = 0;
	/* IPv4 source address */
	if (IS_IPV4(srcadr)) {
		/*
		 * Ignore any packets with a multicast source address
		 * (this should be done early in the receive process,
		 * not later!)
		 */
		if (IN_CLASSD(SRCADR(srcadr)))
			return (int)RES_IGNORE;

		match = match_restrict4_addr(SRCADR(srcadr),
					     SRCPORT(srcadr));
		match->count++;
		/*
		 * res_not_found counts only use of the final default
		 * entry, not any "restrict default ntpport ...", which
		 * would be just before the final default.
		 */
		if (&restrict_def4 == match)
			res_not_found++;
		else
			res_found++;
		flags = match->flags;
	}

	/* IPv6 source address */
	if (IS_IPV6(srcadr)) {
		pin6 = PSOCK_ADDR6(srcadr);

		/*
		 * Ignore any packets with a multicast source address
		 * (this should be done early in the receive process,
		 * not later!)
		 */
		if (IN6_IS_ADDR_MULTICAST(pin6))
			return (int)RES_IGNORE;

		match = match_restrict6_addr(pin6, SRCPORT(srcadr));
		match->count++;
		if (&restrict_def6 == match)
			res_not_found++;
		else
			res_found++;
		flags = match->flags;
	}
	return (flags);
}
Пример #2
0
/*
 * restrict_source - maintains dynamic "restrict source ..." entries as
 *		     peers come and go.
 */
void
restrict_source(
	sockaddr_u *	addr,
	int		farewell,	/* 0 to add, 1 to remove */
	u_long		expire		/* 0 is infinite, valid until */
	)
{
	sockaddr_u	onesmask;
	restrict_u *	res;
	int		found_specific;

	if (!restrict_source_enabled || SOCK_UNSPEC(addr) ||
	    IS_MCAST(addr) || ISREFCLOCKADR(addr))
		return;

	REQUIRE(AF_INET == AF(addr) || AF_INET6 == AF(addr));

	SET_HOSTMASK(&onesmask, AF(addr));
	if (farewell) {
		hack_restrict(RESTRICT_REMOVE, addr, &onesmask,
			      0, 0, 0);
		DPRINTF(1, ("restrict_source: %s removed", stoa(addr)));
		return;
	}

	/*
	 * If there is a specific entry for this address, hands
	 * off, as it is condidered more specific than "restrict
	 * server ...".
	 * However, if the specific entry found is a fleeting one
	 * added by pool_xmit() before soliciting, replace it
	 * immediately regardless of the expire value to make way
	 * for the more persistent entry.
	 */
	if (IS_IPV4(addr)) {
		res = match_restrict4_addr(SRCADR(addr), SRCPORT(addr));
		INSIST(res != NULL);
		found_specific = (SRCADR(&onesmask) == res->u.v4.mask);
	} else {
		res = match_restrict6_addr(&SOCK_ADDR6(addr),
					   SRCPORT(addr));
		INSIST(res != NULL);
		found_specific = ADDR6_EQ(&res->u.v6.mask,
					  &SOCK_ADDR6(&onesmask));
	}
	if (!expire && found_specific && res->expire) {
		found_specific = 0;
		free_res(res, IS_IPV6(addr));
	}
	if (found_specific)
		return;

	hack_restrict(RESTRICT_FLAGS, addr, &onesmask,
		      restrict_source_mflags, restrict_source_flags,
		      expire);
	DPRINTF(1, ("restrict_source: %s host restriction added\n", 
		    stoa(addr)));
}
Пример #3
0
static char
decodeaddrtype(
	sockaddr_u *sock
	)
{
	char ch = '-';
	u_int32 dummy;

	switch(AF(sock)) {
	case AF_INET:
		dummy = SRCADR(sock);
		ch = (char)(((dummy&0xf0000000)==0xe0000000) ? 'm' :
			((dummy&0x000000ff)==0x000000ff) ? 'b' :
			((dummy&0xffffffff)==0x7f000001) ? 'l' :
			((dummy&0xffffffe0)==0x00000000) ? '-' :
			'u');
		break;
	case AF_INET6:
		if (IN6_IS_ADDR_MULTICAST(PSOCK_ADDR6(sock)))
			ch = 'm';
		else
			ch = 'u';
		break;
	default:
		ch = '-';
		break;
	}
	return ch;
}
Пример #4
0
const char *
refnumtoa(
	sockaddr_u *num
	)
{
	u_int32 netnum;
	char *buf;
	const char *rclock;

	if (!ISREFCLOCKADR(num))
		return socktoa(num);

	LIB_GETBUF(buf);
	netnum = SRCADR(num);
	rclock = clockname((int)((u_long)netnum >> 8) & 0xff);

	if (rclock != NULL)
		snprintf(buf, LIB_BUFLENGTH, "%s(%lu)",
			 rclock, (u_long)netnum & 0xff);
	else
		snprintf(buf, LIB_BUFLENGTH, "REFCLK(%lu,%lu)",
			 ((u_long)netnum >> 8) & 0xff,
			 (u_long)netnum & 0xff);

	return buf;
}
Пример #5
0
sockaddr_u *
netof(
	sockaddr_u *hostaddr
	)
{
	static sockaddr_u	netofbuf[8];
	static int		next_netofbuf;
	u_int32			netnum;
	sockaddr_u *		netaddr;

	netaddr = &netofbuf[next_netofbuf];
	next_netofbuf = (next_netofbuf + 1) % COUNTOF(netofbuf);

	memcpy(netaddr, hostaddr, sizeof(*netaddr));

	if (IS_IPV4(netaddr)) {
		netnum = SRCADR(netaddr);

		/*
		 * We live in a modern CIDR world where the basement nets, which
		 * used to be class A, are now probably associated with each
		 * host address. So, for class-A nets, all bits are significant.
		 */
		if (IN_CLASSC(netnum))
			netnum &= IN_CLASSC_NET;
		else if (IN_CLASSB(netnum))
			netnum &= IN_CLASSB_NET;

		SET_ADDR4(netaddr, netnum);

	} else if (IS_IPV6(netaddr))
		/* assume the typical /64 subnet size */
		zero_mem(&NSRCADR6(netaddr)[8], 8);
#ifdef DEBUG
	else {
		msyslog(LOG_ERR, "netof unknown AF %d", AF(netaddr));
		exit(1);
	}
#endif

	return netaddr;
}
Пример #6
0
/*
 * hack_restrict - add/subtract/manipulate entries on the restrict list
 */
void
hack_restrict(
	int op,
	struct sockaddr_storage *resaddr,
	struct sockaddr_storage *resmask,
	int mflags,
	int flags
	)
{
	register u_int32 addr = 0;
	register u_int32 mask = 0;
	struct in6_addr addr6;
	struct in6_addr mask6;
	register struct restrictlist *rl = NULL;
	register struct restrictlist *rlprev = NULL;
	register struct restrictlist6 *rl6 = NULL;
	register struct restrictlist6 *rlprev6 = NULL;
	int i, addr_cmp, mask_cmp;
	memset(&addr6, 0, sizeof(struct in6_addr)); 
	memset(&mask6, 0, sizeof(struct in6_addr)); 

	if (resaddr->ss_family == AF_INET) {
		/*
		 * Get address and mask in host byte order
		 */
		addr = SRCADR(resaddr);
		mask = SRCADR(resmask);
		addr &= mask;		/* make sure low bits zero */

		/*
		 * If this is the default address, point at first on
		 * list. Else go searching for it.
		 */
		if (addr == 0) {
			rlprev = NULL;
			rl = restrictlist;
		} else {
			rlprev = restrictlist;
			rl = rlprev->next;
			while (rl != NULL) {
				if (rl->addr > addr) {
					rl = NULL;
					break;
				} else if (rl->addr == addr) {
					if (rl->mask == mask) {
						if ((mflags &
						    RESM_NTPONLY) ==
						    (rl->mflags &
						    RESM_NTPONLY))
							break;

						if (!(mflags &
						    RESM_NTPONLY)) {
							rl = NULL;
							break;
						}
					} else if (rl->mask > mask) {
						rl = NULL;
						break;
					}
				}
				rlprev = rl;
				rl = rl->next;
			}
		}
	}

	if (resaddr->ss_family == AF_INET6) {
		mask6 = GET_INADDR6(*resmask);
		SET_IPV6_ADDR_MASK(&addr6,
		    &GET_INADDR6(*resaddr), &mask6);
		if (IN6_IS_ADDR_UNSPECIFIED(&addr6)) {
			rlprev6 = NULL;
			rl6 = restrictlist6;
		} else {
			rlprev6 = restrictlist6;
			rl6 = rlprev6->next;
			while (rl6 != NULL) {
				addr_cmp = memcmp(&rl6->addr6, &addr6,
				    sizeof(addr6));
				if (addr_cmp > 0) {
					rl6 = NULL;
					break;
				} else if (addr_cmp == 0) {
					mask_cmp = memcmp(&rl6->mask6,
					    &mask6, sizeof(mask6));
					if (mask_cmp == 0) {
						if ((mflags &
						    RESM_NTPONLY) ==
						    (rl6->mflags &
						    RESM_NTPONLY))
							break;

						if (!(mflags &
						    RESM_NTPONLY)) {
							rl6 = NULL;
							break;
						}
					} else if (mask_cmp > 0) {
						rl6 = NULL;
						break;
					}
				}
				rlprev6 = rl6;
				rl6 = rl6->next;
			}
		}
	}

	/*
	 * 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
	 */
	if (resaddr->ss_family == AF_INET) {
		switch (op) {
		case RESTRICT_FLAGS:
			/*
			 * Here we add bits to the flags. If this is a
			 * new restriction add it.
			 */
			if (rl == NULL) {
				if (resfree == NULL) {
					rl = (struct restrictlist *)
					    emalloc(INCRESLIST *
					    sizeof(struct
					    restrictlist));
					memset((char *)rl, 0,
					    INCRESLIST * sizeof(struct
					    restrictlist));
					for (i = 0; i < INCRESLIST; i++) {
						rl->next = resfree;
						resfree = rl;
						rl++;
					}
					numresfree = INCRESLIST;
				}

				rl = resfree;
				resfree = rl->next;
				numresfree--;

				rl->addr = addr;
				rl->mask = mask;
				rl->mflags = (u_short)mflags;

				if (rlprev == NULL) {
					rl->next = restrictlist;
					restrictlist = rl;
				} else {
					rl->next = rlprev->next;
					rlprev->next = rl;
				}
				restrictcount++;
			}
			if ((rl->flags ^ (u_short)flags) &
			    RES_LIMITED) {
				res_limited_refcnt++;
				mon_start(MON_RES);
			}
			rl->flags |= (u_short)flags;
			break;

		case RESTRICT_UNFLAG:
			/*
			 * Remove some bits from the flags. If we didn't
			 * find this one, just return.
			 */
			if (rl != NULL) {
				if ((rl->flags ^ (u_short)flags) &
				    RES_LIMITED) {
					res_limited_refcnt--;
					if (res_limited_refcnt == 0)
						mon_stop(MON_RES);
				}
				rl->flags &= (u_short)~flags;
			}
			break;
	
		case RESTRICT_REMOVE:
		case RESTRICT_REMOVEIF:
			/*
			 * 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 != NULL
			    && rl->addr != htonl(INADDR_ANY)
			    && !(rl->mflags & RESM_INTERFACE && op != RESTRICT_REMOVEIF)) {
				if (rlprev != NULL) {
					rlprev->next = rl->next;
				} else {
					restrictlist = rl->next;
				}
				restrictcount--;
				if (rl->flags & RES_LIMITED) {
					res_limited_refcnt--;
					if (res_limited_refcnt == 0)
						mon_stop(MON_RES);
				}
				memset((char *)rl, 0,
				    sizeof(struct restrictlist));

				rl->next = resfree;
				resfree = rl;
				numresfree++;
			}
			break;

		default:
			break;
		}
	} else if (resaddr->ss_family == AF_INET6) {
		switch (op) {
		case RESTRICT_FLAGS:
			/*
			 * Here we add bits to the flags. If this is a
			 * new restriction add it.
			 */
			if (rl6 == NULL) {
				if (resfree6 == NULL) {
					rl6 = (struct
					    restrictlist6 *)emalloc(
					    INCRESLIST * sizeof(struct
					    restrictlist6));
					memset((char *)rl6, 0,
					    INCRESLIST * sizeof(struct
					    restrictlist6));

					for (i = 0; i < INCRESLIST;
					    i++) {
						rl6->next = resfree6;
						resfree6 = rl6;
						rl6++;
					}
					numresfree6 = INCRESLIST;
				}
				rl6 = resfree6;
				resfree6 = rl6->next;
				numresfree6--;
				rl6->addr6 = addr6;
				rl6->mask6 = mask6;
				rl6->mflags = (u_short)mflags;
				if (rlprev6 != NULL) {
					rl6->next = rlprev6->next;
					rlprev6->next = rl6;
				} else {
					rl6->next = restrictlist6;
					restrictlist6 = rl6;
				}
				restrictcount6++;
			}
			if ((rl6->flags ^ (u_short)flags) &
			    RES_LIMITED) {
				res_limited_refcnt6++;
				mon_start(MON_RES);
			}
			rl6->flags |= (u_short)flags;
			break;

		case RESTRICT_UNFLAG:
			/*
			 * Remove some bits from the flags. If we didn't
			 * find this one, just return.
			 */
			if (rl6 != NULL) {
				if ((rl6->flags ^ (u_short)flags) &
				    RES_LIMITED) {
					res_limited_refcnt6--;
					if (res_limited_refcnt6 == 0)
						mon_stop(MON_RES);
				}
				rl6->flags &= (u_short)~flags;
			}
			break;

		case RESTRICT_REMOVE:
		case RESTRICT_REMOVEIF:
			/*
			 * 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 (rl6 != NULL &&
			    !IN6_IS_ADDR_UNSPECIFIED(&rl6->addr6)
			    && !(rl6->mflags & RESM_INTERFACE && op != RESTRICT_REMOVEIF)) {
				if (rlprev6 != NULL) {
					rlprev6->next = rl6->next;
				} else {
					restrictlist6 = rl6->next;
				}
				restrictcount6--;
				if (rl6->flags & RES_LIMITED) {
					res_limited_refcnt6--;
					if (res_limited_refcnt6 == 0)
						mon_stop(MON_RES);
				}
				memset((char *)rl6, 0,
				    sizeof(struct restrictlist6));
				rl6->next = resfree6;
				resfree6 = rl6;
				numresfree6++;
			}
			break;

		default:
			break;
		}
	}
}
Пример #7
0
/*
 * restrictions - return restrictions for this host
 */
int
restrictions(
	struct sockaddr_storage *srcadr,
	int at_listhead
	)
{
	struct restrictlist *rl;
	struct restrictlist *match = NULL;
	struct restrictlist6 *rl6;
	struct restrictlist6 *match6 = NULL;
	struct in6_addr hostaddr6;
	struct in6_addr hostservaddr6;
	u_int32	hostaddr;
	int	flags = 0;
	int	isntpport;

	res_calls++;
	if (srcadr->ss_family == AF_INET) {
		/*
		 * We need the host address in host order.  Also need to
		 * know whether this is from the ntp port or not.
		 */
		hostaddr = SRCADR(srcadr);
		isntpport = (SRCPORT(srcadr) == NTP_PORT);

		/*
		 * Ignore any packets with a multicast source address
		 * (this should be done early in the receive process,
		 * later!)
		 */
		if (IN_CLASSD(SRCADR(srcadr)))
			return (int)RES_IGNORE;

		/*
		 * Set match to first entry, which is default entry.
		 * Work our way down from there.
		 */
		match = restrictlist;
		for (rl = match->next; rl != NULL && rl->addr <= hostaddr;
		    rl = rl->next)
			if ((hostaddr & rl->mask) == rl->addr) {
				if ((rl->mflags & RESM_NTPONLY) &&
				    !isntpport)
					continue;
				match = rl;
			}
		match->count++;
		if (match == restrictlist)
			res_not_found++;
		else
			res_found++;
		flags = match->flags;
	}

	/* IPv6 source address */
	if (srcadr->ss_family == AF_INET6) {
		/*
		 * Need to know whether this is from the ntp port or
		 * not.
		 */
		hostaddr6 = GET_INADDR6(*srcadr);
		isntpport = (ntohs((
		    (struct sockaddr_in6 *)srcadr)->sin6_port) ==
		    NTP_PORT);

		/*
		 * Ignore any packets with a multicast source address
		 * (this should be done early in the receive process,
		 * later!)
		 */
		if (IN6_IS_ADDR_MULTICAST(&hostaddr6))
			return (int)RES_IGNORE;

		/*
		 * Set match to first entry, which is default entry.
		 *  Work our way down from there.
		 */
		match6 = restrictlist6;
		for (rl6 = match6->next; rl6 != NULL &&
		    (memcmp(&(rl6->addr6), &hostaddr6,
		    sizeof(hostaddr6)) <= 0); rl6 = rl6->next) {
			SET_IPV6_ADDR_MASK(&hostservaddr6, &hostaddr6,
			    &rl6->mask6);
			if (memcmp(&hostservaddr6, &(rl6->addr6),
			    sizeof(hostservaddr6)) == 0) {
				if ((rl6->mflags & RESM_NTPONLY) &&
				    !isntpport)
					continue;
				match6 = rl6;
			}
		}
		match6->count++;
		if (match6 == restrictlist6)
			res_not_found++;
		else
			res_found++;
		flags = match6->flags;
	}

	/*
	 * The following implements a generalized call gap facility.
	 * Douse the RES_LIMITED bit only if the interval since the last
	 * packet is greater than res_min_interval and the average is
	 * greater thatn res_avg_interval.
	 */
	if (!at_listhead || mon_enabled == MON_OFF) {
		flags &= ~RES_LIMITED;
	} else {
		struct mon_data *md;

		/*
		 * At this poin the most recent arrival is first in the
		 * MRU list. Let the first 10 packets in for free until
		 * the average stabilizes.
		 */
		md = mon_mru_list.mru_next;
		if (md->avg_interval == 0)
			md->avg_interval = md->drop_count;
		else
			md->avg_interval += (md->drop_count -
			    md->avg_interval) / RES_AVG;
		if (md->count < 10 || (md->drop_count >
		    res_min_interval && md->avg_interval >
		    res_avg_interval))
			flags &= ~RES_LIMITED;
		md->drop_count = flags;
	}
	return (flags);
}
Пример #8
0
/*
 * hack_restrict - add/subtract/manipulate entries on the restrict list
 */
void
hack_restrict(
	int		op,
	sockaddr_u *	resaddr,
	sockaddr_u *	resmask,
	u_short		mflags,
	u_short		flags,
	u_long		expire
	)
{
	int		v6;
	restrict_u	match;
	restrict_u *	res;
	restrict_u **	plisthead;

	DPRINTF(1, ("restrict: op %d addr %s mask %s mflags %08x flags %08x\n",
		    op, stoa(resaddr), stoa(resmask), mflags, flags));

	if (NULL == resaddr) {
		REQUIRE(NULL == resmask);
		REQUIRE(RESTRICT_FLAGS == op);
		restrict_source_flags = flags;
		restrict_source_mflags = mflags;
		restrict_source_enabled = 1;
		return;
	}

	ZERO(match);

#if 0
	/* silence VC9 potentially uninit warnings */
	// HMS: let's use a compiler-specific "enable" for this.
	res = NULL;
	v6 = 0;
#endif

	if (IS_IPV4(resaddr)) {
		v6 = 0;
		/*
		 * Get address and mask in host byte order for easy
		 * comparison as u_int32
		 */
		match.u.v4.addr = SRCADR(resaddr);
		match.u.v4.mask = SRCADR(resmask);
		match.u.v4.addr &= match.u.v4.mask;

	} else if (IS_IPV6(resaddr)) {
		v6 = 1;
		/*
		 * Get address and mask in network byte order for easy
		 * comparison as byte sequences (e.g. memcmp())
		 */
		match.u.v6.mask = SOCK_ADDR6(resmask);
		MASK_IPV6_ADDR(&match.u.v6.addr, PSOCK_ADDR6(resaddr),
			       &match.u.v6.mask);

	} else	/* not IPv4 nor IPv6 */
		REQUIRE(0);

	match.flags = flags;
	match.mflags = mflags;
	match.expire = expire;
	res = match_restrict_entry(&match, v6);

	switch (op) {

	case RESTRICT_FLAGS:
		/*
		 * Here we add bits to the flags. If this is a
		 * new restriction add it.
		 */
		if (NULL == res) {
			if (v6) {
				res = alloc_res6();
				memcpy(res, &match,
				       V6_SIZEOF_RESTRICT_U);
				plisthead = &restrictlist6;
			} else {
				res = alloc_res4();
				memcpy(res, &match,
				       V4_SIZEOF_RESTRICT_U);
				plisthead = &restrictlist4;
			}
			LINK_SORT_SLIST(
				*plisthead, res,
				(v6)
				  ? res_sorts_before6(res, L_S_S_CUR())
				  : res_sorts_before4(res, L_S_S_CUR()),
				link, restrict_u);
			restrictcount++;
			if (RES_LIMITED & flags)
				inc_res_limited();
		} else {
			if ((RES_LIMITED & flags) &&
			    !(RES_LIMITED & res->flags))
				inc_res_limited();
			res->flags |= flags;
		}
		break;

	case RESTRICT_UNFLAG:
		/*
		 * Remove some bits from the flags. If we didn't
		 * find this one, just return.
		 */
		if (res != NULL) {
			if ((RES_LIMITED & res->flags)
			    && (RES_LIMITED & flags))
				dec_res_limited();
			res->flags &= ~flags;
		}
		break;

	case RESTRICT_REMOVE:
	case RESTRICT_REMOVEIF:
		/*
		 * 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 (res != NULL
		    && (RESTRICT_REMOVEIF == op
			|| !(RESM_INTERFACE & res->mflags))
		    && res != &restrict_def4
		    && res != &restrict_def6)
			free_res(res, v6);
		break;

	default:	/* unknown op */
		INSIST(0);
		break;
	}

}
Пример #9
0
/*
 * hack_restrict - add/subtract/manipulate entries on the restrict list
 */
void
hack_restrict(
	int op,
	struct sockaddr_in *resaddr,
	struct sockaddr_in *resmask,
	int mflags,
	int flags
	)
{
	register u_int32 addr;
	register u_int32 mask;
	register struct restrictlist *rl;
	register struct restrictlist *rlprev;
	int i;

	/*
	 * Get address and mask in host byte order
	 */
	addr = SRCADR(resaddr);
	mask = SRCADR(resmask);
	addr &= mask;		/* make sure low bits are zero */

	/*
	 * If this is the default address, point at first on list.  Else
	 * go searching for it.
	 */
	if (addr == htonl(INADDR_ANY)) {
		rlprev = 0;
		rl = restrictlist;
	} else {
		rlprev = restrictlist;
		rl = rlprev->next;
		while (rl != 0) {
			if (rl->addr > addr) {
				rl = 0;
				break;
			} else if (rl->addr == addr) {
				if (rl->mask == mask) {
					if ((mflags & RESM_NTPONLY)
					    == (rl->mflags & RESM_NTPONLY))
					    break;	/* exact match */
					if (!(mflags & RESM_NTPONLY)) {
						/*
						 * No flag fits before flag
						 */
						rl = 0;
						break;
					}
					/* continue on */
				} else if (rl->mask > mask) {
					rl = 0;
					break;
				}
			}
			rlprev = rl;
			rl = rl->next;
		}
	}
	/*
	 * 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) {
				rl = (struct restrictlist *) emalloc(
					INCRESLIST*sizeof(struct restrictlist));
				memset((char *)rl, 0,
				       INCRESLIST*sizeof(struct restrictlist));

				for (i = 0; i < INCRESLIST; i++) {
					rl->next = resfree;
					resfree = rl;
					rl++;
				}
				numresfree = INCRESLIST;
			}

			rl = resfree;
			resfree = rl->next;
			numresfree--;

			rl->addr = addr;
			rl->mask = mask;
			rl->mflags = (u_short)mflags;

			rl->next = rlprev->next;
			rlprev->next = rl;
			restrictcount++;
		}
		if ((rl->flags ^ (u_short)flags) & RES_LIMITED) {
			res_limited_refcnt++;
			mon_start(MON_RES); /* ensure data gets collected */
		}
		rl->flags |= (u_short)flags;
		break;
	
	    case RESTRICT_UNFLAG:
		/*
		 * Remove some bits from the flags.  If we didn't
		 * find this one, just return.
		 */
		if (rl != 0) {
			if ((rl->flags ^ (u_short)flags) & RES_LIMITED) {
				res_limited_refcnt--;
				if (res_limited_refcnt == 0)
				    mon_stop(MON_RES);
			}
			rl->flags &= (u_short)~flags;
		}
		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
		    && rl->addr != htonl(INADDR_ANY)
		    && !(rl->mflags & RESM_INTERFACE)) {
			rlprev->next = rl->next;
			restrictcount--;
			if (rl->flags & RES_LIMITED) {
				res_limited_refcnt--;
				if (res_limited_refcnt == 0)
				    mon_stop(MON_RES);
			}
			memset((char *)rl, 0, sizeof(struct restrictlist));

			rl->next = resfree;
			resfree = rl;
			numresfree++;
		}
		break;

	    default:
		/* Oh, well */
		break;
	}

	/* done! */
}
Пример #10
0
/*
 * restrictions - return restrictions for this host
 */
int
restrictions(
	struct sockaddr_in *srcadr
	)
{
	register struct restrictlist *rl;
	register struct restrictlist *match;
	register u_int32 hostaddr;
	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.
	 */
	hostaddr = SRCADR(srcadr);
	isntpport = (SRCPORT(srcadr) == NTP_PORT);

	/*
	 * Ignore any packets with a multicast source address
	 * (this should be done early in the receive process, later!)
	 */
	if (IN_CLASSD(ntohl(srcadr->sin_addr.s_addr)))
	    return (int)RES_IGNORE;

	/*
	 * Set match to first entry, which is default entry.  Work our
	 * way down from there.
	 */
	match = restrictlist;

	for (rl = match->next; rl != 0 && rl->addr <= hostaddr; rl = rl->next)
	    if ((hostaddr & rl->mask) == rl->addr) {
		    if ((rl->mflags & RESM_NTPONLY) && !isntpport)
			continue;
		    match = rl;
	    }

	match->count++;
	if (match == restrictlist)
	    res_not_found++;
	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
	 */
	if (match->flags & RES_LIMITED) {
		int lcnt;
		struct mon_data *md, *this_client;

#ifdef DEBUG
		if (debug > 2)
		    printf("limited clients check: %ld clients, period %ld seconds, net is 0x%lX\n",
			   client_limit, client_limit_period,
			   (u_long)netof(hostaddr));
#endif /*DEBUG*/
		if (mon_enabled == MON_OFF) {
#ifdef DEBUG
			if (debug > 4)
			    printf("no limit - monitoring is off\n");
#endif
			return (int)(match->flags & ~RES_LIMITED);
		}

		/*
		 * 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!!!
		 */
		this_client = mon_mru_list.mru_next;

		for (md = mon_fifo_list.fifo_next,lcnt = 0;
		     md != &mon_fifo_list;
		     md = md->fifo_next) {
			if ((current_time - md->lasttime)
			    > client_limit_period) {
#ifdef DEBUG
				if (debug > 5)
				    printf("checking: %s: ignore: too old: %ld\n",
					   numtoa(md->rmtadr),
					   current_time - md->lasttime);
#endif
				continue;
			}
			if (md->mode == MODE_BROADCAST ||
			    md->mode == MODE_CONTROL ||
			    md->mode == MODE_PRIVATE) {
#ifdef DEBUG
				if (debug > 5)
				    printf("checking: %s: ignore mode %d\n",
					   numtoa(md->rmtadr),
					   md->mode);
#endif
				continue;
			}
			if (netof(md->rmtadr) !=
			    netof(hostaddr)) {
#ifdef DEBUG
				if (debug > 5)
				    printf("checking: %s: different net 0x%lX\n",
					   numtoa(md->rmtadr),
					   (u_long)netof(md->rmtadr));
#endif
				continue;
			}
			lcnt++;
			if (lcnt >  (int) client_limit ||
			    md->rmtadr == hostaddr) {
#ifdef DEBUG
				if (debug > 5)
				    printf("considering %s: found host\n",
					   numtoa(md->rmtadr));
#endif
				break;
			}
#ifdef DEBUG
			else {
				if (debug > 5)
				    printf("considering %s: same net\n",
					   numtoa(md->rmtadr));
			}
#endif

		}
#ifdef DEBUG
		if (debug > 4)
		    printf("this one is rank %d in list, limit is %lu: %s\n",
			   lcnt, client_limit,
			   (lcnt <= (int) client_limit) ? "ALLOW" : "REJECT");
#endif
		if (lcnt <= (int) client_limit) {
			this_client->lastdrop = 0;
			return (int)(match->flags & ~RES_LIMITED);
		} else {
			this_client->lastdrop = current_time;
		}
	}
	return (int)match->flags;
}
Пример #11
0
/*
 * restrictions - return restrictions for this host in *r4a
 */
void
restrictions(
	sockaddr_u *srcadr,
	r4addr *r4a
	)
{
	restrict_u *match;
	struct in6_addr *pin6;

	REQUIRE(NULL != r4a);

	res_calls++;
	r4a->rflags = RES_IGNORE;
	r4a->ippeerlimit = 0;

	DPRINTF(1, ("restrictions: looking up %s\n", stoa(srcadr)));

	/* IPv4 source address */
	if (IS_IPV4(srcadr)) {
		/*
		 * Ignore any packets with a multicast source address
		 * (this should be done early in the receive process,
		 * not later!)
		 */
		if (IN_CLASSD(SRCADR(srcadr))) {
			DPRINTF(1, ("restrictions: srcadr %s is multicast\n", stoa(srcadr)));
			r4a->ippeerlimit = 2;	/* XXX: we should use a better value */
			return;
		}

		match = match_restrict4_addr(SRCADR(srcadr),
					     SRCPORT(srcadr));

		INSIST(match != NULL);

		match->count++;
		/*
		 * res_not_found counts only use of the final default
		 * entry, not any "restrict default ntpport ...", which
		 * would be just before the final default.
		 */
		if (&restrict_def4 == match)
			res_not_found++;
		else
			res_found++;
		r4a->rflags = match->rflags;
		r4a->ippeerlimit = match->ippeerlimit;
	}

	/* IPv6 source address */
	if (IS_IPV6(srcadr)) {
		pin6 = PSOCK_ADDR6(srcadr);

		/*
		 * Ignore any packets with a multicast source address
		 * (this should be done early in the receive process,
		 * not later!)
		 */
		if (IN6_IS_ADDR_MULTICAST(pin6))
			return;

		match = match_restrict6_addr(pin6, SRCPORT(srcadr));
		INSIST(match != NULL);
		match->count++;
		if (&restrict_def6 == match)
			res_not_found++;
		else
			res_found++;
		r4a->rflags = match->rflags;
		r4a->ippeerlimit = match->ippeerlimit;
	}
	return;
}