File: flood.c

package info (click to toggle)
ircii 20210328-2
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 5,644 kB
  • sloc: ansic: 42,273; makefile: 860; sh: 524; perl: 348
file content (128 lines) | stat: -rw-r--r-- 2,810 bytes parent folder | download | duplicates (5)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
/*
 * flood.c: handle channel flooding. 
 *
 * This attempts to give you some protection from flooding.  Basically, it keeps
 * track of how far apart (timewise) messages come in from different people.
 * If a single nickname sends more than 3 messages in a row in under a
 * second, this is considered flooding.  It then activates the ON FLOOD with
 * the nickname and type (appropriate for use with IGNORE). 
 *
 * Thanks to Tomi Ollila <f36664r@puukko.hut.fi> for this one. 
 */

#include "irc.h"
IRCII_RCSID("@(#)$eterna: flood.c,v 1.22 2014/01/31 12:35:57 mrg Exp $");

#include "hook.h"
#include "ircaux.h"
#include "ignore.h"
#include "flood.h"
#include "vars.h"
#include "output.h"

static	char	*ignore_types[NUMBER_OF_FLOODS] =
{
	"MSG",
	"PUBLIC",
	"NOTICE",
	"WALL",
	"WALLOP"
};

typedef struct flood_stru
{
	u_char	*nick;
	int	type;
	u_char	flood;
	long	cnt;
	time_t	start;
}	Flooding;

static	Flooding *flood = NULL;

/*
 * check_flooding: This checks for message flooding of the type specified for
 * the given nickname.  This is described above.  This will return 0 if no
 * flooding took place, or flooding is not being monitored from a certain
 * person.  It will return 1 if flooding is being check for someone and an ON
 * FLOOD is activated. 
 *
 * NOTE:  flood's are never freed.
 */
int
check_flooding(u_char *nick, u_char *to, int type, u_char *line)
{
	static	int	users = 0,
			pos = 0;
	int	i;
	time_t	flood_time,
	diff;
	Flooding *tmp;

	if (users != get_int_var(FLOOD_USERS_VAR))
	{
		if ((users = get_int_var(FLOOD_USERS_VAR)) == 0)
			return(1);
		if (flood)
			flood = new_realloc(flood, sizeof(*flood) * users);
		else
			flood = new_malloc(sizeof(*flood) * users);
		for (i = 0; i < users; i++)
		{
			flood[i].nick = 0;
			flood[i].cnt = 0;
			flood[i].flood = 0;
		}
	}
	if (users == 0)
		return (1);
	for (i = 0; i < users; i++)
	{
		if (flood[i].nick && *(flood[i].nick))
		{
			if ((my_stricmp(nick, flood[i].nick) == 0) &&
					(type == flood[i].type))
				break;
		}
	}
	flood_time = time(0);
	if (i == users)
	{
		pos = (pos + 1) % users;
		tmp = &(flood[pos]);
		tmp->nick = 0;
		malloc_strcpy(&tmp->nick, nick);
		tmp->type = type;
		tmp->cnt = 1;
		tmp->start = flood_time;
		tmp->flood = 0;
		return (1);
	}
	else
		tmp = &(flood[i]);
	tmp->cnt++;
	diff = flood_time - tmp->start;
	if (tmp->cnt > get_int_var(FLOOD_AFTER_VAR))
	{
		if ((diff == 0) || (tmp->cnt / diff) >
				get_int_var(FLOOD_RATE_VAR))
		{
			if (tmp->flood == 0)
			{
				if (get_int_var(FLOOD_WARNING_VAR))
					say("%s flooding detected from %s",
						ignore_types[type], nick);
				tmp->flood = 1;
			}
			return (do_hook(FLOOD_LIST, "%s %s %s %s", nick,
				to, ignore_types[type], line));
		}
		else
		{
			tmp->flood = 0;
			tmp->cnt = 1;
			tmp->start = flood_time;
		}
	}
	return (1);
}