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 #ifdef HAVE_CONFIG_H
22 #include "config.h"
23 #endif
24
25 #include "server.h"
26
27 master_sv_t master_status[MAX_MASTERS]; // status of master servers
28
29 client_t *sv_client; // current client
30
31 cvar_t *sv_paused;
32 cvar_t *sv_timedemo;
33
34 cvar_t *sv_enforcetime;
35
36 cvar_t *timeout; // seconds without any message
37 cvar_t *zombietime; // seconds to sink messages after disconnect
38
39 cvar_t *rcon_password; // password for remote server commands
40
41 cvar_t *allow_download;
42 cvar_t *allow_download_players;
43 cvar_t *allow_download_models;
44 cvar_t *allow_download_sounds;
45 cvar_t *allow_download_maps;
46
47 cvar_t *sv_airaccelerate;
48
49 cvar_t *sv_joustmode;
50 cvar_t *sv_tactical;
51 cvar_t *sv_excessive;
52
53 cvar_t *sv_noreload; // don't reload level state when reentering
54
55 cvar_t *maxclients; // FIXME: rename sv_maxclients
56 cvar_t *sv_showclamp;
57
58 cvar_t *hostname;
59 cvar_t *public_server; // should heartbeats be sent
60
61 cvar_t *sv_reconnect_limit; // minimum seconds between connect messages
62
63 cvar_t *sv_ratelimit_status; //new security measures
64 cvar_t *sv_iplimit;
65
66 cvar_t *sv_downloadurl;
67
68 cvar_t *sv_iplogfile; // Log file by IP address
69
70 int sv_numbots;
71
72 void Master_Shutdown (void);
73
74 short ShortSwap (short l);
75
76 //============================================================================
77
78
79 /*
80 =====================
81 SV_LogEvent
82
83 Logs an event to the IP log.
84 =====================
85 */
SV_LogEvent(netadr_t address,const char * event,const char * name)86 static void SV_LogEvent( netadr_t address , const char * event , const char * name )
87 {
88 FILE * file;
89
90 if ( !( sv_iplogfile && sv_iplogfile->string[0] ) )
91 return;
92
93
94 file = fopen( sv_iplogfile->string , "a" );
95 if ( !file ) {
96 Com_DPrintf( "Failed to write to IP log file '%s'\n" , sv_iplogfile->string );
97 return;
98 }
99 fprintf( file , "%s\t%s\t%d\t%s\r\n" , NET_AdrToString(address) , event ,
100 ( name != NULL ) , ( name != NULL ) ? name : "" );
101 fclose( file );
102 }
103
104
105
106
107 /*
108 =====================
109 SV_DropClient
110
111 Called when the player is totally leaving the server, either willingly
112 or unwillingly. This is NOT called if the entire server is quiting
113 or crashing.
114 =====================
115 */
SV_DropClient(client_t * drop)116 void SV_DropClient (client_t *drop)
117 {
118 // add the disconnect
119
120 MSG_WriteByte (&drop->netchan.message, svc_disconnect);
121
122 if (drop->state == cs_spawned)
123 {
124 // call the prog function for removing a client
125 // this will remove the body, among other things
126 ge->ClientDisconnect (drop->edict);
127 }
128
129 if (drop->download)
130 {
131 FS_FreeFile (drop->download);
132 drop->download = NULL;
133 }
134
135 SV_LogEvent( drop->netchan.remote_address , "DCN" , drop->name );
136 drop->state = cs_zombie; // become free in a few seconds
137 drop->name[0] = 0;
138 }
139
140
141
142 /*
143 ==============================================================================
144
145 CONNECTIONLESS COMMANDS
146
147 ==============================================================================
148 */
149
150 /*
151 ===============
152 SV_StatusString
153
154 Builds the string that is sent as heartbeats and status replies
155 ===============
156 */
SV_StatusString(void)157 char *SV_StatusString (void)
158 {
159 static char status[MAX_MSGLEN - 16]; // static buffer for the status string
160 qboolean msg_overflow = false;
161
162 char player[MAX_INFO_STRING];
163 client_t *cl;
164 size_t count;
165
166 // server info string. MAX_INFO_STRING is always < sizeof(status)
167 strcpy( status, Cvar_Serverinfo() );
168 strcat( status, "\n" );
169
170 // real player score info
171 for ( cl=svs.clients, count=maxclients->integer ; count-- ; cl++ )
172 {
173 if (cl->state == cs_connected || cl->state == cs_spawned )
174 {
175 /* send score of 0 for spectators and players not yet in game
176 * statistics program uses this data when polling for scores
177 */
178 int cl_score = 0;
179 if ( cl->state == cs_spawned
180 && cl->edict->client->ps.stats[STAT_SPECTATOR] == 0 )
181 {
182 cl_score = cl->edict->client->ps.stats[STAT_FRAGS];;
183 }
184 /*
185 * send color characters
186 * do not send actual ip addresses for security/privacy reasons
187 */
188 Com_sprintf( player, sizeof(player),
189 "%i %i \"%s\" \"127.0.0.1\"\n",
190 cl_score, cl->ping, cl->name);
191 if ( (strlen(status) + strlen(player) + 1) < sizeof(status) )
192 {
193 strncat( status, player, strlen(player) );
194 }
195 else
196 {
197 msg_overflow = true;
198 break;
199 }
200 }
201 }
202
203 // bot score info
204 if ( !msg_overflow )
205 {
206 for ( cl=svs.clients, count=maxclients->integer ; count-- ; cl++ )
207 {
208 size_t bot_count;
209 bot_count = cl->edict->client->ps.botnum;
210 if ( bot_count )
211 { // normally, first client contains the bot names and scores
212 bot_t* ps_bot;
213 for ( ps_bot = cl->edict->client->ps.bots ; bot_count-- ; ps_bot++ )
214 {
215 int bot_score = ps_bot->score;
216 Com_sprintf( player, sizeof(player),
217 "%i %i \"%s\" \"127.0.0.1\"\n",
218 bot_score,
219 0, // bot ping
220 ps_bot->name );
221 if ( (strlen(status) + strlen(player) + 1) < sizeof(status) )
222 {
223 strncat( status, player, strlen(player) );
224 }
225 else
226 {
227 msg_overflow = true;
228 break;
229 }
230 }
231 }
232 break;
233 }
234 }
235 if ( msg_overflow )
236 {
237 Com_DPrintf("SV_StatusString overflowed\n");
238 }
239
240 return status;
241 }
242
243 /*
244 ================
245 SVC_Status
246
247 Responds with all the info that qplug or qspy can see
248 ================
249 */
250 /*void SVC_Status (void)
251 {
252 Netchan_OutOfBandPrint (NS_SERVER, net_from, "print\n%s", SV_StatusString());
253 #if 0
254 Com_BeginRedirect (RD_PACKET, sv_outputbuf, SV_OUTPUTBUF_LENGTH, SV_FlushRedirect);
255 Com_Printf (SV_StatusString());
256 Com_EndRedirect ();
257 #endif
258 }*/
RateLimited(ratelimit_t * limit,int maxCount)259 static qboolean RateLimited (ratelimit_t *limit, int maxCount)
260 {
261 int diff;
262
263 diff = sv.time - limit->time;
264
265 //a new sampling period
266 if (diff > limit->period || diff < 0)
267 {
268 limit->time = sv.time;
269 limit->count = 0;
270 }
271 else
272 {
273 if (limit->count >= maxCount)
274 return true;
275 }
276
277 return false;
278 }
279
RateSample(ratelimit_t * limit)280 static void RateSample (ratelimit_t *limit)
281 {
282 int diff;
283
284 diff = sv.time - limit->time;
285
286 //a new sampling period
287 if (diff > limit->period || diff < 0)
288 {
289 limit->time = sv.time;
290 limit->count = 1;
291 }
292 else
293 {
294 limit->count++;
295 }
296 }
297
SVC_Status(void)298 static void SVC_Status (void)
299 {
300
301 RateSample (&svs.ratelimit_status);
302
303 if (RateLimited (&svs.ratelimit_status, sv_ratelimit_status->integer))
304 {
305 Com_DPrintf ("SVC_Status: Dropped status request from %s\n", NET_AdrToString (net_from));
306 return;
307 }
308
309 Netchan_OutOfBandPrint (NS_SERVER, net_from, "print\n%s", SV_StatusString());
310 }
311
312 /*
313 ================
314 SVC_Ack
315
316 ================
317 */
SVC_Ack(void)318 void SVC_Ack (void)
319 {
320 int i;
321 Com_Printf ("Ping acknowledge from %s\n", NET_AdrToString(net_from));
322 for ( i = 0 ; i < MAX_MASTERS ; i ++ ) {
323 if ( master_status[i].name[0] == 0 )
324 break;
325
326 if ( master_status[i].addr.port == 0 )
327 continue;
328
329 if ( NET_CompareAdr (master_status[i].addr, net_from) )
330 master_status[i].last_ping_ack = 2;
331 }
332 }
333
334 /*
335 ================
336 SVC_Info
337
338 Responds with short info for broadcast scans
339 The second parameter should be the current protocol version number.
340 ================
341 */
SVC_Info(void)342 void SVC_Info (void)
343 {
344 char string[64];
345 int i, count;
346 int version;
347 client_t *cl;
348
349 if (maxclients->integer == 1)
350 return; // ignore in single player
351
352 version = atoi (Cmd_Argv(1));
353
354 if (version != PROTOCOL_VERSION) {
355 Com_sprintf (string, sizeof(string), "%s: wrong version\n", hostname->string, sizeof(string));
356 //r1: return instead of sending another packet. prevents spoofed udp packet
357 // causing server <-> server info loops.
358 return;
359 }
360 else
361 {
362 count = 0;
363 for (i=0 ; i<maxclients->integer ; i++)
364 if (svs.clients[i].state >= cs_connected)
365 count++;
366
367 //bot score info
368 for (i=0 ; i<maxclients->integer ; i++)
369 {
370 cl = &svs.clients[i];
371 if(cl->edict->client->ps.botnum > 0)
372 {
373 count += cl->edict->client->ps.botnum; //add the bots
374 break;
375 }
376 }
377 //end bot score info
378
379 Com_sprintf (string, sizeof(string), "%16s %8s %2i/%2i\n", hostname->string, sv.name, count, maxclients->integer);
380 }
381
382 Netchan_OutOfBandPrint (NS_SERVER, net_from, "info\n%s", string);
383 }
384
385 /*
386 ================
387 SVC_Ping
388
389 Just responds with an acknowledgement
390 ================
391 */
SVC_Ping(void)392 void SVC_Ping (void)
393 {
394 Netchan_OutOfBandPrint (NS_SERVER, net_from, "ack");
395 }
396
SV_KickClient(client_t * cl,const char * reason,const char * cprintf)397 void SV_KickClient (client_t *cl, const char /*@null@*/*reason, const char /*@null@*/*cprintf)
398 {
399 if (reason && cl->state == cs_spawned && cl->name[0])
400 SV_BroadcastPrintf (PRINT_HIGH, "%s was dropped: %s\n", cl->name, reason);
401 if (cprintf)
402 SV_ClientPrintf (cl, PRINT_HIGH, "%s", cprintf);
403 Com_Printf ("Dropping %s, %s.\n", cl->name, reason ? reason : "SV_KickClient");
404 SV_DropClient (cl);
405 }
406
407 /*
408 =================
409 SVC_GetChallenge
410
411 Returns a challenge number that can be used
412 in a subsequent client_connect command.
413 We do this to prevent denial of service attacks that
414 flood the server with invalid connection IPs. With a
415 challenge, they must give a valid IP address.
416 =================
417 */
SVC_GetChallenge(void)418 void SVC_GetChallenge (void)
419 {
420 int i;
421 int oldest;
422 int oldestTime;
423
424 oldest = 0;
425 oldestTime = 0x7fffffff;
426
427 // see if we already have a challenge for this ip
428 for (i = 0 ; i < MAX_CHALLENGES ; i++)
429 {
430 if (NET_CompareBaseAdr (net_from, svs.challenges[i].adr))
431 break;
432 if (svs.challenges[i].time < oldestTime)
433 {
434 oldestTime = svs.challenges[i].time;
435 oldest = i;
436 }
437 }
438
439 if (i == MAX_CHALLENGES)
440 {
441 // overwrite the oldest
442 svs.challenges[oldest].challenge = rand() & 0x7fff;
443 svs.challenges[oldest].adr = net_from;
444 svs.challenges[oldest].time = curtime;
445 i = oldest;
446 }
447
448 // send it back
449 Netchan_OutOfBandPrint (NS_SERVER, net_from, "challenge %i", svs.challenges[i].challenge);
450 }
451
452 /*
453 ==================
454 SVC_DirectConnect
455
456 A connection request that did not come from the master
457 ==================
458 */
SVC_DirectConnect(void)459 void SVC_DirectConnect (void)
460 {
461 char userinfo[MAX_INFO_STRING];
462 netadr_t adr;
463 int i;
464 client_t *cl, *newcl;
465 client_t temp;
466 edict_t *ent;
467 int edictnum;
468 int version;
469 int qport;
470 int challenge;
471 int previousclients;
472 int botnum, botkick;
473
474 adr = net_from;
475
476 Com_DPrintf ("SVC_DirectConnect ()\n");
477
478 version = atoi(Cmd_Argv(1));
479 if (version != PROTOCOL_VERSION)
480 {
481 Netchan_OutOfBandPrint (NS_SERVER, adr, "print\nServer is protocol version %s\n", PROTOCOL_VERSION);
482 Com_DPrintf (" rejected connect from protocol version %i\n", version);
483 SV_LogEvent( adr , "RVR" , NULL );
484 return;
485 }
486
487 qport = atoi(Cmd_Argv(2));
488
489 challenge = atoi(Cmd_Argv(3));
490
491 //security, overflow fixes
492
493 //limit connections from a single IP
494 previousclients = 0;
495 for (i=0,cl=svs.clients ; i<maxclients->integer ; i++,cl++)
496 {
497 if (cl->state == cs_free)
498 continue;
499 if (NET_CompareBaseAdr (adr, cl->netchan.remote_address))
500 {
501 //zombies are less dangerous
502 if (cl->state == cs_zombie)
503 previousclients++;
504 else
505 previousclients += 2;
506 }
507 }
508
509 if (previousclients >= sv_iplimit->integer * 2)
510 {
511 Netchan_OutOfBandPrint (NS_SERVER, adr, "print\nToo many connections from your host.\n");
512 Com_DPrintf (" too many connections\n");
513 SV_LogEvent( adr , "R00" , NULL );
514 return;
515 }
516
517 // sku - reserve 32 bytes for the IP address
518 strncpy (userinfo, Cmd_Argv(4), sizeof(userinfo)-32);
519 userinfo[sizeof(userinfo) - 32] = 0;
520
521 //check it is not overflowed, save enough bytes for /ip/111.222.333.444:55555
522 if (strlen(userinfo) + 25 >= sizeof(userinfo)-1)
523 {
524 Com_DPrintf (" userinfo length exceeded\n");
525 Netchan_OutOfBandPrint (NS_SERVER, adr, "print\nUserinfo string length exceeded.\n");
526 SV_LogEvent( adr , "R01" , NULL );
527 return;
528 }
529 else if (!userinfo[0])
530 {
531 Com_DPrintf (" empty userinfo string\n");
532 Netchan_OutOfBandPrint (NS_SERVER, adr, "print\nBad userinfo string.\n");
533 SV_LogEvent( adr , "R02" , NULL );
534 return;
535 }
536
537 //block anyone trying to use the end-of-message-in-string exploit
538 if (strchr(userinfo, '\xFF'))
539 {
540 char *ptr;
541 ptr = strchr (userinfo, '\xFF');
542 ptr -= 8;
543 if (ptr < userinfo)
544 ptr = userinfo;
545 Netchan_OutOfBandPrint (NS_SERVER, adr, "print\nConnection refused due to attempted exploit!\n");
546 SV_LogEvent( adr , "R03" , NULL );
547 return;
548 }
549 if (Info_KeyExists (userinfo, "ip"))
550 {
551 char *p;
552 p = Info_ValueForKey(userinfo, "ip");
553 Com_Printf ("EXPLOIT: Client %s attempted to spoof IP address: %s\n", Info_ValueForKey (userinfo, "name"), NET_AdrToString(adr));
554 SV_LogEvent( adr , "R04" , NULL );
555 return;
556 }
557
558 // force the IP key/value pair so the game can filter based on ip
559 Info_SetValueForKey (userinfo, "ip", NET_AdrToString(net_from));
560
561 // attractloop servers are ONLY for local clients
562 if (sv.attractloop)
563 {
564 if (!NET_IsLocalAddress (adr))
565 {
566 Com_Printf ("Remote connect in attract loop. Ignored.\n");
567 Netchan_OutOfBandPrint (NS_SERVER, adr, "print\nConnection refused.\n");
568 SV_LogEvent( adr , "R05" , NULL );
569 return;
570 }
571 }
572
573 // see if the challenge is valid
574 if (!NET_IsLocalAddress (adr))
575 {
576 for (i=0 ; i<MAX_CHALLENGES ; i++)
577 {
578 if (NET_CompareBaseAdr (net_from, svs.challenges[i].adr))
579 {
580 if (challenge == svs.challenges[i].challenge)
581 break; // good
582 Netchan_OutOfBandPrint (NS_SERVER, adr, "print\nBad challenge.\n");
583 SV_LogEvent( adr , "R06" , NULL );
584 return;
585 }
586 }
587 if (i == MAX_CHALLENGES)
588 {
589 Netchan_OutOfBandPrint (NS_SERVER, adr, "print\nNo challenge for address.\n");
590 SV_LogEvent( adr , "R07" , NULL );
591 return;
592 }
593 }
594
595 newcl = &temp;
596 memset (newcl, 0, sizeof(client_t));
597
598 // if there is already a slot for this ip, reuse it
599 for (i=0,cl=svs.clients ; i<maxclients->integer ; i++,cl++)
600 {
601 if (cl->state == cs_free)
602 continue;
603
604 if (NET_CompareAdr (adr, cl->netchan.remote_address))
605 {
606
607 //r1: !! fix nasty bug where non-disconnected clients (from dropped disconnect
608 //packets) could be overwritten!
609 if (cl->state != cs_zombie)
610 {
611 Com_DPrintf (" client already found\n");
612 Netchan_OutOfBandPrint (NS_SERVER, adr, "print\nPlayer '%s' is already connected from %s.\n", cl->name, NET_AdrToString(adr));
613 SV_LogEvent( adr , "R08" , cl->name );
614 return;
615 }
616
617 if (!NET_IsLocalAddress (adr) && (svs.realtime - cl->lastconnect) < ((int)sv_reconnect_limit->integer * 1000))
618 {
619 Com_DPrintf ("%s:reconnect rejected : too soon\n", NET_AdrToString (adr));
620 SV_LogEvent( adr , "R09" , NULL );
621 return;
622 }
623 Com_Printf ("%s:reconnect\n", NET_AdrToString (adr));
624 SV_LogEvent( adr , "RCN" , NULL );
625
626 newcl = cl;
627 goto gotnewcl;
628 }
629 }
630
631 // find a client slot
632
633 //get number of bots
634 for (i=botnum=0 ; i<maxclients->integer ; i++)
635 {
636 cl = &svs.clients[i];
637 botnum = cl->edict->client->ps.botnum;
638 if(botnum > 0)
639 break;
640 }
641
642 //still need to reserve one slot
643 newcl = NULL;
644
645 //are we using botkickthreshold?
646 botkick = Cvar_VariableValue("sv_botkickthreshold");
647
648 //prevent client slot overwrites with bots rejoining after map change
649 if(botkick) {
650
651 if(botkick < sv_numbots)
652 botnum = botkick;
653 else
654 botnum = sv_numbots;
655 }
656
657 for (i=0,cl=svs.clients ; i<maxclients->integer-botnum; i++,cl++)
658 {
659 if (cl->state == cs_free)
660 {
661 newcl = cl;
662 break;
663 }
664 }
665 if (!newcl)
666 {
667 Netchan_OutOfBandPrint (NS_SERVER, adr, "print\nServer is full.\n");
668 Com_DPrintf ("Rejected a connection.\n");
669 SV_LogEvent( adr , "R10" , NULL );
670 return;
671 }
672 SV_LogEvent( adr , "NCN" , NULL );
673
674 gotnewcl:
675
676 // build a new connection
677 // accept the new client
678 // this is the only place a client_t is ever initialized
679 *newcl = temp;
680 sv_client = newcl;
681 edictnum = (newcl-svs.clients)+1;
682 ent = EDICT_NUM(edictnum);
683 newcl->edict = ent;
684 newcl->challenge = challenge; // save challenge for checksumming
685
686 // get the game a chance to reject this connection or modify the userinfo
687
688 if (!(ge->ClientConnect (ent, userinfo)))
689 {
690
691 if (*Info_ValueForKey (userinfo, "rejmsg"))
692 Netchan_OutOfBandPrint (NS_SERVER, adr, "print\n%s\nConnection refused.\n",
693 Info_ValueForKey (userinfo, "rejmsg"));
694 else
695 Netchan_OutOfBandPrint (NS_SERVER, adr, "print\nConnection refused.\n" );
696 SV_LogEvent( adr , "GRJ" , NULL );
697 Com_DPrintf ("Game rejected a connection.\n");
698 return;
699 }
700
701 // parse some info from the info strings
702 Q_strncpyz2( newcl->userinfo, userinfo, sizeof(newcl->userinfo) );
703 SV_UserinfoChanged (newcl);
704 SV_LogEvent( adr , "UUS" , newcl->name );
705
706 // send the connect packet to the client
707 Netchan_OutOfBandPrint(NS_SERVER, adr, "client_connect %s", sv_downloadurl->string);
708
709 Netchan_Setup (NS_SERVER, &newcl->netchan , adr, qport);
710
711 newcl->state = cs_connected;
712
713 SZ_Init (&newcl->datagram, newcl->datagram_buf, sizeof(newcl->datagram_buf) );
714 SZ_SetName (&newcl->datagram, va("Datagram buffer %s", NET_AdrToString(adr)), true);
715
716 newcl->datagram.allowoverflow = true;
717 newcl->lastmessage = svs.realtime; // don't timeout
718 newcl->lastconnect = svs.realtime;
719
720 ge->ForceExitIntermission ();
721 Cbuf_Execute ();
722 }
723
Rcon_Validate(void)724 int Rcon_Validate (void)
725 {
726 if (!strlen (rcon_password->string))
727 return 0;
728
729 if (strcmp (Cmd_Argv(1), rcon_password->string) )
730 return 0;
731
732 return 1;
733 }
734
735 /*
736 ===============
737 SVC_RemoteCommand
738
739 A client issued an rcon command.
740 Shift down the remaining args
741 Redirect all printfs
742 ===============
743 */
SVC_RemoteCommand(void)744 void SVC_RemoteCommand (void)
745 {
746 int i;
747 char remaining[1024];
748
749 i = Rcon_Validate ();
750
751 if (i == 0)
752 Com_Printf ("Bad rcon from %s:\n%s\n", NET_AdrToString (net_from), net_message.data+4);
753 else
754 Com_Printf ("Rcon from %s:\n%s\n", NET_AdrToString (net_from), net_message.data+4);
755
756 Com_BeginRedirect (RD_PACKET, sv_outputbuf, SV_OUTPUTBUF_LENGTH, SV_FlushRedirect);
757
758 if (!Rcon_Validate ())
759 {
760 Com_Printf ("Bad rcon_password.\n");
761 }
762 else
763 {
764 remaining[0] = 0;
765
766 for (i=2 ; i<Cmd_Argc() ; i++)
767 {
768 /* If spaces present in args, quote them in the remaining string */
769 if(strchr(Cmd_Argv(i), ' '))
770 {
771 strcat (remaining, "\"");
772 strcat (remaining, Cmd_Argv(i) );
773 strcat (remaining, "\"");
774 }
775 else
776 {
777 strcat (remaining, Cmd_Argv(i) );
778 }
779 strcat (remaining, " ");
780 }
781 if ( strncmp( remaining, "killserver", 10 ) )
782 { // not too surprising, rcon killserver does bad things
783 Cmd_ExecuteString (remaining);
784 }
785 else
786 {
787 Com_Printf("Cannot do that.\n");
788 }
789 }
790
791 Com_EndRedirect ();
792 }
793
794 /*
795 =================
796 SV_ConnectionlessPacket
797
798 A connectionless packet has four leading 0xff
799 characters to distinguish it from a game channel.
800 Clients that are in the game can still send
801 connectionless packets.
802 =================
803 */
SV_ConnectionlessPacket(void)804 void SV_ConnectionlessPacket (void)
805 {
806 char *s;
807 char *c;
808
809 //r1: make sure we never talk to ourselves
810 if (NET_IsLocalAddress (net_from) && !NET_IsLocalHost(&net_from) && ShortSwap(net_from.port) == server_port)
811 {
812 Com_DPrintf ("dropped %d byte connectionless packet from self! (spoofing attack?)\n", net_message.cursize);
813 return;
814 }
815
816
817 MSG_BeginReading (&net_message);
818 MSG_ReadLong (&net_message); // skip the -1 marker
819
820 s = MSG_ReadStringLine (&net_message);
821
822 Cmd_TokenizeString (s, false);
823
824 c = Cmd_Argv(0);
825 Com_DPrintf ("Packet %s : %s\n", NET_AdrToString(net_from), c);
826
827 if (!strcmp(c, "ping"))
828 SVC_Ping ();
829 else if (!strcmp(c, "ack"))
830 SVC_Ack ();
831 else if (!strcmp(c,"status"))
832 SVC_Status ();
833 else if (!strcmp(c,"info"))
834 SVC_Info ();
835 else if (!strcmp(c,"getchallenge"))
836 SVC_GetChallenge ();
837 else if (!strcmp(c,"connect"))
838 SVC_DirectConnect ();
839 else if (!strcmp(c, "rcon"))
840 SVC_RemoteCommand ();
841 else if (!strcmp(c, "teamgame")) {
842 Netchan_OutOfBandPrint (NS_SERVER, net_from, "teamgame %f", Cvar_VariableValue ("g_teamgame"));
843 } else
844 Com_Printf ("bad connectionless packet from %s:\n%s\n"
845 , NET_AdrToString (net_from), s);
846 }
847
848
849 //============================================================================
850
851 /*
852 ===================
853 SV_CalcPings
854
855 Updates the cl->ping variables
856 ===================
857 */
SV_CalcPings(void)858 void SV_CalcPings (void)
859 {
860 int i, j;
861 client_t *cl;
862 int total, count;
863
864 for (i=0 ; i<maxclients->integer ; i++)
865 {
866 cl = &svs.clients[i];
867 if (cl->state != cs_spawned )
868 continue;
869
870 #if 0
871 if (cl->lastframe > 0)
872 cl->frame_latency[sv.framenum&(LATENCY_COUNTS-1)] = sv.framenum - cl->lastframe + 1;
873 else
874 cl->frame_latency[sv.framenum&(LATENCY_COUNTS-1)] = 0;
875 #endif
876
877 total = 0;
878 count = 0;
879 for (j=0 ; j<LATENCY_COUNTS ; j++)
880 {
881 if (cl->frame_latency[j] > 0)
882 {
883 count++;
884 total += cl->frame_latency[j];
885 }
886 }
887 if (!count)
888 cl->ping = 0;
889 else
890 #if 0
891 cl->ping = total*100/count - 100;
892 #else
893 cl->ping = total / count;
894 #endif
895
896 // let the game dll know about the ping
897 cl->edict->client->ping = cl->ping;
898 }
899 }
900
901
902 /*
903 ===================
904 SV_GiveMsec
905
906 Every few frames, gives all clients an allotment of milliseconds
907 for their command moves. If they exceed it, assume cheating.
908 ===================
909 */
SV_GiveMsec(void)910 void SV_GiveMsec (void)
911 {
912 int i;
913 client_t *cl;
914
915 if (sv.framenum & 15)
916 return;
917
918 for (i=0 ; i<maxclients->integer ; i++)
919 {
920 cl = &svs.clients[i];
921 if (cl->state == cs_free )
922 continue;
923
924 cl->commandMsec = 1800; // 1600 + some slop
925 }
926 }
927
928
929 /*
930 =================
931 SV_ReadPackets
932 =================
933 */
934 extern int sys_msec_as_of_packet_read;
SV_ReadPackets(void)935 void SV_ReadPackets (void)
936 {
937 int i;
938 client_t *cl;
939 int qport;
940 sys_msec_as_of_packet_read = Sys_Milliseconds ();
941
942 while (NET_GetPacket (NS_SERVER, &net_from, &net_message))
943 {
944 // check for connectionless packet (0xffffffff) first
945 if (*(int *)net_message.data == -1)
946 {
947 SV_ConnectionlessPacket ();
948 continue;
949 }
950
951 // read the qport out of the message so we can fix up
952 // stupid address translating routers
953 MSG_BeginReading (&net_message);
954 MSG_ReadLong (&net_message); // sequence number
955 MSG_ReadLong (&net_message); // sequence number
956 qport = MSG_ReadShort (&net_message) & 0xffff;
957
958 // check for packets from connected clients
959 for (i=0, cl=svs.clients ; i<maxclients->integer ; i++,cl++)
960 {
961 if (cl->state == cs_free)
962 continue;
963
964 if (!NET_CompareBaseAdr (net_from, cl->netchan.remote_address))
965 continue;
966 if (cl->netchan.qport != qport)
967 continue;
968 if (cl->netchan.remote_address.port != net_from.port)
969 {
970 Com_Printf ("SV_ReadPackets: fixing up a translated port\n");
971 cl->netchan.remote_address.port = net_from.port;
972 }
973
974 if (Netchan_Process(&cl->netchan, &net_message))
975 { // this is a valid, sequenced packet, so process it
976 if (cl->state != cs_zombie)
977 {
978 cl->lastmessage = svs.realtime; // don't timeout
979 SV_ExecuteClientMessage (cl);
980 }
981 }
982 break;
983 }
984
985 if (i != maxclients->integer)
986 continue;
987 }
988 }
989
990 /*
991 ==================
992 SV_CheckTimeouts
993
994 If a packet has not been received from a client for timeout->value
995 seconds, drop the conneciton. Server frames are used instead of
996 realtime to avoid dropping the local client while debugging.
997
998 When a client is normally dropped, the client_t goes into a zombie state
999 for a few seconds to make sure any final reliable message gets resent
1000 if necessary
1001 ==================
1002 */
SV_CheckTimeouts(void)1003 void SV_CheckTimeouts (void)
1004 {
1005 int i;
1006 client_t *cl;
1007 int droppoint;
1008 int zombiepoint;
1009
1010 droppoint = svs.realtime - 1000*timeout->value;
1011 zombiepoint = svs.realtime - 1000*zombietime->value;
1012
1013 for (i=0,cl=svs.clients ; i<maxclients->integer ; i++,cl++)
1014 {
1015
1016
1017 // message times may be wrong across a changelevel
1018 if (cl->lastmessage > svs.realtime)
1019 cl->lastmessage = svs.realtime;
1020
1021 if (cl->state == cs_zombie
1022 && cl->lastmessage < zombiepoint)
1023 {
1024 cl->state = cs_free; // can now be reused
1025 continue;
1026 }
1027 if ( (cl->state == cs_connected || cl->state == cs_spawned)
1028 && cl->lastmessage < droppoint)
1029 {
1030 SV_BroadcastPrintf (PRINT_HIGH, "%s timed out\n", cl->name);
1031 SV_DropClient (cl);
1032 cl->state = cs_free; // don't bother with zombie state
1033 }
1034 }
1035 }
1036
1037 /*
1038 ================
1039 SV_PrepWorldFrame
1040
1041 This has to be done before the world logic, because
1042 player processing happens outside RunWorldFrame
1043 ================
1044 */
SV_PrepWorldFrame(void)1045 void SV_PrepWorldFrame (void)
1046 {
1047 edict_t *ent;
1048 int i;
1049
1050 for (i=0 ; i<ge->num_edicts ; i++, ent++)
1051 {
1052 ent = EDICT_NUM(i);
1053 // events only last for a single message
1054 ent->s.event = 0;
1055 }
1056
1057 }
1058
1059
1060 /*
1061 =================
1062 SV_RunGameFrame
1063 =================
1064 */
SV_RunGameFrame(void)1065 void SV_RunGameFrame (void)
1066 {
1067 if (host_speeds->integer)
1068 time_before_game = Sys_Milliseconds ();
1069
1070 // we always need to bump framenum, even if we
1071 // don't run the world, otherwise the delta
1072 // compression can get confused when a client
1073 // has the "current" frame
1074 sv.framenum++;
1075 sv.time = sv.framenum*100;
1076
1077 // don't run if paused
1078 if (!sv_paused->integer || maxclients->integer > 1)
1079 {
1080 ge->RunFrame ();
1081
1082 // never get more than one tic behind
1083 if (sv.time < svs.realtime)
1084 {
1085 if (sv_showclamp->integer)
1086 Com_Printf ("sv highclamp\n");
1087 svs.realtime = sv.time;
1088 }
1089 }
1090
1091 if (host_speeds->integer)
1092 time_after_game = Sys_Milliseconds ();
1093
1094 }
1095
1096 /*
1097 ==================
1098 SV_Frame
1099
1100 ==================
1101 */
1102 extern int sys_lasthang;
SV_Frame(int msec)1103 void SV_Frame (int msec)
1104 {
1105 int tmp_systime, tmp_hangtime;
1106 static int old_systime = 0;
1107 if (!old_systime)
1108 old_systime = Sys_Milliseconds ();
1109 time_before_game = time_after_game = 0;
1110
1111 // if server is not active, do nothing
1112 if (!svs.initialized)
1113 return;
1114
1115 svs.realtime += msec;
1116
1117 // keep the random time dependent
1118 rand ();
1119
1120 // check timeouts
1121 SV_CheckTimeouts ();
1122
1123 // get packets from clients
1124 SV_ReadPackets ();
1125
1126 // move autonomous things around if enough time has passed
1127 if (!sv_timedemo->integer && svs.realtime < sv.time)
1128 {
1129 // never let the time get too far off
1130 if (sv.time - svs.realtime > 100)
1131 {
1132 if (sv_showclamp->integer)
1133 Com_Printf ("sv lowclamp\n");
1134 svs.realtime = sv.time - 100;
1135 }
1136 NET_Sleep(sv.time - svs.realtime);
1137 return;
1138 }
1139
1140 // update ping based on the last known frame from all clients
1141 SV_CalcPings ();
1142
1143 // give the clients some timeslices
1144 SV_GiveMsec ();
1145
1146 // let everything in the world think and move
1147 SV_RunGameFrame ();
1148
1149 // send messages back to the clients that had packets read this frame
1150 SV_SendClientMessages ();
1151
1152 // save the entire world state if recording a serverdemo
1153 SV_RecordDemoMessage ();
1154
1155 // send a heartbeat to the master if needed
1156 Master_Heartbeat ();
1157
1158 // clear teleport flags, etc for next frame
1159 SV_PrepWorldFrame ();
1160
1161 tmp_systime = Sys_Milliseconds ();
1162 tmp_hangtime = tmp_systime-old_systime;
1163 old_systime = tmp_systime;
1164 if (tmp_hangtime > 150) {
1165 sys_lasthang = tmp_systime;
1166 }
1167
1168 }
1169
1170 //============================================================================
1171
1172 /*
1173 ================
1174 Master_Heartbeat
1175
1176 Send a message to the master every few minutes to
1177 let it know we are alive, and log information
1178 ================
1179 */
1180 #define HEARTBEAT_SECONDS 300
Master_Heartbeat(void)1181 void Master_Heartbeat (void)
1182 {
1183 char string[MAX_MSGLEN];
1184
1185 // pgm post3.19 change, cvar pointer not validated before dereferencing
1186
1187 if(!public_server || !public_server->integer)
1188 return;
1189
1190 // check for time wraparound
1191 if (svs.last_heartbeat > svs.realtime)
1192 svs.last_heartbeat = svs.realtime;
1193
1194 if (svs.realtime - svs.last_heartbeat < HEARTBEAT_SECONDS*1000)
1195 return; // not time to send yet
1196
1197 svs.last_heartbeat = svs.realtime;
1198
1199 // send the same string that we would give for a status OOB command
1200 Com_sprintf (string, MAX_MSGLEN, "heartbeat\n%s", SV_StatusString ());
1201 SV_HandleMasters (string, "heartbeat");
1202 }
1203
1204 /*
1205 =================
1206 Master_Shutdown
1207
1208 Informs all masters that this server is going down
1209 =================
1210 */
Master_Shutdown(void)1211 void Master_Shutdown (void)
1212 {
1213
1214 // pgm post3.19 change, cvar pointer not validated before dereferencing
1215 if (!public_server || !public_server->integer)
1216 return; // a private dedicated game
1217
1218 SV_HandleMasters ("shutdown", "shutdown");
1219 }
1220
1221
1222 /*
1223 =================
1224 SV_HandleMasters
1225
1226 Sends a message to all master servers, looking up the
1227 master servers' addresses if appropriate.
1228 =================
1229 */
SV_HandleMasters(const char * message,const char * console_message)1230 void SV_HandleMasters (const char *message, const char *console_message)
1231 {
1232 int i;
1233 qboolean updated_master;
1234
1235 // if the server is not dedicated, we need to check cl_master
1236 if ( !( dedicated && dedicated->integer ) )
1237 {
1238 if ( !sv_master )
1239 {
1240 sv_master = Cvar_Get ("cl_master", "master.corservers.com", CVAR_ARCHIVE);
1241 updated_master = true;
1242 }
1243 else if ( sv_master->modified )
1244 {
1245 sv_master->modified = false;
1246 updated_master = true;
1247 }
1248 else
1249 {
1250 updated_master = false;
1251 }
1252
1253 if ( updated_master )
1254 {
1255 memset (&master_status[0], 0, sizeof(master_sv_t));
1256 strncpy (master_status[0].name, sv_master->string, MAX_MASTER_LEN);
1257 }
1258 }
1259
1260 // first we need to loop through the master servers
1261 // in order to find the ones that need (re-)resolving
1262 for ( i = 0; i < MAX_MASTERS ; i ++ )
1263 {
1264 if ( master_status[i].name[0] == 0 )
1265 break;
1266
1267 // if we already sent a ping and didn't get
1268 // any acknowledgement packet, we need to try
1269 // re-resolving
1270 if ( master_status[i].resolved && master_status[i].last_ping_sent > master_status[i].last_ping_ack )
1271 {
1272 Com_Printf ("No acknowledgement from %s - re-resolving\n", master_status[i].name);
1273 master_status[i].resolved = false;
1274 }
1275
1276 if ( master_status[i].resolved )
1277 continue;
1278
1279 if (!NET_StringToAdr (master_status[i].name, &master_status[i].addr))
1280 {
1281 // resolution failed, did we say so already?
1282 if ( !master_status[i].failed )
1283 {
1284 Com_Printf ("Bad master address: %s\n", master_status[i].name);
1285 master_status[i].failed = true;
1286 }
1287 master_status[i].addr.port = 0;
1288 }
1289 else
1290 {
1291 master_status[i].failed = false;
1292 master_status[i].resolved = true;
1293
1294 if (master_status[i].addr.port == 0)
1295 master_status[i].addr.port = BigShort (PORT_MASTER);
1296
1297 Com_Printf ("Master server at %s\n", NET_AdrToString (master_status[i].addr));
1298 }
1299 }
1300
1301 // send the message we needed to send
1302 for ( i = 0 ; i < MAX_MASTERS ; i ++ )
1303 {
1304 if ( master_status[i].name[0] == 0 )
1305 break;
1306
1307 if ( master_status[i].addr.port == 0 )
1308 continue;
1309
1310 Com_Printf ("Sending %s to %s\n", console_message, NET_AdrToString (master_status[i].addr));
1311 Netchan_OutOfBandPrint (NS_SERVER, master_status[i].addr, "%s", message);
1312 master_status[i].last_ping_sent = 1;
1313 master_status[i].last_ping_ack = 0;
1314 }
1315 }
1316
1317
1318 //============================================================================
1319
1320
1321 /*
1322 =================
1323 SV_UserinfoChanged
1324
1325 Pull specific info from a newly changed userinfo string
1326 into a more C freindly form.
1327 =================
1328 */
SV_UserinfoChanged(client_t * cl)1329 void SV_UserinfoChanged (client_t *cl)
1330 {
1331 char *val;
1332 int i;
1333
1334 // call prog code to allow overrides
1335 ge->ClientUserinfoChanged (cl->edict, cl->userinfo, 0);
1336
1337 // name for C code
1338 Q_strncpyz2( cl->name, Info_ValueForKey (cl->userinfo, "name"), sizeof(cl->name) );
1339 // mask off high bit
1340 for (i=0 ; i<sizeof(cl->name) ; i++)
1341 cl->name[i] &= 127;
1342
1343 // rate command
1344 val = Info_ValueForKey (cl->userinfo, "rate");
1345 if (strlen(val))
1346 {
1347 i = atoi(val);
1348 cl->rate = i;
1349 if (cl->rate < 100)
1350 cl->rate = 100;
1351 if (cl->rate > 15000)
1352 cl->rate = 15000;
1353 }
1354 else
1355 cl->rate = 5000;
1356
1357 // msg command
1358 val = Info_ValueForKey (cl->userinfo, "msg");
1359 if (strlen(val))
1360 {
1361 cl->messagelevel = atoi(val);
1362 }
1363
1364 }
1365
1366
1367 //============================================================================
1368
1369 /*
1370 ===============
1371 SV_Init
1372
1373 Only called at quake2.exe startup, not for each game
1374 ===============
1375 */
SV_Init(void)1376 void SV_Init (void)
1377 {
1378 SV_InitOperatorCommands ();
1379
1380 rcon_password = Cvar_Get ("rcon_password", "", 0);
1381 Cvar_Get ("skill", "1", 0);
1382 Cvar_Get ("deathmatch", "1", CVAR_LATCH); //Alien Arena is *always* deathmatch
1383 Cvar_Get ("ctf", "0", CVAR_LATCH);
1384 Cvar_Get ("dmflags", va("%i", DF_INSTANT_ITEMS+DF_BOT_LEVELAD), CVAR_SERVERINFO);
1385 Cvar_Get ("fraglimit", "0", CVAR_SERVERINFO);
1386 Cvar_Get ("timelimit", "0", CVAR_SERVERINFO);
1387 Cvar_Get ("cheats", "0", CVAR_SERVERINFO|CVAR_LATCH);
1388 Cvar_Get ("protocol", va("%i", PROTOCOL_VERSION), CVAR_SERVERINFO|CVAR_NOSET);;
1389 maxclients = Cvar_Get ("maxclients", "1", CVAR_SERVERINFO | CVAR_LATCH);
1390 hostname = Cvar_Get ("hostname", "noname", CVAR_SERVERINFO | CVAR_ARCHIVE);
1391 timeout = Cvar_Get ("timeout", "125", 0);
1392 zombietime = Cvar_Get ("zombietime", "2", 0);
1393 sv_showclamp = Cvar_Get ("showclamp", "0", 0);
1394 sv_paused = Cvar_Get ("paused", "0", 0);
1395 sv_timedemo = Cvar_Get ("timedemo", "0", 0);
1396 sv_enforcetime = Cvar_Get ("sv_enforcetime", "0", 0);
1397 allow_download = Cvar_Get ("allow_download", "1", CVAR_ARCHIVE);
1398 allow_download_players = Cvar_Get ("allow_download_players", "0", CVAR_ARCHIVE);
1399 allow_download_models = Cvar_Get ("allow_download_models", "1", CVAR_ARCHIVE);
1400 allow_download_sounds = Cvar_Get ("allow_download_sounds", "1", CVAR_ARCHIVE);
1401 allow_download_maps = Cvar_Get ("allow_download_maps", "1", CVAR_ARCHIVE);
1402 sv_downloadurl = Cvar_Get("sv_downloadurl", "http://red.planetarena.org/sv_downloadurl", CVAR_SERVERINFO);
1403
1404 sv_iplogfile = Cvar_Get("sv_iplogfile" , "" , CVAR_ARCHIVE);
1405
1406 sv_noreload = Cvar_Get ("sv_noreload", "0", 0);
1407
1408 sv_airaccelerate = Cvar_Get("sv_airaccelerate", "0", CVAR_LATCH);
1409
1410 sv_joustmode = Cvar_Get("sv_joustmode", "0", CVAR_SERVERINFO);
1411 sv_tactical = Cvar_Get("g_tactical", "0", CVAR_LATCH | CVAR_GAMEINFO);
1412 sv_excessive = Cvar_Get("excessive", "0", CVAR_LATCH | CVAR_GAMEINFO);
1413
1414 public_server = Cvar_Get ("sv_public", "1", 0);
1415
1416 sv_reconnect_limit = Cvar_Get ("sv_reconnect_limit", "3", CVAR_ARCHIVE);
1417
1418 sv_ratelimit_status = Cvar_Get ("sv_ratelimit_status", "15", 0);
1419
1420 sv_iplimit = Cvar_Get ("sv_iplimit", "3", 0);
1421
1422 SZ_Init (&net_message, net_message_buffer, sizeof(net_message_buffer));
1423 SZ_SetName (&net_message, "Net message buffer", true);
1424
1425 remoteserver_runspeed = 300; //default
1426 }
1427
1428 /*
1429 ==================
1430 SV_FinalMessage
1431
1432 Used by SV_Shutdown to send a final message to all
1433 connected clients before the server goes down. The messages are sent immediately,
1434 not just stuck on the outgoing message list, because the server is going
1435 to totally exit after returning from this function.
1436 ==================
1437 */
SV_FinalMessage(char * message,qboolean reconnect)1438 void SV_FinalMessage (char *message, qboolean reconnect)
1439 {
1440 int i;
1441 client_t *cl;
1442
1443 SZ_Clear (&net_message);
1444 MSG_WriteByte (&net_message, svc_print);
1445 MSG_WriteByte (&net_message, PRINT_HIGH);
1446 MSG_WriteString (&net_message, message);
1447
1448 if (reconnect)
1449 MSG_WriteByte (&net_message, svc_reconnect);
1450 else
1451 MSG_WriteByte (&net_message, svc_disconnect);
1452
1453 // send it twice
1454 // stagger the packets to crutch operating system limited buffers
1455
1456 for (i=0, cl = svs.clients ; i<maxclients->integer ; i++, cl++)
1457
1458 if (cl->state >= cs_connected)
1459 Netchan_Transmit (&cl->netchan, net_message.cursize
1460 , net_message.data);
1461
1462 for (i=0, cl = svs.clients ; i<maxclients->integer ; i++, cl++)
1463
1464 if (cl->state >= cs_connected)
1465 Netchan_Transmit (&cl->netchan, net_message.cursize
1466 , net_message.data);
1467 }
1468
1469
1470
1471 /*
1472 ================
1473 SV_Shutdown
1474
1475 Called when each game quits,
1476 before Sys_Quit or Sys_Error
1477 ================
1478 */
SV_Shutdown(char * finalmsg,qboolean reconnect)1479 void SV_Shutdown (char *finalmsg, qboolean reconnect)
1480 {
1481 extern void Con_Clear_f (void);
1482
1483 if (svs.clients)
1484 SV_FinalMessage (finalmsg, reconnect);
1485
1486 Master_Shutdown ();
1487 SV_ShutdownGameProgs ();
1488
1489 // free current level
1490 if (sv.demofile)
1491 fclose (sv.demofile);
1492 memset (&sv, 0, sizeof(sv));
1493 Com_SetServerState (sv.state);
1494
1495 // free server static data
1496 if (svs.clients)
1497 Z_Free (svs.clients);
1498 if (svs.client_entities)
1499 Z_Free (svs.client_entities);
1500 if (svs.demofile)
1501 fclose (svs.demofile);
1502 memset (&svs, 0, sizeof(svs));
1503 }
1504
IsVisible(vec3_t org1,vec3_t org2)1505 qboolean IsVisible(vec3_t org1,vec3_t org2)
1506 {
1507 trace_t trace;
1508
1509 trace = SV_Trace2 (org1, NULL, NULL, org2, NULL, MASK_VISIBILILITY);
1510
1511 if (trace.fraction != 1)
1512 return false;
1513 return true;
1514 }
1515