1 /*
2     MiddleMan filtering proxy server
3     Copyright (C) 2002  Jason McLaughlin
4 
5     This program is free software; you can redistribute it and/or modify
6     it under the terms of the GNU General Public License as published by
7     the Free Software Foundation; either version 2 of the License, or
8     (at your option) any later version.
9 
10     This program 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
13     GNU General Public License for more details.
14 
15     You should have received a copy of the GNU General Public License
16     along with this program; if not, write to the Free Software
17     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18 */
19 
20 #include <stdio.h>
21 #include <string.h>
22 #include <time.h>
23 #include "proto.h"
24 
limits_load(LIMITS_LIST * limits_list,XML_LIST * xml_list)25 LIMITS_LIST *limits_load(LIMITS_LIST * limits_list, XML_LIST * xml_list)
26 {
27 	LIMITS_LIST *tmp_list = limits_list;
28 	struct LIMITS_LIST_LIST *ll = NULL;
29 	struct tm from, to;
30 	int totime, fromtime;
31 
32 	if (tmp_list == NULL) {
33 		tmp_list = xmalloc(sizeof(LIMITS_LIST));
34 		tmp_list->limits_list = NULL;
35 		tmp_list->enabled = TRUE;
36 		tmp_list->id = 0;
37 
38 		limits_list = tmp_list;
39 
40 		pthread_rwlock_init(&tmp_list->lock, NULL);
41 	} else
42 		ll = limits_list->limits_list;
43 
44 	while ((xml_list = xml_section(xml_list, "<limits>"))) {
45 		XML_LIST_LOOP(xml_list, "<limits>") {
46 			XML_LIST_CMP(xml_list, "<item>") {
47 				ll = limits_ll_new(ll);
48 				ll->id = tmp_list->id++;
49 
50 				if (limits_list->limits_list == NULL)
51 					limits_list->limits_list = ll;
52 
53 				memset(&from, 0, sizeof(struct tm));
54 				memset(&to, 0, sizeof(struct tm));
55 				fromtime = totime = FALSE;
56 
57 				XML_LIST_LOOP(xml_list, "<item>") {
58 					XML_LIST_CMP(xml_list, "<enabled>") {
59 						xml_list = xml_list->next;
60 						if (xml_list->type == XML_VALUE) {
61 							if (!strcasecmp(xml_list->item, "false"))
62 								ll->enabled = FALSE;
63 							else
64 								ll->enabled = TRUE;
65 						}
66 					}
67 					XML_LIST_CMP(xml_list, "<action>") {
68 						xml_list = xml_list->next;
69 						if (xml_list->type == XML_VALUE) {
70 							if (!strcasecmp(xml_list->item, "allow"))
71 								ll->action = POLICY_ALLOW;
72 							else
73 								ll->action = POLICY_DENY;
74 						}
75 					}
76 					XML_LIST_CMP(xml_list, "<profiles>") {
77 						xml_list = xml_list->next;
78 						if (xml_list->type == XML_VALUE)
79 							limits_ll_insert(ll, xml_list->item, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
80 					}
81 					XML_LIST_CMP(xml_list, "<comment>") {
82 						xml_list = xml_list->next;
83 						if (xml_list->type == XML_VALUE)
84 							limits_ll_insert(ll, NULL, xml_list->item, NULL, NULL, NULL, NULL, NULL, NULL);
85 					}
86 					XML_LIST_CMP(xml_list, "<template>") {
87 						xml_list = xml_list->next;
88 						if (xml_list->type == XML_VALUE)
89 							limits_ll_insert(ll, NULL, NULL, xml_list->item, NULL, NULL, NULL, NULL, NULL);
90 					}
91 					XML_LIST_CMP(xml_list, "<fromhour>") {
92 						xml_list = xml_list->next;
93 						if (xml_list->type == XML_VALUE) {
94 							fromtime = TRUE;
95 							from.tm_hour = strtol(xml_list->item, NULL, 10);
96 						}
97 					}
98 					XML_LIST_CMP(xml_list, "<frommin>") {
99 						xml_list = xml_list->next;
100 						if (xml_list->type == XML_VALUE) {
101 							fromtime = TRUE;
102 							from.tm_min = strtol(xml_list->item, NULL, 10);
103 						}
104 					}
105 					XML_LIST_CMP(xml_list, "<frommday>") {
106 						xml_list = xml_list->next;
107 						if (xml_list->type == XML_VALUE) {
108 							fromtime = TRUE;
109 							from.tm_mday = strtol(xml_list->item, NULL, 10);
110 						}
111 					}
112 					XML_LIST_CMP(xml_list, "<frommon>") {
113 						xml_list = xml_list->next;
114 						if (xml_list->type == XML_VALUE) {
115 							fromtime = TRUE;
116 							from.tm_mon = strtol(xml_list->item, NULL, 10);
117 						}
118 					}
119 					XML_LIST_CMP(xml_list, "<fromwday>") {
120 						xml_list = xml_list->next;
121 						if (xml_list->type == XML_VALUE) {
122 							fromtime = TRUE;
123 							from.tm_wday = strtol(xml_list->item, NULL, 10);
124 						}
125 					}
126 					XML_LIST_CMP(xml_list, "<tohour>") {
127 						xml_list = xml_list->next;
128 						if (xml_list->type == XML_VALUE) {
129 							totime = TRUE;
130 							to.tm_hour = strtol(xml_list->item, NULL, 10);
131 						}
132 					}
133 					XML_LIST_CMP(xml_list, "<tomin>") {
134 						xml_list = xml_list->next;
135 						if (xml_list->type == XML_VALUE) {
136 							totime = TRUE;
137 							to.tm_min = strtol(xml_list->item, NULL, 10);
138 						}
139 					}
140 					XML_LIST_CMP(xml_list, "<tomday>") {
141 						xml_list = xml_list->next;
142 						if (xml_list->type == XML_VALUE) {
143 							totime = TRUE;
144 							to.tm_mday = strtol(xml_list->item, NULL, 10);
145 						}
146 					}
147 					XML_LIST_CMP(xml_list, "<tomon>") {
148 						xml_list = xml_list->next;
149 						if (xml_list->type == XML_VALUE) {
150 							totime = TRUE;
151 							to.tm_mon = strtol(xml_list->item, NULL, 10);
152 						}
153 					}
154 					XML_LIST_CMP(xml_list, "<towday>") {
155 						xml_list = xml_list->next;
156 						if (xml_list->type == XML_VALUE) {
157 							totime = TRUE;
158 							to.tm_wday = strtol(xml_list->item, NULL, 10);
159 						}
160 					}
161 					XML_LIST_CMP(xml_list, "<maxbytes>") {
162 						xml_list = xml_list->next;
163 						if (xml_list->type == XML_VALUE)
164 							limits_ll_insert(ll, NULL, NULL, NULL, NULL, NULL, xml_list->item, NULL, NULL);
165 					}
166 					XML_LIST_CMP(xml_list, "<maxrequests>") {
167 						xml_list = xml_list->next;
168 						if (xml_list->type == XML_VALUE)
169 							limits_ll_insert(ll, NULL, NULL, NULL, NULL, NULL, NULL, xml_list->item, NULL);
170 					}
171 					XML_LIST_CMP(xml_list, "<flags>") {
172 						xml_list = xml_list->next;
173 						if (xml_list->type == XML_VALUE)
174 							limits_ll_insert(ll, NULL, NULL, NULL, NULL, NULL, NULL, NULL, xml_list->item);
175 					}
176 				}
177 
178 				if (fromtime == TRUE)
179 					limits_ll_insert(ll, NULL, NULL, NULL, &from, NULL, NULL, NULL, NULL);
180 				if (totime == TRUE)
181 					limits_ll_insert(ll, NULL, NULL, NULL, NULL, &to, NULL, NULL, NULL);
182 			}
183 			XML_LIST_CMP(xml_list, "<enabled>") {
184 				xml_list = xml_list->next;
185 				if (xml_list->type == XML_VALUE) {
186 					if (!strcasecmp(xml_list->item, "false"))
187 						limits_list->enabled = FALSE;
188 					else
189 						limits_list->enabled = TRUE;
190 				}
191 			}
192 		}
193 	}
194 
195 
196 	return limits_list;
197 }
198 
limits_xml(LIMITS_LIST * limits_list,XML_LIST * xml_list)199 XML_LIST *limits_xml(LIMITS_LIST * limits_list, XML_LIST * xml_list)
200 {
201 	char *ptr, buf[128];
202 	struct LIMITS_LIST_LIST *ll;
203 
204 	pthread_rwlock_rdlock(&limits_list->lock);
205 
206 	xml_list = xml_list_add(xml_list, "<limits>", XML_TAG);
207 
208 	xml_list = xml_list_add(xml_list, "<enabled>", XML_TAG);
209 	xml_list = xml_list_add(xml_list, (limits_list->enabled == TRUE) ? "true" : "false", XML_VALUE);
210 	xml_list = xml_list_add(xml_list, "</enabled>", XML_TAG);
211 
212 	for (ll = limits_list->limits_list; ll; ll = ll->next) {
213 		xml_list = xml_list_add(xml_list, "<item>", XML_TAG);
214 
215 		if (ll->comment != NULL) {
216 			xml_list = xml_list_add(xml_list, "<comment>", XML_TAG);
217 			ptr = string_to_xml(ll->comment);
218 			xml_list = xml_list_add(xml_list, ptr, XML_VALUE);
219 			xfree(ptr);
220 			xml_list = xml_list_add(xml_list, "</comment>", XML_TAG);
221 		}
222 
223 		if (ll->profiles != NULL) {
224 			xml_list = xml_list_add(xml_list, "<profiles>", XML_TAG);
225 			ptr = array_merge(ll->profiles, ',');
226 			xml_list = xml_list_add(xml_list, ptr, XML_VALUE);
227 			xfree(ptr);
228 			xml_list = xml_list_add(xml_list, "</profiles>", XML_TAG);
229 		}
230 
231 		xml_list = xml_list_add(xml_list, "<action>", XML_TAG);
232 		xml_list = xml_list_add(xml_list, (ll->action == POLICY_ALLOW) ? "allow" : "deny", XML_VALUE);
233 		xml_list = xml_list_add(xml_list, "</action>", XML_TAG);
234 
235 		if (ll->template != NULL) {
236 			xml_list = xml_list_add(xml_list, "<template>", XML_TAG);
237 			ptr = string_to_xml(ll->template);
238 			xml_list = xml_list_add(xml_list, ptr, XML_VALUE);
239 			xfree(ptr);
240 			xml_list = xml_list_add(xml_list, "</template>", XML_TAG);
241 		}
242 
243 		if (ll->from != NULL) {
244 			if (ll->from->tm_hour != 0) {
245 				xml_list = xml_list_add(xml_list, "<fromhour>", XML_TAG);
246 				snprintf(buf, sizeof(buf), "%d", ll->from->tm_hour);
247 				xml_list = xml_list_add(xml_list, buf, XML_VALUE);
248 				xml_list = xml_list_add(xml_list, "</fromhour>", XML_TAG);
249 			}
250 
251 			if (ll->from->tm_min != 0) {
252 				xml_list = xml_list_add(xml_list, "<frommin>", XML_TAG);
253 				snprintf(buf, sizeof(buf), "%d", ll->from->tm_min);
254 				xml_list = xml_list_add(xml_list, buf, XML_VALUE);
255 				xml_list = xml_list_add(xml_list, "</frommin>", XML_TAG);
256 			}
257 
258 			if (ll->from->tm_mday != 0) {
259 				xml_list = xml_list_add(xml_list, "<frommday>", XML_TAG);
260 				snprintf(buf, sizeof(buf), "%d", ll->from->tm_mday);
261 				xml_list = xml_list_add(xml_list, buf, XML_VALUE);
262 				xml_list = xml_list_add(xml_list, "</frommday>", XML_TAG);
263 			}
264 
265 			if (ll->from->tm_mon != 0) {
266 				xml_list = xml_list_add(xml_list, "<frommon>", XML_TAG);
267 				snprintf(buf, sizeof(buf), "%d", ll->from->tm_mon);
268 				xml_list = xml_list_add(xml_list, buf, XML_VALUE);
269 				xml_list = xml_list_add(xml_list, "</frommon>", XML_TAG);
270 			}
271 
272 			if (ll->from->tm_wday != 0) {
273 				xml_list = xml_list_add(xml_list, "<fromwday>", XML_TAG);
274 				snprintf(buf, sizeof(buf), "%d", ll->from->tm_wday);
275 				xml_list = xml_list_add(xml_list, buf, XML_VALUE);
276 				xml_list = xml_list_add(xml_list, "</fromwday>", XML_TAG);
277 			}
278 		}
279 
280 		if (ll->to != NULL) {
281 			if (ll->to->tm_hour != 0) {
282 				xml_list = xml_list_add(xml_list, "<tohour>", XML_TAG);
283 				snprintf(buf, sizeof(buf), "%d", ll->to->tm_hour);
284 				xml_list = xml_list_add(xml_list, buf, XML_VALUE);
285 				xml_list = xml_list_add(xml_list, "</tohour>", XML_TAG);
286 			}
287 
288 			if (ll->to->tm_min != 0) {
289 				xml_list = xml_list_add(xml_list, "<tomin>", XML_TAG);
290 				snprintf(buf, sizeof(buf), "%d", ll->to->tm_min);
291 				xml_list = xml_list_add(xml_list, buf, XML_VALUE);
292 				xml_list = xml_list_add(xml_list, "</tomin>", XML_TAG);
293 			}
294 
295 			if (ll->to->tm_mday != 0) {
296 				xml_list = xml_list_add(xml_list, "<tomday>", XML_TAG);
297 				snprintf(buf, sizeof(buf), "%d", ll->to->tm_mday);
298 				xml_list = xml_list_add(xml_list, buf, XML_VALUE);
299 				xml_list = xml_list_add(xml_list, "</tomday>", XML_TAG);
300 			}
301 
302 			if (ll->to->tm_mon != 0) {
303 				xml_list = xml_list_add(xml_list, "<tomon>", XML_TAG);
304 				snprintf(buf, sizeof(buf), "%d", ll->to->tm_mon);
305 				xml_list = xml_list_add(xml_list, buf, XML_VALUE);
306 				xml_list = xml_list_add(xml_list, "</tomon>", XML_TAG);
307 			}
308 
309 			if (ll->to->tm_wday != 0) {
310 				xml_list = xml_list_add(xml_list, "<towday>", XML_TAG);
311 				snprintf(buf, sizeof(buf), "%d", ll->to->tm_wday);
312 				xml_list = xml_list_add(xml_list, buf, XML_VALUE);
313 				xml_list = xml_list_add(xml_list, "</towday>", XML_TAG);
314 			}
315 		}
316 
317 		if (ll->maxbytes != 0) {
318 			xml_list = xml_list_add(xml_list, "<maxbytes>", XML_TAG);
319 			snprintf(buf, sizeof(buf), "%u", ll->maxbytes);
320 			xml_list = xml_list_add(xml_list, buf, XML_VALUE);
321 			xml_list = xml_list_add(xml_list, "</maxbytes>", XML_TAG);
322 		}
323 
324 		if (ll->maxrequests != 0) {
325 			xml_list = xml_list_add(xml_list, "<maxrequests>", XML_TAG);
326 			snprintf(buf, sizeof(buf), "%u", ll->maxrequests);
327 			xml_list = xml_list_add(xml_list, buf, XML_VALUE);
328 			xml_list = xml_list_add(xml_list, "</maxrequests>", XML_TAG);
329 		}
330 
331 		if (ll->flags != 0) {
332 			xml_list = xml_list_add(xml_list, "<flags>", XML_TAG);
333 			snprintf(buf, sizeof(buf), "%s,%s,%s", (ll->flags & LIMIT_CACHE) ? "limitcache" : "", (ll->flags & LIMIT_ABSOLUTETIME) ? "absolutetime" : "", (ll->flags & LIMIT_ALLRANGETIME) ? "allrangetime" : "");
334 			xml_list = xml_list_add(xml_list, buf, XML_VALUE);
335 			xml_list = xml_list_add(xml_list, "</flags>", XML_TAG);
336 		}
337 
338 		xml_list = xml_list_add(xml_list, "</item>", XML_TAG);
339 	}
340 
341 	xml_list = xml_list_add(xml_list, "</limits>", XML_TAG);
342 
343 	pthread_rwlock_unlock(&limits_list->lock);
344 
345 	return xml_list;
346 }
347 
limits_ll_insert(struct LIMITS_LIST_LIST * x,char * profiles,char * comment,char * template,struct tm * from,struct tm * to,char * maxbytes,char * maxrequests,char * flags)348 void limits_ll_insert(struct LIMITS_LIST_LIST *x, char *profiles, char *comment, char *template, struct tm *from, struct tm *to, char *maxbytes, char *maxrequests, char *flags)
349 {
350 	int i;
351 	char **args;
352 
353 	if (profiles != NULL) {
354 		if (x->profiles != NULL)
355 			array_free(x->profiles);
356 
357 		if (strcmp(profiles, ""))
358 			x->profiles = string_break(profiles, ',');
359 		else
360 			x->profiles = NULL;
361 	}
362 
363 	if (comment != NULL) {
364 		FREE_AND_NULL(x->comment);
365 
366 		if (strcmp(comment, ""))
367 			x->comment = xstrdup(comment);
368 	}
369 
370 	if (template != NULL) {
371 		FREE_AND_NULL(x->template);
372 
373 		if (strcmp(template, ""))
374 			x->template = xstrdup(template);
375 	}
376 
377 	if (from != NULL) {
378 		FREE_AND_NULL(x->from);
379 
380 		x->from = xmalloc(sizeof(struct tm));
381 		*x->from = *from;
382 	}
383 
384 	if (to != NULL) {
385 		FREE_AND_NULL(x->to);
386 
387 		x->to = xmalloc(sizeof(struct tm));
388 		*x->to = *to;
389 	}
390 
391 	if (maxbytes != NULL) {
392 		x->maxbytes = 0;
393 
394 		if (strcmp(maxbytes, ""))
395 			x->maxbytes = strtoll(maxbytes, NULL, 10);
396 	}
397 
398 	if (maxrequests != NULL) {
399 		x->maxrequests = 0;
400 
401 		if (strcmp(maxrequests, ""))
402 			x->maxrequests = strtoll(maxrequests, NULL, 10);
403 	}
404 
405 	if (flags != NULL) {
406 		x->flags = LIMIT_ABSOLUTETIME;;
407 
408 		if (strcmp(flags, "")) {
409 			args = string_break(flags, ',');
410 			for (i = 0; args[i]; i++) {
411 				if (!strcasecmp(args[i], "limitcache"))
412 					x->flags |= LIMIT_CACHE;
413 				else if (!strcasecmp(args[i], "absolutetime")) {
414 					x->flags &= ~LIMIT_ALLRANGETIME;
415 					x->flags |= LIMIT_ABSOLUTETIME;
416 				} else if (!strcasecmp(args[i], "allrangetime")) {
417 					x->flags &= ~LIMIT_ABSOLUTETIME;
418 					x->flags |= LIMIT_ALLRANGETIME;
419 				}
420 
421 				xfree(args[i]);
422 			}
423 			xfree(args);
424 		}
425 	}
426 
427 }
428 
limits_ll_new(struct LIMITS_LIST_LIST * x)429 struct LIMITS_LIST_LIST *limits_ll_new(struct LIMITS_LIST_LIST *x)
430 {
431 	if (x == NULL) {
432 		x = xmalloc(sizeof(struct LIMITS_LIST_LIST));
433 		x->prev = NULL;
434 	} else {
435 		while (x->next != NULL)
436 			x = x->next;
437 		x->next = xmalloc(sizeof(struct LIMITS_LIST_LIST));
438 		x->next->prev = x;
439 		x = x->next;
440 	}
441 
442 	x->next = NULL;
443 	x->enabled = TRUE;
444 	x->profiles = NULL;
445 	x->action = POLICY_ALLOW;
446 	x->comment = NULL;
447 	x->template = NULL;
448 	x->from = NULL;
449 	x->to = NULL;
450 	x->maxrequests = 0;
451 	x->maxbytes = 0;
452 	x->n_requests = 0;
453 	x->n_bytes = 0;
454 	x->flags = LIMIT_ABSOLUTETIME;
455 
456 	return x;
457 }
458 
limits_ll_delete(struct LIMITS_LIST_LIST * x)459 struct LIMITS_LIST_LIST *limits_ll_delete(struct LIMITS_LIST_LIST *x)
460 {
461 	struct LIMITS_LIST_LIST *start = x;
462 
463 	while (start->prev != NULL)
464 		start = start->prev;
465 
466 	if (x->next != NULL)
467 		x->next->prev = x->prev;
468 	if (x->prev != NULL)
469 		x->prev->next = x->next;
470 	else
471 		start = x->next;
472 
473 	if (x->profiles != NULL)
474 		array_free(x->profiles);
475 	FREE_AND_NULL(x->comment);
476 	FREE_AND_NULL(x->template);
477 	FREE_AND_NULL(x->to);
478 	FREE_AND_NULL(x->from);
479 
480 	xfree(x);
481 
482 	return start;
483 }
484 
limits_ll_free(struct LIMITS_LIST_LIST * x)485 void limits_ll_free(struct LIMITS_LIST_LIST *x)
486 {
487 	struct LIMITS_LIST_LIST *tmp;
488 
489 	while (x != NULL) {
490 		tmp = x->next;
491 
492 		if (x->profiles != NULL)
493 			array_free(x->profiles);
494 		FREE_AND_NULL(x->comment);
495 		FREE_AND_NULL(x->template);
496 		FREE_AND_NULL(x->to);
497 		FREE_AND_NULL(x->from);
498 
499 		xfree(x);
500 
501 		x = tmp;
502 	}
503 }
504 
limits_free(LIMITS_LIST * limits_list)505 void limits_free(LIMITS_LIST * limits_list)
506 {
507 	if (!limits_list)
508 		return;
509 
510 	limits_ll_free(limits_list->limits_list);
511 
512 	pthread_rwlock_destroy(&limits_list->lock);
513 
514 	xfree(limits_list);
515 }
516 
limits_check(LIMITS_LIST * limits_list,CONNECTION * connection)517 struct LIMITS_LIST_LIST *limits_check(LIMITS_LIST * limits_list, CONNECTION * connection)
518 {
519 	struct LIMITS_LIST_LIST *ll, *match = NULL;
520 	time_t curtime;
521 	struct tm lt;
522 
523 	/* caller must always unlock this */
524 	pthread_rwlock_rdlock(&limits_list->lock);
525 
526 	if (!limits_list || (connection->bypass & FEATURE_LIMITS))
527 		return NULL;
528 
529 	curtime = time(NULL);
530 	localtime_r(&curtime, &lt);
531 
532 	if (limits_list->enabled == FALSE)
533 		return NULL;
534 
535 	for (ll = limits_list->limits_list; ll; ll = ll->next) {
536 		if (ll->enabled == FALSE)
537 			continue;
538 
539 		if (!profile_find(connection->profiles, ll->profiles))
540 			continue;
541 
542 		if (ll->from != NULL && ll->to != NULL) {
543 			if (ll->flags & LIMIT_ABSOLUTETIME) {
544 				if (!in_absolutetimerange(&lt, ll->from, ll->to))
545 					continue;
546 			} else {
547 				if (!in_alltimerange(&lt, ll->from, ll->to))
548 					continue;
549 			}
550 		}
551 
552 		match = ll;
553 	}
554 
555 	return match;
556 }
557 
limits_update(LIMITS_LIST * limits_list,CONNECTION * connection)558 void limits_update(LIMITS_LIST * limits_list, CONNECTION * connection)
559 {
560 	struct LIMITS_LIST_LIST *ll;
561 	time_t curtime;
562 	struct tm lt;
563 
564 	if (!limits_list || (connection->bypass & FEATURE_LIMITS))
565 		return;
566 
567 	curtime = time(NULL);
568 	localtime_r(&curtime, &lt);
569 
570 	pthread_rwlock_rdlock(&limits_list->lock);
571 
572 	if (limits_list->enabled == FALSE) {
573 		pthread_rwlock_unlock(&limits_list->lock);
574 
575 		return;
576 	}
577 
578 	for (ll = limits_list->limits_list; ll; ll = ll->next) {
579 		if (ll->enabled == FALSE)
580 			continue;
581 
582 		if (!profile_find(connection->profiles, ll->profiles))
583 			continue;
584 
585 		if (ll->from != NULL && ll->to != NULL) {
586 			if (ll->flags & LIMIT_ABSOLUTETIME) {
587 				if (!in_absolutetimerange(&lt, ll->from, ll->to))
588 					continue;
589 			} else {
590 				if (!in_alltimerange(&lt, ll->from, ll->to))
591 					continue;
592 			}
593 		}
594 
595 		if (ll->maxbytes != 0 && (connection->cachemap == NULL || (connection->flags & CONNECTION_CACHING) || (ll->flags & LIMIT_CACHE))) ll->n_bytes += connection->transferred;
596 		if (ll->maxrequests != 0) ll->n_requests++;
597 	}
598 
599 	pthread_rwlock_unlock(&limits_list->lock);
600 }
601 
602 
limits_reset(LIMITS_LIST * limits_list)603 void limits_reset(LIMITS_LIST * limits_list)
604 {
605 	struct LIMITS_LIST_LIST *ll;
606 	time_t curtime;
607 	struct tm lt;
608 
609 	if (!limits_list)
610 		return;
611 
612 	curtime = time(NULL);
613 	localtime_r(&curtime, &lt);
614 
615 	pthread_rwlock_rdlock(&limits_list->lock);
616 
617 	if (limits_list->enabled == FALSE) {
618 		pthread_rwlock_unlock(&limits_list->lock);
619 
620 		return;
621 	}
622 
623 	for (ll = limits_list->limits_list; ll; ll = ll->next) {
624 		if (ll->enabled == FALSE)
625 			continue;
626 
627 		if (ll->n_bytes == 0 && ll->n_requests == 0) continue;
628 
629 		if (ll->from != NULL && ll->to != NULL) {
630 			if (ll->flags & LIMIT_ABSOLUTETIME) {
631 				if (in_absolutetimerange(&lt, ll->from, ll->to))
632 					continue;
633 			} else {
634 				if (in_alltimerange(&lt, ll->from, ll->to))
635 					continue;
636 			}
637 		} else continue;
638 
639 		/* ok, we are outside the time range this entry applies to, we can reset the
640 		   byte and request counter */
641 		ll->n_bytes = ll->n_requests = 0;
642 	}
643 
644 	pthread_rwlock_unlock(&limits_list->lock);
645 }
646 
647 
648