GNU libmicrohttpd 0.9.77
Loading...
Searching...
No Matches
daemon_ip_limit.c
Go to the documentation of this file.
1/*
2 This file is part of libmicrohttpd
3 Copyright (C) 2007-2018 Daniel Pittman and Christian Grothoff
4
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
9
10 This library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public
16 License along with this library; if not, write to the Free Software
17 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18*/
19
25#include "internal.h"
26#include "daemon_ip_limit.h"
27#if HAVE_SEARCH_H
28#include <search.h>
29#else
30#include "tsearch.h"
31#endif
32
33
37struct MHD_IPCount
38{
42 int family;
43
47 union
48 {
52 struct in_addr ipv4;
53#if HAVE_INET6
57 struct in6_addr ipv6;
58#endif
59 } addr;
60
64 unsigned int count;
65};
66
67
75static struct MHD_Daemon *
76get_master (struct MHD_Daemon *daemon)
77{
78 while (NULL != daemon->master)
79 daemon = daemon->master;
80 return daemon;
81}
82
83
89static void
91{
93}
94
95
101static void
103{
105}
106
107
117static int
118MHD_ip_addr_compare (const void *a1,
119 const void *a2)
120{
121 return memcmp (a1,
122 a2,
123 offsetof (struct MHD_IPCount,
124 count));
125}
126
127
136static int
137MHD_ip_addr_to_key (const struct sockaddr *addr,
138 socklen_t addrlen,
139 struct MHD_IPCount *key)
140{
141 memset (key,
142 0,
143 sizeof(*key));
144
145 /* IPv4 addresses */
146 if (sizeof (struct sockaddr_in) == addrlen)
147 {
148 const struct sockaddr_in *addr4 = (const struct sockaddr_in *) addr;
149
150 key->family = AF_INET;
151 memcpy (&key->addr.ipv4,
152 &addr4->sin_addr,
153 sizeof(addr4->sin_addr));
154 return MHD_YES;
155 }
156
157#if HAVE_INET6
158 /* IPv6 addresses */
159 if (sizeof (struct sockaddr_in6) == addrlen)
160 {
161 const struct sockaddr_in6 *addr6 = (const struct sockaddr_in6 *) addr;
162
163 key->family = AF_INET6;
164 memcpy (&key->addr.ipv6,
165 &addr6->sin6_addr,
166 sizeof(addr6->sin6_addr));
167 return MHD_YES;
168 }
169#endif
170
171 /* Some other address */
172 return MHD_NO;
173}
174
175
187int
189 const struct sockaddr *addr,
190 socklen_t addrlen)
191{
192 struct MHD_IPCount *key;
193 void **nodep;
194 void *node;
195 int result;
196
197 daemon = get_master (daemon);
198 /* Ignore if no connection limit assigned */
199 if (0 == daemon->ip_connection_limit)
200 return MHD_YES;
201
202 if (NULL == (key = malloc (sizeof(*key))))
203 return MHD_NO;
204
205 /* Initialize key */
206 if (MHD_NO == MHD_ip_addr_to_key (addr,
207 addrlen,
208 key))
209 {
210 /* Allow unhandled address types through */
211 free (key);
212 return MHD_YES;
213 }
214 MHD_ip_count_lock (daemon);
215
216 /* Search for the IP address */
217 if (NULL == (nodep = tsearch (key,
220 {
221#ifdef HAVE_MESSAGES
222 MHD_DLOG (daemon,
223 MHD_SC_IP_COUNTER_FAILURE,
224 _ ("Failed to add IP connection count node.\n"));
225#endif
226 MHD_ip_count_unlock (daemon);
227 free (key);
228 return MHD_NO;
229 }
230 node = *nodep;
231 /* If we got an existing node back, free the one we created */
232 if (node != key)
233 free (key);
234 key = (struct MHD_IPCount *) node;
235 /* Test if there is room for another connection; if so,
236 * increment count */
237 result = (key->count < daemon->ip_connection_limit) ? MHD_YES : MHD_NO;
238 if (MHD_YES == result)
239 ++key->count;
240
241 MHD_ip_count_unlock (daemon);
242 return result;
243}
244
245
254void
256 const struct sockaddr *addr,
257 socklen_t addrlen)
258{
259 struct MHD_IPCount search_key;
260 struct MHD_IPCount *found_key;
261 void **nodep;
262
263 daemon = get_master (daemon);
264 /* Ignore if no connection limit assigned */
265 if (0 == daemon->ip_connection_limit)
266 return;
267 /* Initialize search key */
268 if (MHD_NO == MHD_ip_addr_to_key (addr,
269 addrlen,
270 &search_key))
271 return;
272
273 MHD_ip_count_lock (daemon);
274
275 /* Search for the IP address */
276 if (NULL == (nodep = tfind (&search_key,
279 {
280 /* Something's wrong if we couldn't find an IP address
281 * that was previously added */
282 MHD_PANIC (_ ("Failed to find previously-added IP address.\n"));
283 }
284 found_key = (struct MHD_IPCount *) *nodep;
285 /* Validate existing count for IP address */
286 if (0 == found_key->count)
287 {
288 MHD_PANIC (_ ("Previously-added IP address had counter of zero.\n"));
289 }
290 /* Remove the node entirely if count reduces to 0 */
291 if (0 == --found_key->count)
292 {
293 tdelete (found_key,
296 free (found_key);
297 }
298
299 MHD_ip_count_unlock (daemon);
300}
301
302
303/* end of daemon_ip_limit.c */
static struct MHD_Daemon * get_master(struct MHD_Daemon *daemon)
static void MHD_ip_count_unlock(struct MHD_Daemon *daemon)
static int MHD_ip_addr_compare(const void *a1, const void *a2)
static int MHD_ip_addr_to_key(const struct sockaddr *addr, socklen_t addrlen, struct MHD_IPCount *key)
static void MHD_ip_count_lock(struct MHD_Daemon *daemon)
int MHD_ip_limit_add(struct MHD_Daemon *daemon, const struct sockaddr *addr, socklen_t addrlen)
void MHD_ip_limit_del(struct MHD_Daemon *daemon, const struct sockaddr *addr, socklen_t addrlen)
counting of connections per IP
#define MHD_PANIC(msg)
Definition internal.h:69
#define MHD_mutex_unlock_chk_(pmutex)
Definition mhd_locks.h:180
#define MHD_mutex_lock_chk_(pmutex)
Definition mhd_locks.h:154
#define NULL
void * tfind(const void *vkey, void *const *vrootp, int(*compar)(const void *, const void *))
Definition tsearch.c:63
void * tdelete(const void *__restrict vkey, void **__restrict vrootp, int(*compar)(const void *, const void *))
Definition tsearch.c:95
void * tsearch(const void *vkey, void **vrootp, int(*compar)(const void *, const void *))
Definition tsearch.c:27
#define _(String)
Definition mhd_options.h:42
MHD internal shared structures.
@ MHD_YES
Definition microhttpd.h:167
@ MHD_NO
Definition microhttpd.h:162
MHD_mutex_ per_ip_connection_mutex
Definition internal.h:1259
void * per_ip_connection_count
Definition internal.h:1187
unsigned int ip_connection_limit
Definition internal.h:1356
struct MHD_Daemon * master
Definition internal.h:1068