002
2019-02-28
pjp
* Copyright (c) 2014-2019 Peter J. Philipp
003
2014-11-14
pjp
* All rights reserved.
005
2014-11-14
pjp
* Redistribution and use in source and binary forms, with or without
006
2014-11-14
pjp
* modification, are permitted provided that the following conditions
007
2014-11-14
pjp
* are met:
008
2014-11-14
pjp
* 1. Redistributions of source code must retain the above copyright
009
2014-11-14
pjp
* notice, this list of conditions and the following disclaimer.
010
2014-11-14
pjp
* 2. Redistributions in binary form must reproduce the above copyright
011
2014-11-14
pjp
* notice, this list of conditions and the following disclaimer in the
012
2014-11-14
pjp
* documentation and/or other materials provided with the distribution.
013
2014-11-14
pjp
* 3. The name of the author may not be used to endorse or promote products
014
2014-11-14
pjp
* derived from this software without specific prior written permission
016
2014-11-14
pjp
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
017
2014-11-14
pjp
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
018
2014-11-14
pjp
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
019
2014-11-14
pjp
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
020
2014-11-14
pjp
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
021
2014-11-14
pjp
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
022
2014-11-14
pjp
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
023
2014-11-14
pjp
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
024
2014-11-14
pjp
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
025
2014-11-14
pjp
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
029
2019-06-06
pjp
#include <sys/types.h>
030
2019-06-06
pjp
#include <sys/socket.h>
031
2019-06-06
pjp
#include <sys/mman.h>
033
2019-06-06
pjp
#include <netinet/in.h>
034
2019-06-06
pjp
#include <arpa/inet.h>
035
2019-06-06
pjp
#include <netdb.h>
037
2019-06-06
pjp
#include <stdio.h>
038
2019-06-06
pjp
#include <stdlib.h>
039
2019-06-06
pjp
#include <string.h>
040
2019-06-06
pjp
#include <errno.h>
041
2019-06-06
pjp
#include <syslog.h>
042
2019-06-06
pjp
#include <time.h>
044
2019-06-06
pjp
#ifdef __linux__
045
2019-06-06
pjp
#include <grp.h>
046
2019-06-06
pjp
#define __USE_BSD 1
047
2019-06-06
pjp
#include <endian.h>
048
2019-06-06
pjp
#include <bsd/stdlib.h>
049
2019-06-06
pjp
#include <bsd/string.h>
050
2019-06-06
pjp
#include <bsd/sys/queue.h>
051
2019-06-06
pjp
#define __unused
052
2019-06-06
pjp
#include <bsd/sys/tree.h>
053
2019-06-06
pjp
#include <bsd/sys/endian.h>
054
2019-06-06
pjp
#else /* not linux */
055
2019-06-06
pjp
#include <sys/queue.h>
056
2019-06-06
pjp
#include <sys/tree.h>
057
2019-06-06
pjp
#endif /* __linux__ */
059
2016-07-06
pjp
#include "ddd-dns.h"
060
2016-07-06
pjp
#include "ddd-db.h"
062
2014-11-14
pjp
void add_rrlimit(int, u_int16_t *, int, char *);
063
2014-11-14
pjp
int check_rrlimit(int, u_int16_t *, int, char *);
064
2014-11-14
pjp
extern void dolog(int, char *, ...);
065
2014-11-14
pjp
static u_int16_t hash_rrlimit(u_int16_t *, int);
066
2014-11-14
pjp
char *rrlimit_setup(int);
068
2014-11-14
pjp
struct rrlimit {
069
2014-11-14
pjp
u_int8_t pointer;
070
2014-11-14
pjp
time_t times[256];
071
2019-02-28
pjp
} __attribute__((packed));
073
2014-11-14
pjp
int ratelimit = 0;
074
2014-11-14
pjp
int ratelimit_packets_per_second = 6;
077
2014-11-14
pjp
rrlimit_setup(int size)
079
2014-11-14
pjp
char *ptr;
081
2014-11-14
pjp
if (size > 255)
082
2014-11-14
pjp
return NULL;
084
2014-11-14
pjp
size = 65536 * ((size * sizeof(time_t)) + sizeof(u_int8_t));
086
2014-11-14
pjp
ptr = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED |\
087
2014-11-14
pjp
MAP_ANON, -1, 0);
089
2014-11-14
pjp
if (ptr == MAP_FAILED) {
090
2014-11-14
pjp
dolog(LOG_ERR, "failed to setup rlimit mmap segment, exit\n");
091
2014-11-14
pjp
exit(1);
094
2014-11-14
pjp
memset(ptr, 0, size);
096
2014-11-14
pjp
return (ptr);
100
2014-11-14
pjp
check_rrlimit(int size, u_int16_t *ip, int sizeip, char *rrlimit_ptr)
102
2014-11-14
pjp
struct rrlimit *rl;
103
2014-11-14
pjp
u_int16_t hash;
104
2014-11-14
pjp
int count = 0, i;
105
2014-11-14
pjp
u_int8_t offset;
106
2014-11-14
pjp
time_t now;
107
2014-11-14
pjp
char *tmp;
109
2014-11-14
pjp
hash = hash_rrlimit(ip, sizeip);
111
2014-11-14
pjp
tmp = rrlimit_ptr + (hash * ((size * sizeof(time_t)) + sizeof(u_int8_t)));
112
2014-11-14
pjp
rl = (struct rrlimit *)tmp;
114
2014-11-14
pjp
offset = rl->pointer;
116
2014-11-14
pjp
now = time(NULL);
118
2014-11-14
pjp
for (i = 0; i < size; i++) {
119
2014-11-14
pjp
if (difftime(now, rl->times[(offset + i) % size]) <= 1)
120
2014-11-14
pjp
count++;
125
2014-11-14
pjp
if (count > ratelimit_packets_per_second)
126
2014-11-14
pjp
return 1;
128
2014-11-14
pjp
return 0;
133
2014-11-14
pjp
add_rrlimit(int size, u_int16_t *ip, int sizeip, char *rrlimit_ptr)
135
2014-11-14
pjp
struct rrlimit *rl;
136
2014-11-14
pjp
u_int16_t hash;
137
2014-11-14
pjp
int offset;
138
2014-11-14
pjp
time_t now;
139
2014-11-14
pjp
char *tmp;
141
2014-11-14
pjp
hash = hash_rrlimit(ip, sizeip);
143
2014-11-14
pjp
tmp = rrlimit_ptr + (hash * ((size * sizeof(time_t)) + sizeof(u_int8_t)));
144
2014-11-14
pjp
rl = (struct rrlimit *)tmp;
146
2014-11-14
pjp
offset = rl->pointer;
148
2014-11-14
pjp
offset--;
149
2014-11-14
pjp
if (offset < 0)
150
2014-11-14
pjp
offset = size - 1;
152
2014-11-14
pjp
now = time(NULL);
154
2014-11-14
pjp
rl->times[offset] = now;
155
2014-11-14
pjp
rl->pointer = offset; /* XXX race */
159
2014-11-14
pjp
static u_int16_t
160
2014-11-14
pjp
hash_rrlimit(u_int16_t *ip, int size)
162
2014-11-14
pjp
u_int64_t total = 0;
163
2014-11-14
pjp
int i, j;
165
2014-11-14
pjp
for (i = 0, j = 0; i < size; i += 2) {
166
2014-11-14
pjp
total += (u_int64_t)ip[j++];
169
2014-11-14
pjp
total %= 0xffff;
171
2014-11-14
pjp
return ((u_int16_t)total);