summaryrefslogtreecommitdiff
path: root/src/server
diff options
context:
space:
mode:
authorTim Angus <tim@ngus.net>2009-10-03 15:17:16 +0000
committerTim Angus <tim@ngus.net>2013-01-03 00:16:38 +0000
commit6d2ffb4c637a49983bc6ce22b68ccec0ed09e0f4 (patch)
treeff15343e4a2ae5a2512c1c21e05a3821a46f10da /src/server
parente9e52d0b7ec9bae071534df7581126d69d3e9bf8 (diff)
* Merge ioq3-r1637
Diffstat (limited to 'src/server')
-rw-r--r--src/server/server.h3
-rw-r--r--src/server/sv_client.c33
-rw-r--r--src/server/sv_game.c3
-rw-r--r--src/server/sv_init.c15
-rw-r--r--src/server/sv_main.c107
-rw-r--r--src/server/sv_net_chan.c60
-rw-r--r--src/server/sv_snapshot.c3
-rw-r--r--src/server/sv_world.c6
8 files changed, 137 insertions, 93 deletions
diff --git a/src/server/server.h b/src/server/server.h
index eb3766e8..fe78026c 100644
--- a/src/server/server.h
+++ b/src/server/server.h
@@ -205,6 +205,7 @@ typedef struct client_s {
typedef struct {
netadr_t adr;
int challenge;
+ int clientChallenge; // challenge number coming from the client
int time; // time the last packet was sent to the autherize server
int pingTime; // time the challenge response was sent to client
int firstTime; // time the adr was first used, for authorize timeout checks
@@ -313,7 +314,7 @@ void SV_SpawnServer( char *server, qboolean killBots );
//
// sv_client.c
//
-void SV_GetChallenge( netadr_t from );
+void SV_GetChallenge(netadr_t from);
void SV_DirectConnect( netadr_t from );
diff --git a/src/server/sv_client.c b/src/server/sv_client.c
index 4b7b3bb6..4449f1c8 100644
--- a/src/server/sv_client.c
+++ b/src/server/sv_client.c
@@ -42,12 +42,21 @@ to be sent to the authorize server.
When an authorizeip is returned, a challenge response will be
sent to that ip.
+
+ioquake3: we added a possibility for clients to add a challenge
+to their packets, to make it more difficult for malicious servers
+to hi-jack client connections.
+Also, the auth stuff is completely disabled for com_standalone games
+as well as IPv6 connections, since there is no way to use the
+v4-only auth server for these new types of connections.
=================
*/
-void SV_GetChallenge( netadr_t from ) {
+void SV_GetChallenge(netadr_t from)
+{
int i;
int oldest;
int oldestTime;
+ const char *clientChallenge = Cmd_Argv(1);
challenge_t *challenge;
oldest = 0;
@@ -65,21 +74,24 @@ void SV_GetChallenge( netadr_t from ) {
}
}
- if (i == MAX_CHALLENGES) {
+ if (i == MAX_CHALLENGES)
+ {
// this is the first time this client has asked for a challenge
challenge = &svs.challenges[oldest];
-
challenge->challenge = ( (rand() << 16) ^ rand() ) ^ svs.time;
+ challenge->clientChallenge = 0;
challenge->adr = from;
challenge->firstTime = svs.time;
challenge->time = svs.time;
challenge->connected = qfalse;
- i = oldest;
}
// send the challengeResponse
challenge->pingTime = svs.time;
NET_OutOfBandPrint( NS_SERVER, from, "challengeResponse %i", challenge->challenge );
+
+ challenge->pingTime = svs.time;
+ NET_OutOfBandPrint( NS_SERVER, challenge->adr, "challengeResponse %i %s", challenge->challenge, clientChallenge);
}
/*
@@ -339,7 +351,7 @@ void SV_DropClient( client_t *drop, const char *reason ) {
for (i = 0 ; i < MAX_CHALLENGES ; i++, challenge++) {
if ( NET_CompareAdr( drop->netchan.remoteAddress, challenge->adr ) ) {
- challenge->connected = qfalse;
+ Com_Memset(challenge, 0, sizeof(*challenge));
break;
}
}
@@ -350,7 +362,6 @@ void SV_DropClient( client_t *drop, const char *reason ) {
// tell everyone why they got dropped
SV_SendServerCommand( NULL, "print \"%s" S_COLOR_WHITE " %s\n\"", drop->name, reason );
-
if (drop->download) {
FS_FCloseFile( drop->download );
drop->download = 0;
@@ -394,7 +405,7 @@ It will be resent if the client acknowledges a later message but has
the wrong gamestate.
================
*/
-void SV_SendClientGameState( client_t *client ) {
+static void SV_SendClientGameState( client_t *client ) {
int start;
entityState_t *base, nullstate;
msg_t msg;
@@ -531,7 +542,7 @@ SV_StopDownload_f
Abort a download if in progress
==================
*/
-void SV_StopDownload_f( client_t *cl ) {
+static void SV_StopDownload_f( client_t *cl ) {
if (*cl->downloadName)
Com_DPrintf( "clientDownload: %d : file \"%s\" aborted\n", (int) (cl - svs.clients), cl->downloadName );
@@ -545,7 +556,7 @@ SV_DoneDownload_f
Downloads are finished
==================
*/
-void SV_DoneDownload_f( client_t *cl ) {
+static void SV_DoneDownload_f( client_t *cl ) {
Com_DPrintf( "clientDownload: %s Done\n", cl->name);
// resend the game state to update any clients that entered during the download
SV_SendClientGameState(cl);
@@ -559,7 +570,7 @@ The argument will be the last acknowledged block from the client, it should be
the same as cl->downloadClientBlock
==================
*/
-void SV_NextDownload_f( client_t *cl )
+static void SV_NextDownload_f( client_t *cl )
{
int block = atoi( Cmd_Argv(1) );
@@ -588,7 +599,7 @@ void SV_NextDownload_f( client_t *cl )
SV_BeginDownload_f
==================
*/
-void SV_BeginDownload_f( client_t *cl ) {
+static void SV_BeginDownload_f( client_t *cl ) {
// Kill any existing download
SV_CloseDownload( cl );
diff --git a/src/server/sv_game.c b/src/server/sv_game.c
index d375c095..1efa6d5f 100644
--- a/src/server/sv_game.c
+++ b/src/server/sv_game.c
@@ -182,17 +182,14 @@ qboolean SV_inPVSIgnorePortals( const vec3_t p1, const vec3_t p2)
{
int leafnum;
int cluster;
- int area1, area2;
byte *mask;
leafnum = CM_PointLeafnum (p1);
cluster = CM_LeafCluster (leafnum);
- area1 = CM_LeafArea (leafnum);
mask = CM_ClusterPVS (cluster);
leafnum = CM_PointLeafnum (p2);
cluster = CM_LeafCluster (leafnum);
- area2 = CM_LeafArea (leafnum);
if ( mask && (!(mask[cluster>>3] & (1<<(cluster&7)) ) ) )
return qfalse;
diff --git a/src/server/sv_init.c b/src/server/sv_init.c
index 43eb2c09..34ced5c5 100644
--- a/src/server/sv_init.c
+++ b/src/server/sv_init.c
@@ -105,7 +105,7 @@ SV_SetConfigstring
===============
*/
void SV_SetConfigstring (int index, const char *val) {
- int len, i;
+ int i;
client_t *client;
if ( index < 0 || index >= MAX_CONFIGSTRINGS ) {
@@ -141,8 +141,6 @@ void SV_SetConfigstring (int index, const char *val) {
continue;
}
-
- len = strlen( val );
SV_SendConfigstring(client, index);
}
}
@@ -217,7 +215,7 @@ to the clients -- only the fields that differ from the
baseline will be transmitted
================
*/
-void SV_CreateBaseline( void ) {
+static void SV_CreateBaseline( void ) {
sharedEntity_t *svent;
int entnum;
@@ -242,7 +240,7 @@ SV_BoundMaxClients
===============
*/
-void SV_BoundMaxClients( int minimum ) {
+static void SV_BoundMaxClients( int minimum ) {
// get the current maxclients value
Cvar_Get( "sv_maxclients", "8", 0 );
@@ -266,7 +264,7 @@ NOT cause this to be called, unless the game is exited to
the menu system first.
===============
*/
-void SV_Startup( void ) {
+static void SV_Startup( void ) {
if ( svs.initialized ) {
Com_Error( ERR_FATAL, "SV_Startup: svs.initialized" );
}
@@ -364,7 +362,7 @@ void SV_ChangeMaxClients( void ) {
SV_ClearServer
================
*/
-void SV_ClearServer(void) {
+static void SV_ClearServer(void) {
int i;
for ( i = 0 ; i < MAX_CONFIGSTRINGS ; i++ ) {
@@ -382,7 +380,7 @@ SV_TouchCGame
touch the cgame.vm so that a pure client can load it if it's in a seperate pk3
================
*/
-void SV_TouchCGame(void) {
+static void SV_TouchCGame(void) {
fileHandle_t f;
char filename[MAX_QPATH];
@@ -470,7 +468,6 @@ void SV_SpawnServer( char *server, qboolean killBots ) {
Cvar_Set("cl_paused", "0");
// get a new checksum feed and restart the file system
- srand(Com_Milliseconds());
sv.checksumFeed = ( ((int) rand() << 16) ^ rand() ) ^ Com_Milliseconds();
FS_Restart( sv.checksumFeed );
diff --git a/src/server/sv_main.c b/src/server/sv_main.c
index 305cf299..41bfec4a 100644
--- a/src/server/sv_main.c
+++ b/src/server/sv_main.c
@@ -74,7 +74,7 @@ SV_ExpandNewlines
Converts newlines to "\n" so a line prints nicer
===============
*/
-char *SV_ExpandNewlines( char *in ) {
+static char *SV_ExpandNewlines( char *in ) {
static char string[1024];
int l;
@@ -97,10 +97,11 @@ char *SV_ExpandNewlines( char *in ) {
======================
SV_ReplacePendingServerCommands
- This is ugly
+FIXME: This is ugly
======================
*/
-int SV_ReplacePendingServerCommands( client_t *client, const char *cmd ) {
+#if 0 // unused
+static int SV_ReplacePendingServerCommands( client_t *client, const char *cmd ) {
int i, index, csnum1, csnum2;
for ( i = client->reliableSent+1; i <= client->reliableSequence; i++ ) {
@@ -117,6 +118,7 @@ int SV_ReplacePendingServerCommands( client_t *client, const char *cmd ) {
}
return qfalse;
}
+#endif
/*
======================
@@ -223,52 +225,89 @@ but not on every player enter or exit.
#define HEARTBEAT_MSEC 300*1000
#define HEARTBEAT_GAME "Tremulous"
void SV_MasterHeartbeat( void ) {
- static netadr_t adr[MAX_MASTER_SERVERS];
+ static netadr_t adr[MAX_MASTER_SERVERS][2]; // [2] for v4 and v6 address for the same address string.
int i;
int res;
+ int netenabled;
+
+ netenabled = Cvar_VariableIntegerValue("net_enabled");
// "dedicated 1" is for lan play, "dedicated 2" is for inet public play
- if ( !com_dedicated || com_dedicated->integer != 2 ) {
+ if (!com_dedicated || com_dedicated->integer != 2 || !(netenabled & (NET_ENABLEV4 | NET_ENABLEV6)))
return; // only dedicated servers send heartbeats
- }
// if not time yet, don't send anything
- if ( svs.time < svs.nextHeartbeatTime ) {
+ if ( svs.time < svs.nextHeartbeatTime )
return;
- }
- svs.nextHeartbeatTime = svs.time + HEARTBEAT_MSEC;
+ svs.nextHeartbeatTime = svs.time + HEARTBEAT_MSEC;
// send to group masters
- for ( i = 0 ; i < MAX_MASTER_SERVERS ; i++ ) {
- if ( !sv_master[i]->string[0] ) {
+ for (i = 0; i < MAX_MASTER_SERVERS; i++)
+ {
+ if(!sv_master[i]->string[0])
continue;
- }
// see if we haven't already resolved the name
// resolving usually causes hitches on win95, so only
// do it when needed
- if ( sv_master[i]->modified ) {
+ if(sv_master[i]->modified || (adr[i][0].type == NA_BAD && adr[i][1].type == NA_BAD))
+ {
sv_master[i]->modified = qfalse;
-
- Com_Printf( "Resolving %s\n", sv_master[i]->string );
- res = NET_StringToAdr( sv_master[i]->string, &adr[i], NA_UNSPEC );
- if ( !res ) {
- Com_Printf( "Couldn't resolve address: %s\n", sv_master[i]->string );
- continue;
+
+ if(netenabled & NET_ENABLEV4)
+ {
+ Com_Printf("Resolving %s (IPv4)\n", sv_master[i]->string);
+ res = NET_StringToAdr(sv_master[i]->string, &adr[i][0], NA_IP);
+
+ if(res == 2)
+ {
+ // if no port was specified, use the default master port
+ adr[i][0].port = BigShort(PORT_MASTER);
+ }
+
+ if(res)
+ Com_Printf( "%s resolved to %s\n", sv_master[i]->string, NET_AdrToStringwPort(adr[i][0]));
+ else
+ Com_Printf( "%s has no IPv4 address.\n", sv_master[i]->string);
}
- if ( res == 2 ) {
- // if no port was specified, use the default master port
- adr[i].port = BigShort( PORT_MASTER );
+
+ if(netenabled & NET_ENABLEV6)
+ {
+ Com_Printf("Resolving %s (IPv6)\n", sv_master[i]->string);
+ res = NET_StringToAdr(sv_master[i]->string, &adr[i][1], NA_IP6);
+
+ if(res == 2)
+ {
+ // if no port was specified, use the default master port
+ adr[i][1].port = BigShort(PORT_MASTER);
+ }
+
+ if(res)
+ Com_Printf( "%s resolved to %s\n", sv_master[i]->string, NET_AdrToStringwPort(adr[i][1]));
+ else
+ Com_Printf( "%s has no IPv6 address.\n", sv_master[i]->string);
+ }
+
+ if(adr[i][0].type == NA_BAD && adr[i][1].type == NA_BAD)
+ {
+ Com_Printf("Couldn't resolve address: %s\n", sv_master[i]->string);
+ Cvar_Set(sv_master[i]->name, "");
+ sv_master[i]->modified = qfalse;
+ continue;
}
- Com_Printf( "%s resolved to %s\n", sv_master[i]->string, NET_AdrToStringwPort(adr[i]));
}
Com_Printf ("Sending heartbeat to %s\n", sv_master[i]->string );
+
// this command should be changed if the server info / status format
// ever incompatably changes
- NET_OutOfBandPrint( NS_SERVER, adr[i], "heartbeat %s\n", HEARTBEAT_GAME );
+
+ if(adr[i][0].type != NA_BAD)
+ NET_OutOfBandPrint( NS_SERVER, adr[i][0], "heartbeat %s\n", HEARTBEAT_GAME );
+ if(adr[i][1].type != NA_BAD)
+ NET_OutOfBandPrint( NS_SERVER, adr[i][1], "heartbeat %s\n", HEARTBEAT_GAME );
}
}
@@ -342,7 +381,7 @@ and all connected players. Used for getting detailed information after
the simple info query.
================
*/
-void SVC_Status( netadr_t from ) {
+static void SVC_Status( netadr_t from ) {
char player[1024];
char status[MAX_MSGLEN];
int i;
@@ -449,7 +488,7 @@ SVC_FlushRedirect
================
*/
-void SV_FlushRedirect( char *outputbuf ) {
+static void SV_FlushRedirect( char *outputbuf ) {
NET_OutOfBandPrint( NS_SERVER, svs.redirectAddress, "print\n%s", outputbuf );
}
@@ -462,7 +501,7 @@ Shift down the remaining args
Redirect all printfs
===============
*/
-void SVC_RemoteCommand( netadr_t from, msg_t *msg ) {
+static void SVC_RemoteCommand( netadr_t from, msg_t *msg ) {
qboolean valid;
unsigned int time;
char remaining[1024];
@@ -483,10 +522,10 @@ void SVC_RemoteCommand( netadr_t from, msg_t *msg ) {
if ( !strlen( sv_rconPassword->string ) ||
strcmp (Cmd_Argv(1), sv_rconPassword->string) ) {
valid = qfalse;
- Com_Printf ("Bad rcon from %s:\n%s\n", NET_AdrToString (from), Cmd_Argv(2) );
+ Com_Printf ("Bad rcon from %s: %s\n", NET_AdrToString (from), Cmd_ArgsFrom(2) );
} else {
valid = qtrue;
- Com_Printf ("Rcon from %s:\n%s\n", NET_AdrToString (from), Cmd_Argv(2) );
+ Com_Printf ("Rcon from %s: %s\n", NET_AdrToString (from), Cmd_ArgsFrom(2) );
}
// start redirecting all print outputs to the packet
@@ -532,7 +571,7 @@ Clients that are in the game can still send
connectionless packets.
=================
*/
-void SV_ConnectionlessPacket( netadr_t from, msg_t *msg ) {
+static void SV_ConnectionlessPacket( netadr_t from, msg_t *msg ) {
char *s;
char *c;
@@ -554,7 +593,7 @@ void SV_ConnectionlessPacket( netadr_t from, msg_t *msg ) {
} else if (!Q_stricmp(c, "getinfo")) {
SVC_Info( from );
} else if (!Q_stricmp(c, "getchallenge")) {
- SV_GetChallenge( from );
+ SV_GetChallenge(from);
} else if (!Q_stricmp(c, "connect")) {
SV_DirectConnect( from );
} else if (!Q_stricmp(c, "rcon")) {
@@ -641,7 +680,7 @@ SV_CalcPings
Updates the cl->ping variables
===================
*/
-void SV_CalcPings( void ) {
+static void SV_CalcPings( void ) {
int i, j;
client_t *cl;
int total, count;
@@ -697,7 +736,7 @@ for a few seconds to make sure any final reliable message gets resent
if necessary
==================
*/
-void SV_CheckTimeouts( void ) {
+static void SV_CheckTimeouts( void ) {
int i;
client_t *cl;
int droppoint;
@@ -738,7 +777,7 @@ void SV_CheckTimeouts( void ) {
SV_CheckPaused
==================
*/
-qboolean SV_CheckPaused( void ) {
+static qboolean SV_CheckPaused( void ) {
int count;
client_t *cl;
int i;
diff --git a/src/server/sv_net_chan.c b/src/server/sv_net_chan.c
index 0de49d4f..dd2bb204 100644
--- a/src/server/sv_net_chan.c
+++ b/src/server/sv_net_chan.c
@@ -35,28 +35,29 @@ SV_Netchan_Encode
==============
*/
static void SV_Netchan_Encode( client_t *client, msg_t *msg ) {
- long reliableAcknowledge, i, index;
+ long i, index;
byte key, *string;
- int srdc, sbit, soob;
-
+ int srdc, sbit;
+ qboolean soob;
+
if ( msg->cursize < SV_ENCODE_START ) {
return;
}
- srdc = msg->readcount;
- sbit = msg->bit;
- soob = msg->oob;
-
- msg->bit = 0;
- msg->readcount = 0;
- msg->oob = 0;
-
- reliableAcknowledge = MSG_ReadLong(msg);
+ srdc = msg->readcount;
+ sbit = msg->bit;
+ soob = msg->oob;
+
+ msg->bit = 0;
+ msg->readcount = 0;
+ msg->oob = qfalse;
+
+ /* reliableAcknowledge = */ MSG_ReadLong(msg);
+
+ msg->oob = soob;
+ msg->bit = sbit;
+ msg->readcount = srdc;
- msg->oob = soob;
- msg->bit = sbit;
- msg->readcount = srdc;
-
string = (byte *)client->lastClientCommandString;
index = 0;
// xor the client challenge with the netchan sequence number
@@ -90,23 +91,24 @@ SV_Netchan_Decode
*/
static void SV_Netchan_Decode( client_t *client, msg_t *msg ) {
int serverId, messageAcknowledge, reliableAcknowledge;
- int i, index, srdc, sbit, soob;
+ int i, index, srdc, sbit;
+ qboolean soob;
byte key, *string;
- srdc = msg->readcount;
- sbit = msg->bit;
- soob = msg->oob;
-
- msg->oob = 0;
-
- serverId = MSG_ReadLong(msg);
+ srdc = msg->readcount;
+ sbit = msg->bit;
+ soob = msg->oob;
+
+ msg->oob = qfalse;
+
+ serverId = MSG_ReadLong(msg);
messageAcknowledge = MSG_ReadLong(msg);
reliableAcknowledge = MSG_ReadLong(msg);
- msg->oob = soob;
- msg->bit = sbit;
- msg->readcount = srdc;
-
+ msg->oob = soob;
+ msg->bit = sbit;
+ msg->readcount = srdc;
+
string = (byte *)client->reliableCommands[ reliableAcknowledge & (MAX_RELIABLE_COMMANDS-1) ];
index = 0;
//
@@ -137,7 +139,7 @@ void SV_Netchan_TransmitNextFragment( client_t *client ) {
if (!client->netchan.unsentFragments)
{
// make sure the netchan queue has been properly initialized (you never know)
- if (!client->netchan_end_queue) {
+ if ((!client->netchan_end_queue) && (client->state >= CS_CONNECTED)) {
Com_Error(ERR_DROP, "netchan queue is not properly initialized in SV_Netchan_TransmitNextFragment\n");
}
// the last fragment was transmitted, check wether we have queued messages
diff --git a/src/server/sv_snapshot.c b/src/server/sv_snapshot.c
index 037b772d..d813aad4 100644
--- a/src/server/sv_snapshot.c
+++ b/src/server/sv_snapshot.c
@@ -299,7 +299,6 @@ static void SV_AddEntitiesVisibleFromPoint( vec3_t origin, clientSnapshot_t *fra
int l;
int clientarea, clientcluster;
int leafnum;
- int c_fullsend;
byte *clientpvs;
byte *bitvector;
@@ -319,8 +318,6 @@ static void SV_AddEntitiesVisibleFromPoint( vec3_t origin, clientSnapshot_t *fra
clientpvs = CM_ClusterPVS (clientcluster);
- c_fullsend = 0;
-
for ( e = 0 ; e < sv.num_entities ; e++ ) {
ent = SV_GentityNum(e);
diff --git a/src/server/sv_world.c b/src/server/sv_world.c
index d40cc217..508ff0cc 100644
--- a/src/server/sv_world.c
+++ b/src/server/sv_world.c
@@ -104,7 +104,7 @@ SV_CreateworldSector
Builds a uniformly subdivided tree for the given world size
===============
*/
-worldSector_t *SV_CreateworldSector( int depth, vec3_t mins, vec3_t maxs ) {
+static worldSector_t *SV_CreateworldSector( int depth, vec3_t mins, vec3_t maxs ) {
worldSector_t *anode;
vec3_t size;
vec3_t mins1, maxs1, mins2, maxs2;
@@ -380,7 +380,7 @@ SV_AreaEntities_r
====================
*/
-void SV_AreaEntities_r( worldSector_t *node, areaParms_t *ap ) {
+static void SV_AreaEntities_r( worldSector_t *node, areaParms_t *ap ) {
svEntity_t *check, *next;
sharedEntity_t *gcheck;
int count;
@@ -508,7 +508,7 @@ SV_ClipMoveToEntities
====================
*/
-void SV_ClipMoveToEntities( moveclip_t *clip ) {
+static void SV_ClipMoveToEntities( moveclip_t *clip ) {
int i, num;
int touchlist[MAX_GENTITIES];
sharedEntity_t *touch;