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))); } |