g_svcmds.c (6075B)
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 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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