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