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