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