summaryrefslogtreecommitdiff
path: root/usr.sbin
diff options
context:
space:
mode:
authorStuart Henderson <sthen@cvs.openbsd.org>2013-02-18 10:17:42 +0000
committerStuart Henderson <sthen@cvs.openbsd.org>2013-02-18 10:17:42 +0000
commite6bf45d612065fd90c9a2101a4368f85d445ab90 (patch)
treeee0b6036f5ea7ebb3b73812fbfeeeb0c6fd7d5cd /usr.sbin
parentebfb4d52c189242189704661a30c81060404c3ac (diff)
Update to NSD 3.2.15, ok brad@ phessler@ deraadt@ also tested by okan@
Diffstat (limited to 'usr.sbin')
-rw-r--r--usr.sbin/nsd/rrl.c83
1 files changed, 25 insertions, 58 deletions
diff --git a/usr.sbin/nsd/rrl.c b/usr.sbin/nsd/rrl.c
index 65f3788ea59..01da9d75ff1 100644
--- a/usr.sbin/nsd/rrl.c
+++ b/usr.sbin/nsd/rrl.c
@@ -7,7 +7,6 @@
#include "config.h"
#include <errno.h>
#include <ctype.h>
-#include "dns.h"
#include "rrl.h"
#include "util.h"
#include "lookup3.h"
@@ -34,8 +33,6 @@ struct rrl_bucket {
/* rate, in queries per second, which due to rate=r(t)+r(t-1)/2 is
* equal to double the queries per second */
uint32_t rate;
- /* the full hash */
- uint32_t hash;
/* counter for queries arrived in this second */
uint32_t counter;
/* timestamp, which time is the time of the counter, the rate is from
@@ -49,10 +46,6 @@ struct rrl_bucket {
static struct rrl_bucket* rrl_array = NULL;
static size_t rrl_array_size = RRL_BUCKETS;
static uint32_t rrl_ratelimit = RRL_LIMIT; /* 2x qps */
-static uint8_t rrl_slip_ratio = RRL_SLIP;
-static uint8_t rrl_ipv4_prefixlen = RRL_IPV4_PREFIX_LENGTH;
-static uint8_t rrl_ipv6_prefixlen = RRL_IPV6_PREFIX_LENGTH;
-static uint64_t rrl_ipv6_mask; /* max prefixlen 64 */
static uint32_t rrl_whitelist_ratelimit = RRL_WLIST_LIMIT; /* 2x qps */
/* the array of mmaps for the children (saved between reloads) */
@@ -90,8 +83,7 @@ static char* wiredname2str(const uint8_t* dname)
return buf;
}
-void rrl_mmap_init(int numch, size_t numbuck, size_t lm, size_t wlm, size_t sm,
- size_t plf, size_t pls)
+void rrl_mmap_init(int numch, size_t numbuck, size_t lm, size_t wlm)
{
#ifdef HAVE_MMAP
size_t i;
@@ -99,15 +91,6 @@ void rrl_mmap_init(int numch, size_t numbuck, size_t lm, size_t wlm, size_t sm,
if(numbuck != 0)
rrl_array_size = numbuck;
rrl_ratelimit = lm*2;
- rrl_slip_ratio = sm;
- rrl_ipv4_prefixlen = plf;
- rrl_ipv6_prefixlen = pls;
- if (pls <= 32) {
- rrl_ipv6_mask = ((uint64_t) htonl(0xffffffff << (32-pls))) << 32;
- } else {
- rrl_ipv6_mask = ((uint64_t) htonl(0xffffffff << (64-pls))) |
- (((uint64_t)0xffffffff)<<32);
- }
rrl_whitelist_ratelimit = wlm*2;
#ifdef HAVE_MMAP
/* allocate the ratelimit hashtable in a memory map so it is
@@ -116,7 +99,7 @@ void rrl_mmap_init(int numch, size_t numbuck, size_t lm, size_t wlm, size_t sm,
rrl_maps = (void**)xalloc(sizeof(void*)*rrl_maps_num);
for(i=0; i<rrl_maps_num; i++) {
rrl_maps[i] = mmap(NULL,
- sizeof(struct rrl_bucket)*rrl_array_size,
+ sizeof(struct rrl_bucket)*rrl_array_size,
PROT_READ|PROT_WRITE, MAP_SHARED|MAP_ANONYMOUS, -1, 0);
if(rrl_maps[i] == MAP_FAILED) {
log_msg(LOG_ERR, "rrl: mmap failed: %s",
@@ -133,6 +116,12 @@ void rrl_mmap_init(int numch, size_t numbuck, size_t lm, size_t wlm, size_t sm,
#endif
}
+void rrl_set_limit(size_t lm, size_t wlm)
+{
+ rrl_ratelimit = lm*2;
+ rrl_whitelist_ratelimit = wlm*2;
+}
+
void rrl_init(size_t ch)
{
if(!rrl_maps || ch >= rrl_maps_num)
@@ -146,6 +135,7 @@ void rrl_init(size_t ch)
* for genuine queries and the target for reflected packets */
static uint64_t rrl_get_source(query_type* query, uint16_t* c2)
{
+ /* we take a /24 for IPv4 and /64 for IPv6 */
/* note there is an IPv6 subnet, that maps
* to the same buckets as IPv4 space, but there is a flag in c2
* that makes the hash different */
@@ -153,17 +143,17 @@ static uint64_t rrl_get_source(query_type* query, uint16_t* c2)
if( ((struct sockaddr_in*)&query->addr)->sin_family == AF_INET) {
*c2 = 0;
return ((struct sockaddr_in*)&query->addr)->
- sin_addr.s_addr & htonl(0xffffffff << (32-rrl_ipv4_prefixlen));
+ sin_addr.s_addr & htonl(0xffffff00);
} else {
uint64_t s;
*c2 = rrl_ip6;
memmove(&s, &((struct sockaddr_in6*)&query->addr)->sin6_addr,
sizeof(s));
- return s & rrl_ipv6_mask;
+ return s;
}
#else
*c2 = 0;
- return query->addr.sin_addr.s_addr & htonl(0xffffffff << (32-rrl_ipv4_prefixlen));
+ return query->addr.sin_addr.s_addr & htonl(0xffffff00);
#endif
}
@@ -180,11 +170,7 @@ static const char* rrlsource2str(uint64_t s, uint16_t c2)
memmove(&a6, &s, sizeof(s));
if(!inet_ntop(AF_INET6, &a6, buf, sizeof(buf)))
strlcpy(buf, "[ip6 ntop failed]", sizeof(buf));
- else {
- static char prefix[4];
- snprintf(prefix, sizeof(prefix), "/%d", rrl_ipv6_prefixlen);
- strlcat(buf, &prefix[0], sizeof(buf));
- }
+ else strlcat(buf, "/64", sizeof(buf));
return buf;
}
#endif
@@ -192,11 +178,7 @@ static const char* rrlsource2str(uint64_t s, uint16_t c2)
a4.s_addr = (uint32_t)s;
if(!inet_ntop(AF_INET, &a4, buf, sizeof(buf)))
strlcpy(buf, "[ip4 ntop failed]", sizeof(buf));
- else {
- static char prefix[4];
- snprintf(prefix, sizeof(prefix), "/%d", rrl_ipv4_prefixlen);
- strlcat(buf, &prefix[0], sizeof(buf));
- }
+ else strlcat(buf, "/24", sizeof(buf));
return buf;
}
@@ -234,7 +216,7 @@ const char* rrltype2str(enum rrl_type c)
/** classify the query in a number of different types, each has separate
* ratelimiting, so that positive queries are not impeded by others */
-static uint16_t rrl_classify(query_type* query, const uint8_t** d,
+static uint16_t rrl_classify(query_type* query, const uint8_t** d,
size_t* d_len)
{
if(RCODE(query->packet) == RCODE_NXDOMAIN) {
@@ -310,7 +292,7 @@ static void examine_query(query_type* query, uint32_t* hash, uint64_t* source,
*source = rrl_get_source(query, &c2);
c = rrl_classify(query, &dname, &dname_len);
- if(query->zone && query->zone->opts &&
+ if(query->zone && query->zone->opts &&
(query->zone->opts->rrl_whitelist & c))
*lm = rrl_whitelist_ratelimit;
if(*lm == 0) return;
@@ -352,21 +334,15 @@ rrl_msg(query_type* query, const char* str)
const uint8_t* d = NULL;
size_t d_len;
uint64_t s;
- char address[128];
if(verbosity < 2) return;
- if (addr2ip(query->addr, address, sizeof(address))) {
- DEBUG(DEBUG_XFRD,1, (LOG_INFO, "addr2ip failed"));
- strlcpy(address, "[unknown]", sizeof(address));
- }
s = rrl_get_source(query, &c2);
c = rrl_classify(query, &d, &d_len) | c2;
- if(query->zone && query->zone->opts &&
+ if(query->zone && query->zone->opts &&
(query->zone->opts->rrl_whitelist & c))
wl = 1;
- log_msg(LOG_INFO, "ratelimit %s %s type %s%s target %s query %s %s",
+ log_msg(LOG_INFO, "ratelimit %s %s type %s%s target %s",
str, d?wiredname2str(d):"", rrltype2str(c),
- wl?"(whitelisted)":"", rrlsource2str(s, c2),
- address, rrtype_to_string(query->qtype));
+ wl?"(whitelisted)":"", rrlsource2str(s, c2));
}
/** true if the query used to be blocked by the ratelimit */
@@ -386,23 +362,14 @@ uint32_t rrl_update(query_type* query, uint32_t hash, uint64_t source,
(long long unsigned)source, hash, b->rate, b->counter, b->stamp));
/* check if different source */
- if(b->source != source || b->flags != flags || b->hash != hash) {
+ if(b->source != source || b->flags != flags) {
/* initialise */
/* potentially the wrong limit here, used lower nonwhitelim */
if(verbosity >=2 &&
- used_to_block(b->rate, b->counter, rrl_ratelimit)) {
- char address[128];
- if (addr2ip(query->addr, address, sizeof(address))) {
- DEBUG(DEBUG_XFRD,1, (LOG_INFO, "addr2ip failed"));
- strlcpy(address, "[unknown]", sizeof(address));
- }
- log_msg(LOG_INFO, "ratelimit unblock ~ type %s target %s query %s %s (%s collision)",
+ used_to_block(b->rate, b->counter, rrl_ratelimit))
+ log_msg(LOG_INFO, "ratelimit unblock ~ type %s target %s",
rrltype2str(b->flags),
- rrlsource2str(b->source, b->flags),
- address, rrtype_to_string(query->qtype),
- (b->hash!=hash?"bucket":"hash"));
- }
- b->hash = hash;
+ rrlsource2str(b->source, b->flags));
b->source = source;
b->flags = flags;
b->counter = 1;
@@ -476,8 +443,8 @@ int rrl_process_query(query_type* query)
query_state_type rrl_slip(query_type* query)
{
- /* discard number of packets, randomly */
- if((rrl_slip_ratio > 0) && ((rrl_slip_ratio == 1) || ((random() % rrl_slip_ratio) == 0))) {
+ /* discard half the packets, randomly */
+ if((random() & 0x1)) {
/* set TC on the rest */
TC_SET(query->packet);
ANCOUNT_SET(query->packet, 0);