1 /*
2 Copyright (C) 1997-2001 Id Software, Inc.
3
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
13 See the 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
21 #include "g_local.h"
22
23
Svcmd_Test_f(void)24 void Svcmd_Test_f (void)
25 {
26 gi.cprintf (NULL, PRINT_HIGH, "Svcmd_Test_f()\n");
27 }
28
29 /*
30 ==============================================================================
31
32 PACKET FILTERING
33
34
35 You can add or remove addresses from the filter list with:
36
37 addip <ip>
38 removeip <ip>
39
40 The ip address is specified in dot format, and any unspecified digits will match any value, so you can specify an entire class C network with "addip 192.246.40".
41
42 Removeip will only remove an address specified exactly the same way. You cannot addip a subnet, then removeip a single host.
43
44 listip
45 Prints the current list of filters.
46
47 writeip
48 Dumps "addip <ip>" commands to listip.cfg so it can be execed at a later date. The filter lists are not saved and restored by default, because I beleive it would cause too much confusion.
49
50 filterban <0 or 1>
51
52 If 1 (the default), then ip addresses matching the current list will be prohibited from entering the game. This is the default setting.
53
54 If 0, then only addresses matching the list will be allowed. This lets you easily set up a private game, or a game that only allows players from your local network.
55
56
57 ==============================================================================
58 */
59
60 typedef struct
61 {
62 unsigned mask;
63 unsigned compare;
64 } ipfilter_t;
65
66 #define MAX_IPFILTERS 1024
67
68 ipfilter_t ipfilters[MAX_IPFILTERS];
69 int numipfilters;
70
71 /*
72 =================
73 StringToFilter
74 =================
75 */
StringToFilter(char * s,ipfilter_t * f)76 static qboolean StringToFilter (char *s, ipfilter_t *f)
77 {
78 char num[128];
79 int i, j;
80 byte b[4];
81 byte m[4];
82
83 for (i=0 ; i<4 ; i++)
84 {
85 b[i] = 0;
86 m[i] = 0;
87 }
88
89 for (i=0 ; i<4 ; i++)
90 {
91 if (*s < '0' || *s > '9')
92 {
93 gi.cprintf(NULL, PRINT_HIGH, "Bad filter address: %s\n", s);
94 return false;
95 }
96
97 j = 0;
98 while (*s >= '0' && *s <= '9')
99 {
100 num[j++] = *s++;
101 }
102 num[j] = 0;
103 b[i] = atoi(num);
104 if (b[i] != 0)
105 m[i] = 255;
106
107 if (!*s)
108 break;
109 s++;
110 }
111
112 f->mask = *(unsigned *)m;
113 f->compare = *(unsigned *)b;
114
115 return true;
116 }
117
118 /*
119 =================
120 SV_FilterPacket
121 =================
122 */
SV_FilterPacket(char * from)123 qboolean SV_FilterPacket (char *from)
124 {
125 int i;
126 unsigned in;
127 byte m[4];
128 char *p;
129
130 i = 0;
131 p = from;
132 while (*p && i < 4) {
133 m[i] = 0;
134 while (*p >= '0' && *p <= '9') {
135 m[i] = m[i]*10 + (*p - '0');
136 p++;
137 }
138 if (!*p || *p == ':')
139 break;
140 i++, p++;
141 }
142
143 in = *(unsigned *)m;
144
145 for (i=0 ; i<numipfilters ; i++)
146 if ( (in & ipfilters[i].mask) == ipfilters[i].compare)
147 return (int)filterban->value;
148
149 return (int)!filterban->value;
150 }
151
152
153 /*
154 =================
155 SV_AddIP_f
156 =================
157 */
SVCmd_AddIP_f(void)158 void SVCmd_AddIP_f (void)
159 {
160 int i;
161
162 if (gi.argc() < 3) {
163 gi.cprintf(NULL, PRINT_HIGH, "Usage: addip <ip-mask>\n");
164 return;
165 }
166
167 for (i=0 ; i<numipfilters ; i++)
168 if (ipfilters[i].compare == 0xffffffff)
169 break; // free spot
170 if (i == numipfilters)
171 {
172 if (numipfilters == MAX_IPFILTERS)
173 {
174 gi.cprintf (NULL, PRINT_HIGH, "IP filter list is full\n");
175 return;
176 }
177 numipfilters++;
178 }
179
180 if (!StringToFilter (gi.argv(2), &ipfilters[i]))
181 ipfilters[i].compare = 0xffffffff;
182 }
183
184 /*
185 =================
186 SV_RemoveIP_f
187 =================
188 */
SVCmd_RemoveIP_f(void)189 void SVCmd_RemoveIP_f (void)
190 {
191 ipfilter_t f;
192 int i, j;
193
194 if (gi.argc() < 3) {
195 gi.cprintf(NULL, PRINT_HIGH, "Usage: sv removeip <ip-mask>\n");
196 return;
197 }
198
199 if (!StringToFilter (gi.argv(2), &f))
200 return;
201
202 for (i=0 ; i<numipfilters ; i++)
203 if (ipfilters[i].mask == f.mask
204 && ipfilters[i].compare == f.compare)
205 {
206 for (j=i+1 ; j<numipfilters ; j++)
207 ipfilters[j-1] = ipfilters[j];
208 numipfilters--;
209 gi.cprintf (NULL, PRINT_HIGH, "Removed.\n");
210 return;
211 }
212 gi.cprintf (NULL, PRINT_HIGH, "Didn't find %s.\n", gi.argv(2));
213 }
214
215 /*
216 =================
217 SV_ListIP_f
218 =================
219 */
SVCmd_ListIP_f(void)220 void SVCmd_ListIP_f (void)
221 {
222 int i;
223 byte b[4];
224
225 gi.cprintf (NULL, PRINT_HIGH, "Filter list:\n");
226 for (i=0 ; i<numipfilters ; i++)
227 {
228 *(unsigned *)b = ipfilters[i].compare;
229 gi.cprintf (NULL, PRINT_HIGH, "%3i.%3i.%3i.%3i\n", b[0], b[1], b[2], b[3]);
230 }
231 }
232
233 /*
234 =================
235 SV_WriteIP_f
236 =================
237 */
SVCmd_WriteIP_f(void)238 void SVCmd_WriteIP_f (void)
239 {
240 FILE *f;
241 char name[MAX_OSPATH];
242 byte b[4];
243 int i;
244 cvar_t *game;
245
246 game = gi.cvar("game", "", 0);
247
248 if (!*game->string)
249 sprintf (name, "%s/listip.cfg", GAMEVERSION);
250 else
251 sprintf (name, "%s/listip.cfg", game->string);
252
253 gi.cprintf (NULL, PRINT_HIGH, "Writing %s.\n", name);
254
255 f = fopen (name, "wb");
256 if (!f)
257 {
258 gi.cprintf (NULL, PRINT_HIGH, "Couldn't open %s\n", name);
259 return;
260 }
261
262 fprintf(f, "set filterban %d\n", (int)filterban->value);
263
264 for (i=0 ; i<numipfilters ; i++)
265 {
266 *(unsigned *)b = ipfilters[i].compare;
267 fprintf (f, "sv addip %i.%i.%i.%i\n", b[0], b[1], b[2], b[3]);
268 }
269
270 fclose (f);
271 }
272
273 /*
274 =================
275 ServerCommand
276
277 ServerCommand will be called when an "sv" command is issued.
278 The game can issue gi.argc() / gi.argv() commands to get the rest
279 of the parameters
280 =================
281 */
ServerCommand(void)282 void ServerCommand (void)
283 {
284 char *cmd;
285
286 cmd = gi.argv(1);
287 if (Q_stricmp (cmd, "test") == 0)
288 Svcmd_Test_f ();
289 else if (Q_stricmp (cmd, "addip") == 0)
290 SVCmd_AddIP_f ();
291 else if (Q_stricmp (cmd, "removeip") == 0)
292 SVCmd_RemoveIP_f ();
293 else if (Q_stricmp (cmd, "listip") == 0)
294 SVCmd_ListIP_f ();
295 else if (Q_stricmp (cmd, "writeip") == 0)
296 SVCmd_WriteIP_f ();
297 else
298 gi.cprintf (NULL, PRINT_HIGH, "Unknown server command \"%s\"\n", cmd);
299 }
300
301