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