diff options
Diffstat (limited to 'ntpd/ntp_restrict.c')
| -rw-r--r-- | ntpd/ntp_restrict.c | 197 | 
1 files changed, 160 insertions, 37 deletions
| diff --git a/ntpd/ntp_restrict.c b/ntpd/ntp_restrict.c index ad6c82a32a41..f3c129342550 100644 --- a/ntpd/ntp_restrict.c +++ b/ntpd/ntp_restrict.c @@ -86,6 +86,8 @@ static	u_long res_limited_refcnt;  /*   * Our default entries. + * + * We can make this cleaner with c99 support: see init_restrict().   */  static	restrict_u	restrict_def4;  static	restrict_u	restrict_def6; @@ -94,8 +96,9 @@ static	restrict_u	restrict_def6;   * "restrict source ..." enabled knob and restriction bits.   */  static	int		restrict_source_enabled; -static	u_short		restrict_source_flags; +static	u_short		restrict_source_rflags;  static	u_short		restrict_source_mflags; +static	short		restrict_source_ippeerlimit;  /*   * private functions @@ -111,9 +114,82 @@ static restrict_u *	match_restrict6_addr(const struct in6_addr *,  static restrict_u *	match_restrict_entry(const restrict_u *, int);  static int		res_sorts_before4(restrict_u *, restrict_u *);  static int		res_sorts_before6(restrict_u *, restrict_u *); +static char *		roptoa(restrict_op op); + + +void	dump_restricts(void); + +/* + * dump_restrict - spit out a restrict_u + */ +static void +dump_restrict( +	restrict_u *	res, +	int		is_ipv6 +	) +{ +	char as[INET6_ADDRSTRLEN]; +	char ms[INET6_ADDRSTRLEN]; + +	if (is_ipv6) { +		inet_ntop(AF_INET6, &res->u.v6.addr, as, sizeof as); +		inet_ntop(AF_INET6, &res->u.v6.mask, ms, sizeof ms); +	} else { +		struct in_addr	sia = { htonl(res->u.v4.addr) }; +		struct in_addr	sim = { htonl(res->u.v4.mask) }; + +		inet_ntop(AF_INET, &sia, as, sizeof as); +		inet_ntop(AF_INET, &sim, ms, sizeof ms); +	} +	mprintf("restrict node at %p: %s/%s count %d, rflags %05x, mflags %05x, ippeerlimit %d, expire %lu, next %p\n", +		res, as, ms, res->count, res->rflags, res->mflags, +		res->ippeerlimit, res->expire, res->link); +	return; +}  /* + * dump_restricts - spit out the 'restrict' lines + */ +void +dump_restricts(void) +{ +	int		defaultv4_done = 0; +	int		defaultv6_done = 0; +	restrict_u *	res; +	restrict_u *	next; + +	mprintf("dump_restrict: restrict_def4: %p\n", &restrict_def4); +	/* Spit out 'restrict {,-4,-6} default ...' lines, if needed */ +	for (res = &restrict_def4; res != NULL; res = next) { +		dump_restrict(res, 0); +		next = res->link; +	} + +	mprintf("dump_restrict: restrict_def6: %p\n", &restrict_def6); +	for (res = &restrict_def6; res != NULL; res = next) { +		dump_restrict(res, 1); +		next = res->link; +	} + +	/* Spit out the IPv4 list */ +	mprintf("dump_restrict: restrictlist4: %p\n", &restrictlist4); +	for (res = restrictlist4; res != NULL; res = next) { +		dump_restrict(res, 0); +		next = res->link; +	} + +	/* Spit out the IPv6 list */ +	mprintf("dump_restrict: restrictlist6: %p\n", &restrictlist6); +	for (res = restrictlist6; res != NULL; res = next) { +		dump_restrict(res, 1); +		next = res->link; +	} + +	return; +} + +/*   * init_restrict - initialize the restriction data structures   */  void @@ -147,6 +223,10 @@ init_restrict(void)  	 * behavior as but reversed implementation compared to the docs.  	 *   	 */ + +	restrict_def4.ippeerlimit = -1;		/* Cleaner if we have C99 */ +	restrict_def6.ippeerlimit = -1;		/* Cleaner if we have C99 */ +  	LINK_SLIST(restrictlist4, &restrict_def4, link);  	LINK_SLIST(restrictlist6, &restrict_def6, link);  	restrictcount = 2; @@ -215,7 +295,7 @@ free_res(  	restrict_u *	unlinked;  	restrictcount--; -	if (RES_LIMITED & res->flags) +	if (RES_LIMITED & res->rflags)  		dec_res_limited();  	if (v6) @@ -265,14 +345,21 @@ match_restrict4_addr(  	restrict_u *	next;  	for (res = restrictlist4; res != NULL; res = next) { +		struct in_addr	sia = { htonl(res->u.v4.addr) }; +  		next = res->link; -		if (res->expire && -		    res->expire <= current_time) -			free_res(res, v6); -		if (res->u.v4.addr == (addr & res->u.v4.mask) -		    && (!(RESM_NTPONLY & res->mflags) -			|| NTP_PORT == port)) +		DPRINTF(2, ("match_restrict4_addr: Checking %s, port %d ... ", +			    inet_ntoa(sia), port)); +		if (   res->expire +		    && res->expire <= current_time) +			free_res(res, v6);	/* zeroes the contents */ +		if (   res->u.v4.addr == (addr & res->u.v4.mask) +		    && (   !(RESM_NTPONLY & res->mflags) +			|| NTP_PORT == port)) { +			DPRINTF(2, ("MATCH: ippeerlimit %d\n", res->ippeerlimit));  			break; +		} +		DPRINTF(2, ("doesn't match: ippeerlimit %d\n", res->ippeerlimit));  	}  	return res;  } @@ -410,19 +497,25 @@ res_sorts_before6(  /* - * restrictions - return restrictions for this host + * restrictions - return restrictions for this host in *r4a   */ -u_short +void  restrictions( -	sockaddr_u *srcadr +	sockaddr_u *srcadr, +	r4addr *r4a  	)  {  	restrict_u *match;  	struct in6_addr *pin6; -	u_short flags; + +	REQUIRE(NULL != r4a);  	res_calls++; -	flags = 0; +	r4a->rflags = RES_IGNORE; +	r4a->ippeerlimit = 0; + +	DPRINTF(1, ("restrictions: looking up %s\n", stoa(srcadr))); +  	/* IPv4 source address */  	if (IS_IPV4(srcadr)) {  		/* @@ -430,8 +523,11 @@ restrictions(  		 * (this should be done early in the receive process,  		 * not later!)  		 */ -		if (IN_CLASSD(SRCADR(srcadr))) -			return (int)RES_IGNORE; +		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)); @@ -448,7 +544,8 @@ restrictions(  			res_not_found++;  		else  			res_found++; -		flags = match->flags; +		r4a->rflags = match->rflags; +		r4a->ippeerlimit = match->ippeerlimit;  	}  	/* IPv6 source address */ @@ -461,7 +558,7 @@ restrictions(  		 * not later!)  		 */  		if (IN6_IS_ADDR_MULTICAST(pin6)) -			return (int)RES_IGNORE; +			return;  		match = match_restrict6_addr(pin6, SRCPORT(srcadr));  		INSIST(match != NULL); @@ -470,9 +567,29 @@ restrictions(  			res_not_found++;  		else  			res_found++; -		flags = match->flags; +		r4a->rflags = match->rflags; +		r4a->ippeerlimit = match->ippeerlimit; +	} +	return; +} + + +/* + * roptoa - convert a restrict_op to a string + */ +char * +roptoa(restrict_op op) { +	static char sb[30]; + +	switch(op) { +	    case RESTRICT_FLAGS:	return "RESTRICT_FLAGS"; +	    case RESTRICT_UNFLAG:	return "RESTRICT_UNFLAGS"; +	    case RESTRICT_REMOVE:	return "RESTRICT_REMOVE"; +	    case RESTRICT_REMOVEIF:	return "RESTRICT_REMOVEIF"; +	    default: +		snprintf(sb, sizeof sb, "**RESTRICT_#%d**", op); +		return sb;  	} -	return (flags);  } @@ -481,11 +598,12 @@ restrictions(   */  void  hack_restrict( -	int		op, +	restrict_op	op,  	sockaddr_u *	resaddr,  	sockaddr_u *	resmask, +	short		ippeerlimit,  	u_short		mflags, -	u_short		flags, +	u_short		rflags,  	u_long		expire  	)  { @@ -494,14 +612,15 @@ hack_restrict(  	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)); +	DPRINTF(1, ("hack_restrict: op %s addr %s mask %s ippeerlimit %d mflags %08x rflags %08x\n", +		    roptoa(op), stoa(resaddr), stoa(resmask), ippeerlimit, mflags, rflags));  	if (NULL == resaddr) {  		REQUIRE(NULL == resmask);  		REQUIRE(RESTRICT_FLAGS == op); -		restrict_source_flags = flags; +		restrict_source_rflags = rflags;  		restrict_source_mflags = mflags; +		restrict_source_ippeerlimit = ippeerlimit;  		restrict_source_enabled = 1;  		return;  	} @@ -538,8 +657,9 @@ hack_restrict(  	} else	/* not IPv4 nor IPv6 */  		REQUIRE(0); -	match.flags = flags; +	match.rflags = rflags;  	match.mflags = mflags; +	match.ippeerlimit = ippeerlimit;  	match.expire = expire;  	res = match_restrict_entry(&match, v6); @@ -547,7 +667,7 @@ hack_restrict(  	case RESTRICT_FLAGS:  		/* -		 * Here we add bits to the flags. If this is a +		 * Here we add bits to the rflags. If this is a  		 * new restriction add it.  		 */  		if (NULL == res) { @@ -569,26 +689,29 @@ hack_restrict(  				  : res_sorts_before4(res, L_S_S_CUR()),  				link, restrict_u);  			restrictcount++; -			if (RES_LIMITED & flags) +			if (RES_LIMITED & rflags)  				inc_res_limited();  		} else { -			if ((RES_LIMITED & flags) && -			    !(RES_LIMITED & res->flags)) +			if (   (RES_LIMITED & rflags) +			    && !(RES_LIMITED & res->rflags))  				inc_res_limited(); -			res->flags |= flags; +			res->rflags |= rflags;  		} + +		res->ippeerlimit = match.ippeerlimit; +  		break;  	case RESTRICT_UNFLAG:  		/* -		 * Remove some bits from the flags. If we didn't +		 * Remove some bits from the rflags. If we didn't  		 * find this one, just return.  		 */  		if (res != NULL) { -			if ((RES_LIMITED & res->flags) -			    && (RES_LIMITED & flags)) +			if (   (RES_LIMITED & res->rflags) +			    && (RES_LIMITED & rflags))  				dec_res_limited(); -			res->flags &= ~flags; +			res->rflags &= ~rflags;  		}  		break; @@ -639,7 +762,7 @@ restrict_source(  	SET_HOSTMASK(&onesmask, AF(addr));  	if (farewell) {  		hack_restrict(RESTRICT_REMOVE, addr, &onesmask, -			      0, 0, 0); +			      -2, 0, 0, 0);  		DPRINTF(1, ("restrict_source: %s removed", stoa(addr)));  		return;  	} @@ -672,8 +795,8 @@ restrict_source(  		return;  	hack_restrict(RESTRICT_FLAGS, addr, &onesmask, -		      restrict_source_mflags, restrict_source_flags, -		      expire); +		      restrict_source_ippeerlimit, restrict_source_mflags, +		      restrict_source_rflags, expire);  	DPRINTF(1, ("restrict_source: %s host restriction added\n",   		    stoa(addr)));  } | 
