Blob


1 /*
2 * Copyright (c) 2014 Peter J. Philipp
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. The name of the author may not be used to endorse or promote products
14 * derived from this software without specific prior written permission
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 *
27 */
28 #include "include.h"
29 #include "dns.h"
30 #include "db.h"
32 void add_rrlimit(int, u_int16_t *, int, char *);
33 int check_rrlimit(int, u_int16_t *, int, char *);
34 extern void dolog(int, char *, ...);
35 static u_int16_t hash_rrlimit(u_int16_t *, int);
36 char *rrlimit_setup(int);
38 struct rrlimit {
39 u_int8_t pointer;
40 time_t times[256];
41 };
43 int ratelimit = 0;
44 int ratelimit_packets_per_second = 6;
46 char *
47 rrlimit_setup(int size)
48 {
49 char *ptr;
51 if (size > 255)
52 return NULL;
54 size = 65536 * ((size * sizeof(time_t)) + sizeof(u_int8_t));
56 ptr = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED |\
57 MAP_ANON, -1, 0);
59 if (ptr == MAP_FAILED) {
60 dolog(LOG_ERR, "failed to setup rlimit mmap segment, exit\n");
61 exit(1);
62 }
64 memset(ptr, 0, size);
66 return (ptr);
67 }
69 int
70 check_rrlimit(int size, u_int16_t *ip, int sizeip, char *rrlimit_ptr)
71 {
72 struct rrlimit *rl;
73 u_int16_t hash;
74 int count = 0, i;
75 u_int8_t offset;
76 time_t now;
77 char *tmp;
79 hash = hash_rrlimit(ip, sizeip);
81 tmp = rrlimit_ptr + (hash * ((size * sizeof(time_t)) + sizeof(u_int8_t)));
82 rl = (struct rrlimit *)tmp;
84 offset = rl->pointer;
86 now = time(NULL);
88 for (i = 0; i < size; i++) {
89 if (difftime(now, rl->times[(offset + i) % size]) <= 1)
90 count++;
91 else
92 break;
93 }
95 if (count > ratelimit_packets_per_second)
96 return 1;
98 return 0;
99 }
102 void
103 add_rrlimit(int size, u_int16_t *ip, int sizeip, char *rrlimit_ptr)
105 struct rrlimit *rl;
106 u_int16_t hash;
107 int offset;
108 time_t now;
109 char *tmp;
111 hash = hash_rrlimit(ip, sizeip);
113 tmp = rrlimit_ptr + (hash * ((size * sizeof(time_t)) + sizeof(u_int8_t)));
114 rl = (struct rrlimit *)tmp;
116 offset = rl->pointer;
118 offset--;
119 if (offset < 0)
120 offset = size - 1;
122 now = time(NULL);
124 rl->times[offset] = now;
125 rl->pointer = offset; /* XXX race */
129 static u_int16_t
130 hash_rrlimit(u_int16_t *ip, int size)
132 u_int64_t total = 0;
133 int i, j;
135 for (i = 0, j = 0; i < size; i += 2) {
136 total += (u_int64_t)ip[j++];
139 total %= 0xffff;
141 return ((u_int16_t)total);