]> icculus.org git repositories - divverent/nexuiz.git/blob - data/qcsrc/server/ipban.qc
banning, kicking and banning in voting, some display extensions (kick votes show...
[divverent/nexuiz.git] / data / qcsrc / server / ipban.qc
1 #define BAN_MAX 64
2 float ban_loaded;
3 string ban_ip[BAN_MAX];
4 float ban_expire[BAN_MAX];
5 float ban_count;
6
7 string ban_ip1;
8 string ban_ip2;
9 string ban_ip3;
10 string ban_ip4;
11
12 void Ban_SaveBans()
13 {
14         string out;
15         float i;
16
17         if(!ban_loaded)
18                 return;
19
20         // version of list
21         out = "1";
22         for(i = 0; i < ban_count; ++i)
23         {
24                 if(time > ban_expire[i])
25                         continue;
26                 out = strcat(out, " ", ban_ip[i]);
27                 out = strcat(out, " ", ftos(ban_expire[i] - time));
28         }
29         cvar_set("g_banned_list", out);
30 }
31
32 float Ban_Delete(float i)
33 {
34         if(i < 0)
35                 return FALSE;
36         if(i >= ban_count)
37                 return FALSE;
38         if(ban_expire[i] == 0)
39                 return FALSE;
40         if(ban_expire[i] > 0)
41                 strunzone(ban_ip[i]);
42         ban_expire[i] = 0;
43         ban_ip[i] = "";
44         Ban_SaveBans();
45         return TRUE;
46 }
47
48 void Ban_LoadBans()
49 {
50         float i, n;
51         for(i = 0; i < ban_count; ++i)
52                 Ban_Delete(i);
53         ban_count = 0;
54         ban_loaded = TRUE;
55         n = tokenize(cvar_string("g_banned_list"));
56         if(stof(argv(0)) == 1)
57         {
58                 ban_count = (n - 1) / 2;
59                 for(i = 0; i < ban_count; ++i)
60                 {
61                         ban_ip[i] = strzone(argv(2*i+1));
62                         ban_expire[i] = time + stof(argv(2*i+2));
63                 }
64         }
65 }
66
67 void Ban_View()
68 {
69         float i;
70         string msg;
71         for(i = 0; i < ban_count; ++i)
72         {
73                 if(time > ban_expire[i])
74                         continue;
75                 msg = strcat("#", ftos(i), ": ");
76                 msg = strcat(msg, ban_ip[i], " is still banned for ");
77                 msg = strcat(msg, ftos(ban_expire[i] - time), " seconds");
78                 ServerConsoleEcho(msg, FALSE);
79         }
80 }
81
82 float Ban_GetClientIP(entity client)
83 {
84         float n;
85         n = tokenizebyseparator(client.netaddress, ".");
86         if(n != 4)
87                 return FALSE;
88         ban_ip1 = strcat1(argv(1));
89         ban_ip2 = strcat(ban_ip1, ".", argv(2));
90         ban_ip3 = strcat(ban_ip2, ".", argv(3));
91         ban_ip4 = strcat(ban_ip3, ".", argv(4));
92         return TRUE;
93 }
94
95 float Ban_IsClientBanned(entity client)
96 {
97         float i;
98         if(!ban_loaded)
99                 Ban_LoadBans();
100         if(!Ban_GetClientIP(client))
101                 return FALSE;
102         for(i = 0; i < ban_count; ++i)
103         {
104                 string s;
105                 if(time > ban_expire[i])
106                         continue;
107                 s = ban_ip[i];
108                 if(ban_ip1 == s) return TRUE;
109                 if(ban_ip2 == s) return TRUE;
110                 if(ban_ip3 == s) return TRUE;
111                 if(ban_ip4 == s) return TRUE;
112         }
113         return FALSE;
114 }
115
116 float Ban_Insert(string ip, float bantime)
117 {
118         float i;
119         float j;
120         float bestscore;
121         // already banned?
122         for(i = 0; i < ban_count; ++i)
123                 if(ban_ip[i] == ip)
124                         return FALSE;
125         // do we have a free slot?
126         for(i = 0; i < ban_count; ++i)
127                 if(time > ban_expire[i])
128                         break;
129         // no free slot? Then look for the one who would get unbanned next
130         if(i >= BAN_MAX)
131         {
132                 i = 0;
133                 bestscore = ban_expire[i];
134                 for(j = 1; j < ban_count; ++j)
135                 {
136                         if(ban_expire[j] < bestscore)
137                         {
138                                 i = j;
139                                 bestscore = ban_expire[i];
140                         }
141                 }
142         }
143         // if we replace someone, will we be banned longer than him (so long-term
144         // bans never get overridden by short-term bans)
145         if(ban_expire[i] > time + bantime)
146                 return FALSE;
147         // okay, insert our new victim as i
148         Ban_Delete(i);
149         ServerConsoleEcho(strcat(ip, " has been banned for ", ftos(bantime), " seconds"), FALSE);
150         ban_expire[i] = time + bantime;
151         ban_ip[i] = strzone(ip);
152         ban_count = max(ban_count, i + 1);
153
154         Ban_SaveBans();
155
156         return TRUE;
157 }
158
159 void Ban_KickBanClient(entity client, float bantime, float masksize)
160 {
161         if(!Ban_GetClientIP(client))
162         {
163                 dropclient(client);
164                 return;
165         }
166         // now ban him
167         switch(masksize)
168         {
169                 case 1:
170                         Ban_Insert(ban_ip1, bantime);
171                         break;
172                 case 2:
173                         Ban_Insert(ban_ip2, bantime);
174                         break;
175                 case 3:
176                         Ban_Insert(ban_ip3, bantime);
177                         break;
178                 default:
179                         Ban_Insert(ban_ip4, bantime);
180                         break;
181         }
182         // and kick him
183         dropclient(client);
184 }
185
186 float GameCommand_Ban(string command)
187 {
188         float argc;
189         float bantime;
190         entity client;
191         float entno;
192         float masksize;
193
194         argc = tokenize(command);
195         if(argv(0) == "help")
196         {
197                 print("  kickban # n m p - kickban player n for m seconds, using mask size p (1 to 4)\n");
198                 print("  ban ip m - ban an IP or range (incomplete IP, like 1.2.3) for m seconds\n");
199                 print("  bans - list all existing bans\n");
200                 print("  unban n - delete the entry #n from the bans list\n");
201                 return TRUE;
202         }
203         if(argv(0) == "kickban")
204         {
205                 if(argc >= 3)
206                 {
207                         entno = stof(argv(2));
208                         if(entno > maxclients || entno < 1)
209                                 return TRUE;
210                         for(client = world; entno > 0; --entno, client = nextent(client))
211                                 ;
212                         if(argc >= 4)
213                                 bantime = stof(argv(3));
214                         else
215                                 bantime = cvar("g_ban_default_bantime");
216                         if(argc >= 5)
217                                 masksize = stof(argv(4));
218                         else
219                                 masksize = cvar("g_ban_default_masksize");
220                         Ban_KickBanClient(client, bantime, masksize);
221                         return TRUE;
222                 }
223         }
224         else if(argv(0) == "ban")
225         {
226                 if(argc >= 2)
227                 {
228                         string ip;
229                         ip = argv(1);
230                         if(argc >= 3)
231                                 bantime = stof(argv(2));
232                         else
233                                 bantime = cvar("g_ban_default_bantime");
234                         Ban_Insert(ip, bantime);
235                         return TRUE;
236                 }
237         }
238         else if(argv(0) == "bans")
239         {
240                 Ban_View();
241                 return TRUE;
242         }
243         else if(argv(0) == "unban")
244         {
245                 if(argc >= 2)
246                 {
247                         float who;
248                         who = stof(argv(1));
249                         Ban_Delete(who);
250                         return TRUE;
251                 }
252         }
253         return FALSE;
254 }