aboutsummaryrefslogtreecommitdiff
path: root/ntpd/ntp_restrict.c
diff options
context:
space:
mode:
Diffstat (limited to 'ntpd/ntp_restrict.c')
-rw-r--r--ntpd/ntp_restrict.c197
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)));
}