codemp/game/g_svcmds.c

Go to the documentation of this file.
00001 // Copyright (C) 1999-2000 Id Software, Inc.
00002 //
00003 
00004 // this file holds commands that can be executed by the server console, but not remote clients
00005 
00006 #include "g_local.h"
00007 
00008 
00009 /*
00010 ==============================================================================
00011 
00012 PACKET FILTERING
00013  
00014 
00015 You can add or remove addresses from the filter list with:
00016 
00017 addip <ip>
00018 removeip <ip>
00019 
00020 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".
00021 
00022 Removeip will only remove an address specified exactly the same way.  You cannot addip a subnet, then removeip a single host.
00023 
00024 listip
00025 Prints the current list of filters.
00026 
00027 g_filterban <0 or 1>
00028 
00029 If 1 (the default), then ip addresses matching the current list will be prohibited from entering the game.  This is the default setting.
00030 
00031 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.
00032 
00033 
00034 ==============================================================================
00035 */
00036 
00037 // extern       vmCvar_t        g_banIPs;
00038 // extern       vmCvar_t        g_filterBan;
00039 
00040 
00041 typedef struct ipFilter_s
00042 {
00043         unsigned        mask;
00044         unsigned        compare;
00045 } ipFilter_t;
00046 
00047 // VVFIXME - We don't need this at all, but this is the quick way.
00048 #ifdef _XBOX
00049 #define MAX_IPFILTERS   1
00050 #else
00051 #define MAX_IPFILTERS   1024
00052 #endif
00053 
00054 static ipFilter_t       ipFilters[MAX_IPFILTERS];
00055 static int                      numIPFilters;
00056 
00057 /*
00058 =================
00059 StringToFilter
00060 =================
00061 */
00062 static qboolean StringToFilter (char *s, ipFilter_t *f)
00063 {
00064         char    num[128];
00065         int             i, j;
00066         byte    b[4];
00067         byte    m[4];
00068         
00069         for (i=0 ; i<4 ; i++)
00070         {
00071                 b[i] = 0;
00072                 m[i] = 0;
00073         }
00074         
00075         for (i=0 ; i<4 ; i++)
00076         {
00077                 if (*s < '0' || *s > '9')
00078                 {
00079                         G_Printf( "Bad filter address: %s\n", s );
00080                         return qfalse;
00081                 }
00082                 
00083                 j = 0;
00084                 while (*s >= '0' && *s <= '9')
00085                 {
00086                         num[j++] = *s++;
00087                 }
00088                 num[j] = 0;
00089                 b[i] = atoi(num);
00090                 if (b[i] != 0)
00091                         m[i] = 255;
00092 
00093                 if (!*s)
00094                         break;
00095                 s++;
00096         }
00097         
00098         f->mask = *(unsigned *)m;
00099         f->compare = *(unsigned *)b;
00100         
00101         return qtrue;
00102 }
00103 
00104 /*
00105 =================
00106 UpdateIPBans
00107 =================
00108 */
00109 static void UpdateIPBans (void)
00110 {
00111         byte    b[4];
00112         int             i;
00113         char    iplist[MAX_INFO_STRING];
00114 
00115         *iplist = 0;
00116         for (i = 0 ; i < numIPFilters ; i++)
00117         {
00118                 if (ipFilters[i].compare == 0xffffffff)
00119                         continue;
00120 
00121                 *(unsigned *)b = ipFilters[i].compare;
00122                 Com_sprintf( iplist + strlen(iplist), sizeof(iplist) - strlen(iplist), 
00123                         "%i.%i.%i.%i ", b[0], b[1], b[2], b[3]);
00124         }
00125 
00126         trap_Cvar_Set( "g_banIPs", iplist );
00127 }
00128 
00129 /*
00130 =================
00131 G_FilterPacket
00132 =================
00133 */
00134 qboolean G_FilterPacket (char *from)
00135 {
00136         byte                    m[4];// = {'\0','\0','\0','\0'};
00137         int                             i = 0;
00138         unsigned int    in;
00139         char                    *p;
00140 
00141         while (i < 4)
00142         {
00143                 m[i] = 0;
00144                 i++;
00145         }
00146 
00147         i = 0;
00148         p = from;
00149         while (*p && i < 4) {
00150                 while (*p >= '0' && *p <= '9') {
00151                         m[i] = m[i]*10 + (*p - '0');
00152                         p++;
00153                 }
00154                 if (!*p || *p == ':')
00155                         break;
00156                 i++, p++;
00157         }
00158         
00159         in = *(unsigned int *)m;
00160 
00161         for (i=0 ; i<numIPFilters ; i++)
00162                 if ( (in & ipFilters[i].mask) == ipFilters[i].compare)
00163                         return g_filterBan.integer != 0;
00164 
00165         return g_filterBan.integer == 0;
00166 }
00167 
00168 /*
00169 =================
00170 AddIP
00171 =================
00172 */
00173 static void AddIP( char *str )
00174 {
00175         int             i;
00176 
00177         for (i = 0 ; i < numIPFilters ; i++)
00178                 if (ipFilters[i].compare == 0xffffffff)
00179                         break;          // free spot
00180         if (i == numIPFilters)
00181         {
00182                 if (numIPFilters == MAX_IPFILTERS)
00183                 {
00184                         G_Printf ("IP filter list is full\n");
00185                         return;
00186                 }
00187                 numIPFilters++;
00188         }
00189         
00190         if (!StringToFilter (str, &ipFilters[i]))
00191                 ipFilters[i].compare = 0xffffffffu;
00192 
00193         UpdateIPBans();
00194 }
00195 
00196 /*
00197 =================
00198 G_ProcessIPBans
00199 =================
00200 */
00201 void G_ProcessIPBans(void) 
00202 {
00203         char *s, *t;
00204         char            str[MAX_TOKEN_CHARS];
00205 
00206         Q_strncpyz( str, g_banIPs.string, sizeof(str) );
00207 
00208         for (t = s = g_banIPs.string; *t; /* */ ) {
00209                 s = strchr(s, ' ');
00210                 if (!s)
00211                         break;
00212                 while (*s == ' ')
00213                         *s++ = 0;
00214                 if (*t)
00215                         AddIP( t );
00216                 t = s;
00217         }
00218 }
00219 
00220 
00221 /*
00222 =================
00223 Svcmd_AddIP_f
00224 =================
00225 */
00226 void Svcmd_AddIP_f (void)
00227 {
00228         char            str[MAX_TOKEN_CHARS];
00229 
00230         if ( trap_Argc() < 2 ) {
00231                 G_Printf("Usage:  addip <ip-mask>\n");
00232                 return;
00233         }
00234 
00235         trap_Argv( 1, str, sizeof( str ) );
00236 
00237         AddIP( str );
00238 
00239 }
00240 
00241 /*
00242 =================
00243 Svcmd_RemoveIP_f
00244 =================
00245 */
00246 void Svcmd_RemoveIP_f (void)
00247 {
00248         ipFilter_t      f;
00249         int                     i;
00250         char            str[MAX_TOKEN_CHARS];
00251 
00252         if ( trap_Argc() < 2 ) {
00253                 G_Printf("Usage:  sv removeip <ip-mask>\n");
00254                 return;
00255         }
00256 
00257         trap_Argv( 1, str, sizeof( str ) );
00258 
00259         if (!StringToFilter (str, &f))
00260                 return;
00261 
00262         for (i=0 ; i<numIPFilters ; i++) {
00263                 if (ipFilters[i].mask == f.mask &&
00264                         ipFilters[i].compare == f.compare) {
00265                         ipFilters[i].compare = 0xffffffffu;
00266                         G_Printf ("Removed.\n");
00267 
00268                         UpdateIPBans();
00269                         return;
00270                 }
00271         }
00272 
00273         G_Printf ( "Didn't find %s.\n", str );
00274 }
00275 
00276 /*
00277 ===================
00278 Svcmd_EntityList_f
00279 ===================
00280 */
00281 void    Svcmd_EntityList_f (void) {
00282         int                     e;
00283         gentity_t               *check;
00284 
00285         check = g_entities+1;
00286         for (e = 1; e < level.num_entities ; e++, check++) {
00287                 if ( !check->inuse ) {
00288                         continue;
00289                 }
00290                 G_Printf("%3i:", e);
00291                 switch ( check->s.eType ) {
00292                 case ET_GENERAL:
00293                         G_Printf("ET_GENERAL          ");
00294                         break;
00295                 case ET_PLAYER:
00296                         G_Printf("ET_PLAYER           ");
00297                         break;
00298                 case ET_ITEM:
00299                         G_Printf("ET_ITEM             ");
00300                         break;
00301                 case ET_MISSILE:
00302                         G_Printf("ET_MISSILE          ");
00303                         break;
00304                 case ET_MOVER:
00305                         G_Printf("ET_MOVER            ");
00306                         break;
00307                 case ET_BEAM:
00308                         G_Printf("ET_BEAM             ");
00309                         break;
00310                 case ET_PORTAL:
00311                         G_Printf("ET_PORTAL           ");
00312                         break;
00313                 case ET_SPEAKER:
00314                         G_Printf("ET_SPEAKER          ");
00315                         break;
00316                 case ET_PUSH_TRIGGER:
00317                         G_Printf("ET_PUSH_TRIGGER     ");
00318                         break;
00319                 case ET_TELEPORT_TRIGGER:
00320                         G_Printf("ET_TELEPORT_TRIGGER ");
00321                         break;
00322                 case ET_INVISIBLE:
00323                         G_Printf("ET_INVISIBLE        ");
00324                         break;
00325                 case ET_NPC:
00326                         G_Printf("ET_NPC              ");
00327                         break;
00328                 default:
00329                         G_Printf("%3i                 ", check->s.eType);
00330                         break;
00331                 }
00332 
00333                 if ( check->classname ) {
00334                         G_Printf("%s", check->classname);
00335                 }
00336                 G_Printf("\n");
00337         }
00338 }
00339 
00340 gclient_t       *ClientForString( const char *s ) {
00341         gclient_t       *cl;
00342         int                     i;
00343         int                     idnum;
00344 
00345         // numeric values are just slot numbers
00346         if ( s[0] >= '0' && s[0] <= '9' ) {
00347                 idnum = atoi( s );
00348                 if ( idnum < 0 || idnum >= level.maxclients ) {
00349                         Com_Printf( "Bad client slot: %i\n", idnum );
00350                         return NULL;
00351                 }
00352 
00353                 cl = &level.clients[idnum];
00354                 if ( cl->pers.connected == CON_DISCONNECTED ) {
00355                         G_Printf( "Client %i is not connected\n", idnum );
00356                         return NULL;
00357                 }
00358                 return cl;
00359         }
00360 
00361         // check for a name match
00362         for ( i=0 ; i < level.maxclients ; i++ ) {
00363                 cl = &level.clients[i];
00364                 if ( cl->pers.connected == CON_DISCONNECTED ) {
00365                         continue;
00366                 }
00367                 if ( !Q_stricmp( cl->pers.netname, s ) ) {
00368                         return cl;
00369                 }
00370         }
00371 
00372         G_Printf( "User %s is not on the server\n", s );
00373 
00374         return NULL;
00375 }
00376 
00377 /*
00378 ===================
00379 Svcmd_ForceTeam_f
00380 
00381 forceteam <player> <team>
00382 ===================
00383 */
00384 void    Svcmd_ForceTeam_f( void ) {
00385         gclient_t       *cl;
00386         char            str[MAX_TOKEN_CHARS];
00387 
00388         // find the player
00389         trap_Argv( 1, str, sizeof( str ) );
00390         cl = ClientForString( str );
00391         if ( !cl ) {
00392                 return;
00393         }
00394 
00395         // set the team
00396         trap_Argv( 2, str, sizeof( str ) );
00397         SetTeam( &g_entities[cl - level.clients], str );
00398 }
00399 
00400 char    *ConcatArgs( int start );
00401 
00402 /*
00403 =================
00404 ConsoleCommand
00405 
00406 =================
00407 */
00408 qboolean        ConsoleCommand( void ) {
00409         char    cmd[MAX_TOKEN_CHARS];
00410 
00411         trap_Argv( 0, cmd, sizeof( cmd ) );
00412 
00413         if ( Q_stricmp (cmd, "entitylist") == 0 ) {
00414                 Svcmd_EntityList_f();
00415                 return qtrue;
00416         }
00417 
00418         if ( Q_stricmp (cmd, "forceteam") == 0 ) {
00419                 Svcmd_ForceTeam_f();
00420                 return qtrue;
00421         }
00422 
00423         if (Q_stricmp (cmd, "game_memory") == 0) {
00424                 Svcmd_GameMem_f();
00425                 return qtrue;
00426         }
00427 
00428         if (Q_stricmp (cmd, "addbot") == 0) {
00429                 Svcmd_AddBot_f();
00430                 return qtrue;
00431         }
00432 
00433         if (Q_stricmp (cmd, "botlist") == 0) {
00434                 Svcmd_BotList_f();
00435                 return qtrue;
00436         }
00437 
00438 /*      if (Q_stricmp (cmd, "abort_podium") == 0) {
00439                 Svcmd_AbortPodium_f();
00440                 return qtrue;
00441         }
00442 */
00443         if (Q_stricmp (cmd, "addip") == 0) {
00444                 Svcmd_AddIP_f();
00445                 return qtrue;
00446         }
00447 
00448         if (Q_stricmp (cmd, "removeip") == 0) {
00449                 Svcmd_RemoveIP_f();
00450                 return qtrue;
00451         }
00452 
00453         if (Q_stricmp (cmd, "listip") == 0) {
00454                 trap_SendConsoleCommand( EXEC_NOW, "g_banIPs\n" );
00455                 return qtrue;
00456         }
00457 
00458         if (g_dedicated.integer) {
00459                 if (Q_stricmp (cmd, "say") == 0) {
00460                         trap_SendServerCommand( -1, va("print \"server: %s\n\"", ConcatArgs(1) ) );
00461                         return qtrue;
00462                 }
00463                 // everything else will also be printed as a say command
00464                 trap_SendServerCommand( -1, va("print \"server: %s\n\"", ConcatArgs(0) ) );
00465                 return qtrue;
00466         }
00467 
00468         return qfalse;
00469 }
00470