File: game\g_svcmds.c

    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 
  301