/* <9a28f> ../engine/sv_log.c:321 */ void SV_AddLogAddress_f(void) { const char *s; int nPort; char szAdr[MAX_PATH]; netadr_t adr; LOGLIST_T *list; qboolean found = FALSE; LOGLIST_T *tmp; if (Cmd_Argc() != 3) { Con_Printf("logaddress_add: usage\nlogaddress_add ip port\n"); for (list = firstLog; list != NULL; list = list->next) Con_Printf("current: %s\n", NET_AdrToString(list->log.net_address_)); return; } nPort = Q_atoi(Cmd_Argv(2)); if (!nPort) { Con_Printf("logaddress_add: must specify a valid port\n"); return; } s = Cmd_Argv(1); if (!s || *s == '\0') { Con_Printf("logaddress_add: unparseable address\n"); return; } Q_snprintf(szAdr, sizeof(szAdr), "%s:%i", s, nPort); if (!NET_StringToAdr(szAdr, &adr)) { Con_Printf("logaddress_add: unable to resolve %s\n", szAdr); return; } if (firstLog) { for (list = firstLog; list != NULL; list = list->next) { #ifdef REHLDS_FIXES //for IPX support if (NET_CompareAdr(adr, list->log.net_address_)) #else if (Q_memcmp(adr.ip, list->log.net_address_.ip, 4) == 0 && adr.port == list->log.net_address_.port) #endif // REHLDS_FIXES { found = TRUE; break; } } if (found) { Con_Printf("logaddress_add: address already in list\n"); return; } tmp = (LOGLIST_T *)Mem_Malloc(sizeof(LOGLIST_T)); if (!tmp) { Con_Printf("logaddress_add: error allocating new node\n"); return; } tmp->next = NULL; Q_memcpy(&tmp->log.net_address_, &adr, sizeof(netadr_t)); list = firstLog; while (list->next) list = list->next; list->next = tmp; } else { firstLog = (LOGLIST_T *)Mem_Malloc(sizeof(LOGLIST_T)); if (!firstLog) { Con_Printf("logaddress_add: error allocating new node\n"); return; } firstLog->next = NULL; Q_memcpy(&firstLog->log.net_address_, &adr, sizeof(netadr_t)); } Con_Printf("logaddress_add: %s\n", NET_AdrToString(adr)); }
/* <9a345> ../engine/sv_log.c:439 */ void SV_DelLogAddress_f(void) { const char *s; int nPort; char szAdr[MAX_PATH]; netadr_t adr; LOGLIST_T *list; LOGLIST_T *prev; qboolean found = FALSE; if (Cmd_Argc() != 3) { Con_Printf("logaddress_del: usage\nlogaddress_del ip port\n"); for (list = firstLog; list != NULL; list = list->next) Con_Printf("current: %s\n", NET_AdrToString(list->log.net_address_)); return; } nPort = Q_atoi(Cmd_Argv(2)); if (!nPort) { Con_Printf("logaddress_del: must specify a valid port\n"); return; } s = Cmd_Argv(1); if (!s || *s == '\0') { Con_Printf("logaddress_del: unparseable address\n"); return; } Q_snprintf(szAdr, sizeof(szAdr), "%s:%i", s, nPort); if (!NET_StringToAdr(szAdr,&adr)) { Con_Printf("logaddress_del: unable to resolve %s\n", szAdr); return; } if (!firstLog) { Con_Printf("logaddress_del: No addresses added yet\n"); return; } for(list = firstLog, prev = firstLog; list != NULL; list = list->next) { #ifdef REHLDS_FIXES //for IPX if (NET_CompareAdr(adr,list->log.net_address_)) #else if (Q_memcmp(adr.ip, list->log.net_address_.ip, 4) == 0 && adr.port == list->log.net_address_.port) #endif // REHLDS_FIXES { found = TRUE; if (list == prev) { firstLog = prev->next; Mem_Free(prev); } else { prev->next = list->next; Mem_Free(list); } break; } prev = list; } if (!found) { Con_Printf("logaddress_del: Couldn't find address in list\n"); return; } Con_Printf("deleting: %s\n", NET_AdrToString(adr)); }
/** * @brief Removes server(s) from the 'cache' * @param source Positive values AS_LOCAL, AS_GLOBAL, AS_FAVORITES * or negative values AS_LOCAL_ALL, AS_GLOBAL_ALL, AS_FAVORITES_ALL to remove all * @param addr Server address - in case of negative source param addr is not required * */ static void LAN_RemoveServer(int source, const char *addr) { int *count = 0; serverInfo_t *servers = NULL; switch (source) { case AS_LOCAL: case AS_LOCAL_ALL: count = &cls.numlocalservers; servers = &cls.localServers[0]; break; case AS_GLOBAL: case AS_GLOBAL_ALL: count = &cls.numglobalservers; servers = &cls.globalServers[0]; break; case AS_FAVORITES: case AS_FAVORITES_ALL: count = &cls.numfavoriteservers; servers = &cls.favoriteServers[0]; break; } if (servers && count > 0) { if (source >= AS_LOCAL) // single server removal { netadr_t comp; int i, j; NET_StringToAdr(addr, &comp, NA_UNSPEC); for (i = 0; i < *count; i++) { if (NET_CompareAdr(comp, servers[i].adr)) { j = i; while (j < *count - 1) { Com_Memcpy(&servers[j], &servers[j + 1], sizeof(servers[j])); j++; } (*count)--; break; } } if (source == AS_FAVORITES) { LAN_SaveServersToFile(); } } else // remove all { switch (source) { case AS_LOCAL_ALL: Com_Printf("Removing %i local servers\n", cls.numlocalservers); cls.numlocalservers = 0; Com_Memset(&cls.localServers, 0, sizeof(cls.localServers)); break; case AS_GLOBAL_ALL: Com_Printf("Removing %i global servers\n", cls.numglobalservers); cls.numglobalservers = 0; Com_Memset(&cls.globalServers, 0, sizeof(cls.globalServers)); break; case AS_FAVORITES_ALL: Com_Printf("Removing %i favourite servers\n", cls.numfavoriteservers); cls.numfavoriteservers = 0; Com_Memset(&cls.favoriteServers, 0, sizeof(cls.favoriteServers)); LAN_SaveServersToFile(); break; default: Com_Printf("LAN_RemoveServer: Invalid source\n"); break; } } } else { Com_Printf("No server found - nothing to remove\n"); } }
void SV_MasterHeartbeat(const char *message) { 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) && !(sv_public->integer) ) || !(netenabled & (NET_ENABLEV4 | NET_ENABLEV6))) return; // only dedicated servers send heartbeats // if not time yet, don't send anything if ( svs.time < svs.nextHeartbeatTime ) return; svs.nextHeartbeatTime = svs.time + HEARTBEAT_MSEC; // send to group masters 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 || (adr[i][0].type == NA_BAD && adr[i][1].type == NA_BAD)) { sv_master[i]->modified = qfalse; 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(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) { // if the address failed to resolve, clear it // so we don't take repeated dns hits 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 ("Sending heartbeat to %s\n", sv_master[i]->string ); // this command should be changed if the server info / status format // ever incompatably changes if(adr[i][0].type != NA_BAD) NET_OutOfBandPrint( NS_SERVER, adr[i][0], "heartbeat %s\n", message); if(adr[i][1].type != NA_BAD) NET_OutOfBandPrint( NS_SERVER, adr[i][1], "heartbeat %s\n", message); } }
/* ============== SV_InitGame A brand new game has been started ============== */ void SV_InitGame (void) { int i; edict_t *ent; char idmaster[32]; if (svs.initialized) { // cause any connected clients to reconnect SV_Shutdown ("Server restarted\n", true); } else { // make sure the client is down CL_Drop (); SCR_BeginLoadingPlaque (); } // get any latched variable changes (maxclients, etc) Cvar_GetLatchedVars (); svs.initialized = true; if (Cvar_VariableValue ("coop") && Cvar_VariableValue ("deathmatch")) { Com_Printf("Deathmatch and Coop both set, disabling Coop\n"); Cvar_FullSet ("coop", "0", CVAR_SERVERINFO | CVAR_LATCH); } // dedicated servers are can't be single player and are usually DM // so unless they explicity set coop, force it to deathmatch if (dedicated->value) { if (!Cvar_VariableValue ("coop")) Cvar_FullSet ("deathmatch", "1", CVAR_SERVERINFO | CVAR_LATCH); } // init clients if (Cvar_VariableValue ("deathmatch")) { if (maxclients->value <= 1) Cvar_FullSet ("maxclients", "8", CVAR_SERVERINFO | CVAR_LATCH); else if (maxclients->value > MAX_CLIENTS) Cvar_FullSet ("maxclients", va("%i", MAX_CLIENTS), CVAR_SERVERINFO | CVAR_LATCH); } else if (Cvar_VariableValue ("coop")) { if (maxclients->value <= 1 || maxclients->value > 4) Cvar_FullSet ("maxclients", "4", CVAR_SERVERINFO | CVAR_LATCH); #ifdef COPYPROTECT if (!sv.attractloop && !dedicated->value) Sys_CopyProtect (); #endif } else // non-deathmatch, non-coop is one player { Cvar_FullSet ("maxclients", "1", CVAR_SERVERINFO | CVAR_LATCH); #ifdef COPYPROTECT if (!sv.attractloop) Sys_CopyProtect (); #endif } svs.spawncount = rand(); svs.clients = Z_Malloc (sizeof(client_t)*maxclients->value); svs.num_client_entities = maxclients->value*UPDATE_BACKUP*64; svs.client_entities = Z_Malloc (sizeof(entity_state_t)*svs.num_client_entities); // init network stuff NET_Config ( (maxclients->value > 1) ); // heartbeats will always be sent to the id master svs.last_heartbeat = -99999; // send immediately Com_sprintf(idmaster, sizeof(idmaster), "192.246.40.37:%i", PORT_MASTER); NET_StringToAdr (idmaster, &master_adr[0]); // init game SV_InitGameProgs (); for (i=0 ; i<maxclients->value ; i++) { ent = EDICT_NUM(i+1); ent->s.number = i+1; svs.clients[i].edict = ent; memset (&svs.clients[i].lastcmd, 0, sizeof(svs.clients[i].lastcmd)); } }
static void FTP_GetExtendedPassiveAddress(const char* line, const char* address, netadr_t* adr) { int i, j, port; Com_Memset(adr, 0, sizeof(netadr_t)); i = 0; /* Remove the port number */ if(NET_StringToAdr(address, adr, NA_UNSPEC) == 0) { /* No valid address string. Must not happen. */ return; } /* Find the start of address */ while(line[i] != '(' && line[i] != '\0') i++; if(line[i] != '(') { Com_Memset(adr,0, sizeof(netadr_t)); return; } i++; for(j = 0; j < 3; j++) { while(line[i] != '|' && line[i] != ')' && line[i] != '\0') i++; if(line[i] == '|') { /* A delimiter */ i++; } } port = atoi(&line[i]); if(port < 1 || port > 65535) { /* Something is invalid */ Com_Memset(adr, 0, sizeof(netadr_t)); return; } while(line[i] != '|' && line[i] != '\0') i++; if(line[i] == '|') { /* A delimiter */ i++; }else { /* Something is invalid */ Com_Memset(adr, 0, sizeof(netadr_t)); return; } while(line[i] != ')' && line[i] != '\0') i++; if(line[i] == ')') { adr->port = BigShort(port); }else { /* Something is invalid */ Com_Memset(adr, 0, sizeof(netadr_t)); } }
/* =============== SVC_RemoteCommand An rcon packet arrived from the network. Shift down the remaining args Redirect all printfs =============== */ void SVC_RemoteCommand( netadr_t from, msg_t *msg ) { qboolean valid; unsigned int time; char remaining[1024]; netadr_t allowedSpamIPAdress; // TTimo - scaled down to accumulate, but not overflow anything network wise, print wise etc. // (OOB messages are the bottleneck here) #define SV_OUTPUTBUF_LENGTH (1024 - 16) char sv_outputbuf[SV_OUTPUTBUF_LENGTH]; static unsigned int lasttime = 0; char *cmd_aux; // TTimo - https://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=534 time = Com_Milliseconds(); NET_StringToAdr( sv_rconAllowedSpamIP->string , &allowedSpamIPAdress); if ( !strlen( sv_rconPassword->string ) || strcmp (Cmd_Argv(1), sv_rconPassword->string) ) { // let's the sv_rconAllowedSpamIP do spam rcon if ( ( !strlen( sv_rconAllowedSpamIP->string ) || !NET_CompareBaseAdr( from , allowedSpamIPAdress ) ) && !NET_IsLocalAddress(from) ){ // MaJ - If the rconpassword is bad and one just happned recently, don't spam the log file, just die. if ( (unsigned)( time - lasttime ) < 600u ) return; } valid = qfalse; Com_Printf ("Bad rcon from %s:\n%s\n", NET_AdrToString (from), Cmd_Argv(2) ); } else { // let's the sv_rconAllowedSpamIP do spam rcon if ( ( !strlen( sv_rconAllowedSpamIP->string ) || !NET_CompareBaseAdr( from , allowedSpamIPAdress ) ) && !NET_IsLocalAddress(from) ){ // MaJ - If the rconpassword is good, allow it much sooner than a bad one. if ( (unsigned)( time - lasttime ) < 180u ) return; } valid = qtrue; Com_Printf ("Rcon from %s:\n%s\n", NET_AdrToString (from), Cmd_Argv(2) ); } lasttime = time; // start redirecting all print outputs to the packet svs.redirectAddress = from; Com_BeginRedirect (sv_outputbuf, SV_OUTPUTBUF_LENGTH, SV_FlushRedirect); if ( !strlen( sv_rconPassword->string ) ) { Com_Printf ("No rconpassword set on the server.\n"); } else if ( !valid ) { Com_Printf ("Bad rconpassword.\n"); } else { remaining[0] = 0; // https://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=543 // get the command directly, "rcon <pass> <command>" to avoid quoting issues // extract the command by walking // since the cmd formatting can fuckup (amount of spaces), using a dumb step by step parsing cmd_aux = Cmd_Cmd(); cmd_aux+=4; while(cmd_aux[0]==' ') cmd_aux++; while(cmd_aux[0] && cmd_aux[0]!=' ') // password cmd_aux++; while(cmd_aux[0]==' ') cmd_aux++; Q_strcat( remaining, sizeof(remaining), cmd_aux); Cmd_ExecuteString (remaining); } Com_EndRedirect (); }
static void SV_AddBanToList(qboolean isexception) { char *banstring, *suffix; netadr_t ip; int argc, mask; fileHandle_t writeto; argc = Cmd_Argc(); if(argc < 2 || argc > 3) { Com_Printf ("Usage: %s (ip[/subnet] | clientnum [subnet])\n", Cmd_Argv(0)); return; } if(serverBansCount > sizeof(serverBans) / sizeof(*serverBans)) { Com_Printf ("Error: Maximum number of bans/exceptions exceeded.\n"); return; } banstring = Cmd_Argv(1); if(strchr(banstring, '.') || strchr(banstring, ':')) { // This is an ip address, not a client num. // Look for a CIDR-Notation suffix suffix = strchr(banstring, '/'); if(suffix) { *suffix = '\0'; suffix++; } if(!NET_StringToAdr(banstring, &ip, NA_UNSPEC)) { Com_Printf("Error: Invalid address %s\n", banstring); return; } } else { client_t *cl; // client num. if(!com_sv_running->integer) { Com_Printf("Server is not running.\n"); return; } cl = SV_GetPlayerByNum(); if(!cl) { Com_Printf("Error: Playernum %s does not exist.\n", Cmd_Argv(1)); return; } ip = cl->netchan.remoteAddress; if(argc == 3) suffix = Cmd_Argv(2); else suffix = NULL; } if(ip.type != NA_IP && ip.type != NA_IP6) { Com_Printf("Error: Can ban players connected via the internet only.\n"); return; } if(suffix) { mask = atoi(suffix); if(ip.type == NA_IP) { if(mask < 0 || mask > 32) mask = 32; } else { if(mask < 0 || mask > 128) mask = 128; } } else if(ip.type == NA_IP) mask = 32; else mask = 128; serverBans[serverBansCount].ip = ip; serverBans[serverBansCount].subnet = mask; serverBans[serverBansCount].isexception = isexception; Com_Printf("Added %s: %s/%d\n", isexception ? "ban exception" : "ban", NET_AdrToString(ip), mask); // Write out the ban information. if((writeto = FS_FOpenFileAppend(SERVER_BANFILE))) { char writebuf[128]; Com_sprintf(writebuf, sizeof(writebuf), "%d %s %d\n", isexception, NET_AdrToString(ip), mask); FS_Write(writebuf, strlen(writebuf), writeto); FS_FCloseFile(writeto); } serverBansCount++; }
/* ==================== CL_UISystemCalls The ui module is making a system call ==================== */ intptr_t CL_UISystemCalls( intptr_t *args ) { // Com_Printf( "SYSCALL(%d)\n", args[0]); switch( args[0] ) { case UI_ERROR: Com_Error( ERR_DROP, "%s", (const char*)VMA(1) ); return 0; case UI_PRINT: Com_Printf( "%s", (const char*)VMA(1) ); return 0; case UI_MILLISECONDS: return Sys_Milliseconds(); case UI_CVAR_REGISTER: Cvar_Register( VMA(1), VMA(2), VMA(3), args[4] ); return 0; case UI_CVAR_UPDATE: Cvar_Update( VMA(1) ); return 0; case UI_CVAR_SET: Cvar_Set( VMA(1), VMA(2) ); return 0; case UI_CVAR_VARIABLEVALUE: return FloatAsInt( Cvar_VariableValue( VMA(1) ) ); case UI_CVAR_VARIABLESTRINGBUFFER: Cvar_VariableStringBuffer( VMA(1), VMA(2), args[3] ); return 0; case UI_CVAR_SETVALUE: Cvar_SetValue( VMA(1), VMF(2) ); return 0; case UI_CVAR_RESET: Cvar_Reset( VMA(1) ); return 0; case UI_CVAR_CREATE: Cvar_Get( VMA(1), VMA(2), args[3] ); return 0; case UI_CVAR_INFOSTRINGBUFFER: Cvar_InfoStringBuffer( args[1], VMA(2), args[3] ); return 0; case UI_ARGC: return Cmd_Argc(); case UI_ARGV: Cmd_ArgvBuffer( args[1], VMA(2), args[3] ); return 0; case UI_CMD_EXECUTETEXT: if(args[1] == 0 && (!strncmp(VMA(2), "snd_restart", 11) || !strncmp(VMA(2), "vid_restart", 11) || !strncmp(VMA(2), "quit", 5))) { Com_Printf (S_COLOR_YELLOW "turning EXEC_NOW '%.11s' into EXEC_INSERT\n", (const char*)VMA(2)); args[1] = EXEC_INSERT; } Cbuf_ExecuteText( args[1], VMA(2) ); return 0; case UI_FS_FOPENFILE: return FS_FOpenFileByMode( VMA(1), VMA(2), args[3] ); case UI_FS_READ: FS_Read2( VMA(1), args[2], args[3] ); return 0; case UI_FS_WRITE: FS_Write( VMA(1), args[2], args[3] ); return 0; case UI_FS_FCLOSEFILE: FS_FCloseFile( args[1] ); return 0; case UI_FS_GETFILELIST: return FS_GetFileList( VMA(1), VMA(2), VMA(3), args[4] ); case UI_FS_SEEK: return FS_Seek( args[1], args[2], args[3] ); case UI_R_REGISTERMODEL: return re.RegisterModel( VMA(1) ); case UI_R_REGISTERSKIN: return re.RegisterSkin( VMA(1) ); case UI_R_REGISTERSHADERNOMIP: return re.RegisterShaderNoMip( VMA(1) ); case UI_R_CLEARSCENE: re.ClearScene(); return 0; case UI_R_ADDREFENTITYTOSCENE: re.AddRefEntityToScene( VMA(1) ); return 0; case UI_R_ADDPOLYTOSCENE: re.AddPolyToScene( args[1], args[2], VMA(3), 1 ); return 0; case UI_R_ADDLIGHTTOSCENE: re.AddLightToScene( VMA(1), VMF(2), VMF(3), VMF(4), VMF(5) ); return 0; case UI_R_RENDERSCENE: re.RenderScene( VMA(1) ); return 0; case UI_R_SETCOLOR: re.SetColor( VMA(1) ); return 0; case UI_R_DRAWSTRETCHPIC: re.DrawStretchPic( VMF(1), VMF(2), VMF(3), VMF(4), VMF(5), VMF(6), VMF(7), VMF(8), args[9] ); return 0; case UI_R_MODELBOUNDS: re.ModelBounds( args[1], VMA(2), VMA(3) ); return 0; case UI_UPDATESCREEN: SCR_UpdateScreen(); return 0; case UI_CM_LERPTAG: re.LerpTag( VMA(1), args[2], args[3], args[4], VMF(5), VMA(6) ); return 0; case UI_S_REGISTERSOUND: return S_RegisterSound( VMA(1), args[2] ); case UI_S_STARTLOCALSOUND: S_StartLocalSound( args[1], args[2] ); return 0; case UI_KEY_KEYNUMTOSTRINGBUF: Key_KeynumToStringBuf( args[1], VMA(2), args[3] ); return 0; case UI_KEY_GETBINDINGBUF: Key_GetBindingBuf( args[1], VMA(2), args[3] ); return 0; case UI_KEY_SETBINDING: Key_SetBinding( args[1], VMA(2) ); return 0; case UI_KEY_ISDOWN: return Key_IsDown( args[1] ); case UI_KEY_GETOVERSTRIKEMODE: return Key_GetOverstrikeMode(); case UI_KEY_SETOVERSTRIKEMODE: Key_SetOverstrikeMode( args[1] ); return 0; case UI_KEY_CLEARSTATES: Key_ClearStates(); return 0; case UI_KEY_GETCATCHER: return Key_GetCatcher(); case UI_KEY_SETCATCHER: // Don't allow the ui module to close the console Key_SetCatcher( args[1] | ( Key_GetCatcher( ) & KEYCATCH_CONSOLE ) ); return 0; case UI_GETCLIPBOARDDATA: CL_GetClipboardData( VMA(1), args[2] ); return 0; case UI_GETCLIENTSTATE: GetClientState( VMA(1) ); return 0; case UI_GETGLCONFIG: CL_GetGlconfig( VMA(1) ); return 0; case UI_GETCONFIGSTRING: return GetConfigString( args[1], VMA(2), args[3] ); case UI_LAN_LOADCACHEDSERVERS: LAN_LoadCachedServers(); return 0; case UI_LAN_SAVECACHEDSERVERS: LAN_SaveServersToCache(); return 0; case UI_LAN_ADDSERVER: return LAN_AddServer(args[1], VMA(2), VMA(3)); case UI_LAN_REMOVESERVER: LAN_RemoveServer(args[1], VMA(2)); return 0; case UI_LAN_GETPINGQUEUECOUNT: return LAN_GetPingQueueCount(); case UI_LAN_CLEARPING: LAN_ClearPing( args[1] ); return 0; case UI_LAN_GETPING: LAN_GetPing( args[1], VMA(2), args[3], VMA(4) ); return 0; case UI_LAN_GETPINGINFO: LAN_GetPingInfo( args[1], VMA(2), args[3] ); return 0; case UI_LAN_GETSERVERCOUNT: return LAN_GetServerCount(args[1]); case UI_LAN_GETSERVERADDRESSSTRING: LAN_GetServerAddressString( args[1], args[2], VMA(3), args[4] ); return 0; case UI_LAN_GETSERVERINFO: LAN_GetServerInfo( args[1], args[2], VMA(3), args[4] ); return 0; case UI_LAN_GETSERVERPING: return LAN_GetServerPing( args[1], args[2] ); case UI_LAN_MARKSERVERVISIBLE: LAN_MarkServerVisible( args[1], args[2], args[3] ); return 0; case UI_LAN_SERVERISVISIBLE: return LAN_ServerIsVisible( args[1], args[2] ); case UI_LAN_UPDATEVISIBLEPINGS: return LAN_UpdateVisiblePings( args[1] ); case UI_LAN_RESETPINGS: LAN_ResetPings( args[1] ); return 0; case UI_LAN_SERVERSTATUS: return LAN_GetServerStatus( VMA(1), VMA(2), args[3] ); case UI_LAN_COMPARESERVERS: return LAN_CompareServers( args[1], args[2], args[3], args[4], args[5] ); case UI_MEMORY_REMAINING: return Hunk_MemoryRemaining(); case UI_GET_CDKEY: CLUI_GetCDKey( VMA(1), args[2] ); return 0; case UI_SET_CDKEY: #ifndef STANDALONE CLUI_SetCDKey( VMA(1) ); #endif return 0; case UI_SET_PBCLSTATUS: return 0; case UI_R_REGISTERFONT: re.RegisterFont( VMA(1), args[2], VMA(3)); return 0; case UI_MEMSET: Com_Memset( VMA(1), args[2], args[3] ); return 0; case UI_MEMCPY: Com_Memcpy( VMA(1), VMA(2), args[3] ); return 0; case UI_STRNCPY: strncpy( VMA(1), VMA(2), args[3] ); return args[1]; case UI_SIN: return FloatAsInt( sin( VMF(1) ) ); case UI_COS: return FloatAsInt( cos( VMF(1) ) ); case UI_ATAN2: return FloatAsInt( atan2( VMF(1), VMF(2) ) ); case UI_SQRT: return FloatAsInt( sqrt( VMF(1) ) ); case UI_FLOOR: return FloatAsInt( floor( VMF(1) ) ); case UI_CEIL: return FloatAsInt( ceil( VMF(1) ) ); case UI_PC_ADD_GLOBAL_DEFINE: return botlib_export->PC_AddGlobalDefine( VMA(1) ); case UI_PC_LOAD_SOURCE: return botlib_export->PC_LoadSourceHandle( VMA(1) ); case UI_PC_FREE_SOURCE: return botlib_export->PC_FreeSourceHandle( args[1] ); case UI_PC_READ_TOKEN: return botlib_export->PC_ReadTokenHandle( args[1], VMA(2) ); case UI_PC_SOURCE_FILE_AND_LINE: return botlib_export->PC_SourceFileAndLine( args[1], VMA(2), VMA(3) ); case UI_S_STOPBACKGROUNDTRACK: S_StopBackgroundTrack(); return 0; case UI_S_STARTBACKGROUNDTRACK: S_StartBackgroundTrack( VMA(1), VMA(2)); return 0; case UI_REAL_TIME: return Com_RealTime( VMA(1) ); case UI_CIN_PLAYCINEMATIC: Com_DPrintf("UI_CIN_PlayCinematic\n"); return CIN_PlayCinematic(VMA(1), args[2], args[3], args[4], args[5], args[6]); case UI_CIN_STOPCINEMATIC: return CIN_StopCinematic(args[1]); case UI_CIN_RUNCINEMATIC: return CIN_RunCinematic(args[1]); case UI_CIN_DRAWCINEMATIC: CIN_DrawCinematic(args[1]); return 0; case UI_CIN_SETEXTENTS: CIN_SetExtents(args[1], args[2], args[3], args[4], args[5]); return 0; case UI_R_REMAP_SHADER: re.RemapShader( VMA(1), VMA(2), VMA(3) ); return 0; case UI_VERIFY_CDKEY: return CL_CDKeyValidate(VMA(1), VMA(2)); #ifdef USE_AUTH case UI_NET_STRINGTOADR: return NET_StringToAdr(VMA(1), VMA(2), NA_IP); case UI_Q_VSNPRINTF: return Q_vsnprintf(VMA(1), (size_t)VMA(2), VMA(3), VMA(4)); case UI_NET_SENDPACKET: { netadr_t addr; const char *destination = VMA(4); NET_StringToAdr(destination, &addr, NA_IP); NET_SendPacket(args[1], args[2], VMA(3), addr); } return 0; case UI_COPYSTRING: return (intptr_t)CopyString(VMA(1)); case UI_SYS_STARTPROCESS: //Sys_StartProcess(VMA(1), (qboolean) VMA(2)); return 0; #endif default: Com_Error( ERR_DROP, "Bad UI system trap: %ld", (long int) args[0] ); } return 0; }
/* =============== SV_MasterHeartbeat =============== */ void SV_MasterHeartbeat( const char *hbname ) { static netadr_t adr[MAX_MASTER_SERVERS][2]; int i, res, netenabled; // Update Server doesn't send heartbeat #if defined (UPDATE_SERVER) return; #endif netenabled = Cvar_VariableIntegerValue("net_enabled"); if ( SV_GameIsSinglePlayer() ) { return; // no heartbeats for SP } // "dedicated 1" is for lan play, "dedicated 2" is for inet public play 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 ) { return; } svs.nextHeartbeatTime = svs.time + HEARTBEAT_MSEC; // send to group masters 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 || (adr[i][0].type == NA_BAD && adr[i][1].type == NA_BAD)) { sv_master[i]->modified = false; 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(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) { // if the address failed to resolve, clear it // so we don't take repeated dns hits Com_Printf( "Couldn't resolve address: %s\n", sv_master[i]->string ); Cvar_Set( sv_master[i]->name, "" ); sv_master[i]->modified = false; continue; } } Com_Printf( "Sending heartbeat to the official OpenWolf servers list %s\n", sv_master[i]->string ); // this command should be changed if the server info / status format // ever incompatably changes 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 ); } } #if defined (USE_PHP) // Send to the main master. if (svs.queryDone) { pthread_exit(&svs.thQuery); svs.queryDone = 0; } else { SV_PHPMaster(); } #endif }
void Master_Init() { int i, SkipSection, tempport; static int HaveConfigured = 0; char * filep; const char * curfilep; netadr_t tempadr; if(HaveConfigured != 0 || gfNoMasterServer != 0) { return; } HaveConfigured = 1; if(COM_CheckParmCase("-nomaster") != 0 || global_svs.allocated_client_slots <= 1) { Con_Printf("%s: Master server comm disabled.\n", __FUNCTION__); gfNoMasterServer = 0; return; //and don't check again, ever. } MasterHeartbeatTimeout = 15; i = COM_CheckParmCase("-comm"); if(i != 0 && i+1 < global_com_argc) { filep = COM_LoadFileForMe(global_com_argv[i+1], NULL); } else { filep = COM_LoadFileForMe("valvecomm.lst", NULL); if(filep == NULL) { filep = COM_LoadFileForMe("woncomm.lst", NULL); } } if(filep == NULL) { Con_Printf("%s: Couldn't load comm file. Disabling masters--fix it.\n", __FUNCTION__); return; } curfilep = filep; i = 0; while(1) { curfilep = COM_Parse(curfilep); if(global_com_token[0] == '\0') { break; } SkipSection = 1; if(Q_strcasecmp("master", global_com_token) == 0) { SkipSection = 0; } curfilep = COM_Parse(curfilep); if(Q_strcmp("{", global_com_token) != 0) { break; } while(1) { curfilep = COM_Parse(curfilep); if(global_com_token[0] == '\0' || Q_strcmp("}", global_com_token) == 0) { break; } if(SkipSection == 0 && NET_StringToAdr(global_com_token, &tempadr) == 0) { break; } //We just (maybe) parsed the server name, if you missed it. Now for the port. curfilep = COM_Parse(curfilep); if(Q_strcmp(":", global_com_token) != 0) { break; } curfilep = COM_Parse(curfilep); if(global_com_token[0] == '\0') { break; } if(SkipSection == 0) { tempport = Q_atoi(global_com_token); if(tempport < 1 || tempport > 65535) { tempport = 27010; } tempadr.port = tempport; Con_Printf("%s: Adding master server %s.\n", __FUNCTION__, NET_AdrToString(tempadr)); //all that work to avoid needless string copying, all gone :) Master_AddServer(&tempadr); i++; } } } COM_FreeFile(filep); if(i == 0) { Con_Printf("%s: Didn't parse any masters. Disabling master comm.\n", __FUNCTION__); gfNoMasterServer = 0; } }
void Master_SetMaster_f() { int AreAdding; const char * arg_1, * arg_2; int port; netadr_t netaddress; master_server_t * ptr, * ptr2; if(Cmd_Argc() < 2 || Cmd_Argc() > 4) { Con_Printf("Setmaster <add | remove | enable | disable> <IP:port>\n"); Con_Printf(" Current master list:\n"); for(ptr = masterlist; ptr != NULL; ptr = ptr->next) { Con_Printf(" %s\n", NET_AdrToString(ptr->address)); } Con_Printf(" End if list\n"); return; } arg_1 = Cmd_Argv(1); if(arg_1[0] == '\0') { return; } if(Q_strcasecmp(arg_1, "disable") == 0) { gfNoMasterServer = 1; return; } if(Q_strcasecmp(arg_1, "enable") == 0) { gfNoMasterServer = 0; return; } if(Q_strcasecmp(arg_1, "add") == 0) { AreAdding = 1; } else if(Q_strcasecmp(arg_1, "remove") == 0) { AreAdding = 0; } else { Con_Printf("Setmaster: Unknown command \"%s\".\n", arg_1); return; } arg_2 = Cmd_Argv(2); if(Cmd_Argc() == 4) { port = Q_atoi(Cmd_Argv(3)); if(port < 1 || port > 65535) { Con_Printf("Setmaster: Invalid port. Ports can't be larger than 65535.\n"); return; } } else { port = 27010; } if(NET_StringToAdr(arg_2, &netaddress) == 0) { Con_Printf("Setmaster: Passed address could not be processed by StringToAdr.\n"); return; } netaddress.port = port; if(AreAdding) { Master_Init(); Master_AddServer(&netaddress); gfNoMasterServer = 0; Con_Printf("Master server %s:%u added.\n", arg_2, port); } else { //case 1: first node. if(NET_CompareAdr(masterlist->address, netaddress) != 0) { ptr = masterlist; masterlist = masterlist->next; Q_Free(ptr); return; } //case 2: some node afterwards for(ptr = masterlist; ptr->next != NULL; ptr = ptr->next) { if(NET_CompareAdr(ptr->next->address, netaddress) != 0) { ptr2 = ptr->next; ptr->next = ptr->next->next; Q_Free(ptr2); return; } } //case 3: not here Con_Printf("Master %s:%u couldn't be removed. Couldn't find it.\n", arg_2, port); } }
void Reload_Sources(void) { int i; vfsfile_t *f; char ln[2048]; source_data *s; for (i=0; i < sourcesn; i++) Delete_Source(sources[i]); sourcesn = 0; // create dummy unbound source sources[0] = Create_Source(); sources[0]->type = type_dummy; strlcpy (sources[0]->name, "Unbound", sizeof (sources[0]->name)); sources[0]->servers = (server_data **) Q_malloc(MAX_UNBOUND*sizeof(server_data *)); sourcesn = 1; f = FS_OpenVFS(SOURCES_LIST_FILENAME, "rb", FS_ANY); if (!f) { //Com_Printf ("sources file not found: %s\n", SOURCES_PATH); return; } s = Create_Source(); while (VFS_GETS(f, ln, sizeof(ln))) { char line[2048]; char *p, *q; if (sscanf(ln, "%[ -~ ]s", line) != 1) { continue; } p = next_nonspace(line); if (*p == '/') continue; // comment q = next_space(p); if (!strncmp(p, "master", q-p)) { s->type = type_master; } else if (!strncmp(p, "file", q-p)) { s->type = type_file; } else if (!strncmp(p, "url", q-p)) { s->type = type_url; } else { continue; } p = next_nonspace(q); q = (*p == '\"') ? next_quote(++p) : next_space(p); if (q-p <= 0) continue; strlcpy (s->name, p, min(q-p+1, MAX_SOURCE_NAME+1)); p = next_nonspace(q+1); q = next_space(p); *q = 0; if (q-p <= 0) continue; if (s->type == type_file) strlcpy (s->address.filename, p, sizeof (s->address.filename)); else if (s->type == type_url) strlcpy (s->address.url, p, sizeof (s->address.url)); else if (!NET_StringToAdr(p, &(s->address.address))) continue; sources[sourcesn] = Create_Source(); i = sources[sourcesn]->unique; memcpy(sources[sourcesn], s, sizeof(source_data)); sources[sourcesn]->unique = i; sourcesn++; } Delete_Source(s); VFS_CLOSE(f); //Com_Printf("Read %d sources for Server Browser\n", sourcesn); // update all file sources for (i=0; i < sourcesn; i++) if (sources[i]->type == type_file) Update_Source(sources[i]); else if (sources[i]->type == type_master || sources[i]->type == type_url) Precache_Source(sources[i]); rebuild_servers_list = 1; resort_sources = 1; }
void SV_UnbanIP_f() { if(Cmd_Argc()!=2) { Com_Printf("Usage: unbanip <ip>\n"); return; } aSingleBan *current = banlist; char* ip = Cmd_Argv(1); netadr_t ipadr; NET_StringToAdr(ip, &ipadr); FILE* f = fopen("ipbans.txt", "w"); if(f) { while(current!=NULL) { if(current->type == IPBAN) { if(NET_CompareBaseAdr(current->adr, ipadr)) { Com_Printf("IP '%s' has been unbanned.\n", ip); current=current->next; continue; } fprintf(f, "%s\n", NET_BaseAdrToString(current->adr)); } current = current->next; } fclose(f); } X_ReadBannedList(false); /*qboolean found = qfalse; netadr_t unban; if(Cmd_Argc() != 2) { Com_Printf("Usage: unbanip \"127.0.0.1\"\n"); return; } FILE* f = fopen("ipban.txt", "w"); if(!f) { Com_Printf("Failed to open ipban.txt\n"); return; } NET_StringToAdr(Cmd_Argv(1), &unban); std::ifstream in("ipban.txt"); std::string line; if(in.is_open()) { bannedIPs.clear(); netadr_t adr; while(std::getline(in, line)) { if(line.empty()) continue; NET_StringToAdr(line.c_str(), &adr); if(!strcmp(Cmd_Argv(1), line.c_str())) { Com_Printf("'%s' has been unbanned.\n", Cmd_Argv(1)); found = qtrue; continue; } fprintf(f, "%s\n", NET_BaseAdrToString(adr)); bannedIPs.push_back(adr); } if(!found) { Com_Printf("'%s' was not found in the banlist.\n", Cmd_Argv(1)); } } else { Com_Printf("Error whilst reading ipban.txt, failed to correctly unban.\n"); } fclose(f); */ }
/* ================== SV_RehashServerRconFile Helper to reload a "serverRcon_t" type of file Returns number of entries loaded ================== */ static int SV_RehashServerRconFile(convar_t *fileName, int maxEntries, serverRcon_t buffer[]) { int index, filelen, numEntries = 0; fileHandle_t readfrom; char *textbuf, *curpos, *maskpos, *newlinepos, *endpos, filepath[MAX_QPATH]; if(!fileName->string || !*fileName->string) { goto exit; } if(!(curpos = Cvar_VariableString("fs_game")) || !*curpos) { curpos = BASEGAME; } Com_sprintf(filepath, sizeof(filepath), "%s/%s", curpos, fileName->string); if((filelen = FS_SV_FOpenFileRead(filepath, &readfrom)) < 0) { Com_Printf("SV_RehashServerRconFile: failed to open %s\n", filepath); goto exit; } if(filelen < 2) { // Don't bother if file is too short. FS_FCloseFile(readfrom); goto exit; } curpos = textbuf = (char*)Z_Malloc(filelen); filelen = FS_Read(textbuf, filelen, readfrom); FS_FCloseFile(readfrom); endpos = textbuf + filelen; for(index = 0; index < maxEntries && curpos + 2 < endpos; index++) { // find the end of the address string for(maskpos = curpos + 2; maskpos < endpos && *maskpos != ' '; maskpos++); if(maskpos + 1 >= endpos) { break; } *maskpos = '\0'; maskpos++; // find the end of the subnet specifier for(newlinepos = maskpos; newlinepos < endpos && *newlinepos != '\n'; newlinepos++); if(newlinepos >= endpos) { break; } *newlinepos = '\0'; if(NET_StringToAdr(curpos + 2, &buffer[index].ip, NA_UNSPEC)) { buffer[index].isexception = (qboolean)(curpos[0] != '0'); buffer[index].subnet = atoi(maskpos); if(buffer[index].ip.type == NA_IP && (buffer[index].subnet < 1 || buffer[index].subnet > 32)) { buffer[index].subnet = 32; } else if(buffer[index].ip.type == NA_IP6 && (buffer[index].subnet < 1 || buffer[index].subnet > 128)) { buffer[index].subnet = 128; } } curpos = newlinepos + 1; } Z_Free(textbuf); numEntries = index; exit: return numEntries; }
/* ================= SV_GetChallenge A "getchallenge" OOB command has been received Returns a challenge number that can be used in a subsequent connectResponse command. We do this to prevent denial of service attacks that flood the server with invalid connection IPs. With a challenge, they must give a valid IP address. If we are authorizing, a challenge request will cause a packet to be sent to the authorize server. When an authorizeip is returned, a challenge response will be sent to that ip. ================= */ void SV_GetChallenge( netadr_t from ) { int i; int oldest; int oldestTime; challenge_t *challenge; // ignore if we are in single player if ( Cvar_VariableValue( "g_gametype" ) == GT_SINGLE_PLAYER || Cvar_VariableValue("ui_singlePlayerActive")) { return; } oldest = 0; oldestTime = 0x7fffffff; // see if we already have a challenge for this ip challenge = &svs.challenges[0]; for (i = 0 ; i < MAX_CHALLENGES ; i++, challenge++) { if ( !challenge->connected && NET_CompareAdr( from, challenge->adr ) ) { break; } if ( challenge->time < oldestTime ) { oldestTime = challenge->time; oldest = i; } } 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->adr = from; challenge->firstTime = svs.time; challenge->time = svs.time; challenge->connected = qfalse; i = oldest; } // if they are on a lan address, send the challengeResponse immediately if ( Sys_IsLANAddress( from ) ) { challenge->pingTime = svs.time; NET_OutOfBandPrint( NS_SERVER, from, "challengeResponse %i", challenge->challenge ); return; } // look up the authorize server's IP if ( !svs.authorizeAddress.ip[0] && svs.authorizeAddress.type != NA_BAD ) { Com_Printf( "Resolving %s\n", AUTHORIZE_SERVER_NAME ); if ( !NET_StringToAdr( AUTHORIZE_SERVER_NAME, &svs.authorizeAddress ) ) { Com_Printf( "Couldn't resolve address\n" ); return; } svs.authorizeAddress.port = BigShort( PORT_AUTHORIZE ); Com_Printf( "%s resolved to %i.%i.%i.%i:%i\n", AUTHORIZE_SERVER_NAME, svs.authorizeAddress.ip[0], svs.authorizeAddress.ip[1], svs.authorizeAddress.ip[2], svs.authorizeAddress.ip[3], BigShort( svs.authorizeAddress.port ) ); } // if they have been challenging for a long time and we // haven't heard anything from the authorize server, go ahead and // let them in, assuming the id server is down if ( svs.time - challenge->firstTime > AUTHORIZE_TIMEOUT ) { Com_DPrintf( "authorize server timed out\n" ); challenge->pingTime = svs.time; NET_OutOfBandPrint( NS_SERVER, challenge->adr, "challengeResponse %i", challenge->challenge ); return; } // otherwise send their ip to the authorize server if ( svs.authorizeAddress.type != NA_BAD ) { cvar_t *fs; char game[1024]; Com_DPrintf( "sending getIpAuthorize for %s\n", NET_AdrToString( from )); strcpy(game, BASEGAME); fs = Cvar_Get ("fs_game", "", CVAR_INIT|CVAR_SYSTEMINFO ); if (fs && fs->string[0] != 0) { strcpy(game, fs->string); } // the 0 is for backwards compatibility with obsolete sv_allowanonymous flags // getIpAuthorize <challenge> <IP> <game> 0 <auth-flag> NET_OutOfBandPrint( NS_SERVER, svs.authorizeAddress, "getIpAuthorize %i %i.%i.%i.%i %s 0 %s", svs.challenges[i].challenge, from.ip[0], from.ip[1], from.ip[2], from.ip[3], game, sv_strictAuth->string ); } }
/* ================= SV_GetChallenge A "getchallenge" OOB command has been received Returns a challenge number that can be used in a subsequent connectResponse command. We do this to prevent denial of service attacks that flood the server with invalid connection IPs. With a challenge, they must give a valid IP address. If we are authorizing, a challenge request will cause a packet 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 ) { static leakyBucket_t outboundLeakyBucket; int i; int oldest; int oldestTime; int oldestClientTime; int clientChallenge; challenge_t *challenge; qboolean wasfound = qfalse; // ignore if we are in single player if ( Cvar_VariableValue( "g_gametype" ) == GT_SINGLE_PLAYER || Cvar_VariableValue("ui_singlePlayerActive")) { return; } // Prevent using getchallenge as an amplifier if ( SVC_RateLimitAddress( from, 10, 1000 ) ) { Com_DPrintf( "SV_GetChallenge: rate limit from %s exceeded, dropping request\n", NET_AdrToString( from ) ); return; } // Allow getchallenge to be DoSed relatively easily, but prevent // excess outbound bandwidth usage when being flooded inbound if ( SVC_RateLimit( &outboundLeakyBucket, 10, 100 ) ) { Com_DPrintf( "SV_GetChallenge: rate limit exceeded, dropping request\n" ); return; } oldest = 0; oldestClientTime = oldestTime = 0x7fffffff; // see if we already have a challenge for this ip challenge = &svs.challenges[0]; clientChallenge = atoi( Cmd_Argv( 1 ) ); for (i = 0 ; i < MAX_CHALLENGES ; i++, challenge++ ) { if ( !challenge->connected && NET_CompareAdr( from, challenge->adr ) ) { wasfound = qtrue; if ( challenge->time < oldestClientTime ) oldestClientTime = challenge->time; } if ( wasfound && i >= MAX_CHALLENGES_MULTI ) { i = MAX_CHALLENGES; break; } if ( challenge->time < oldestTime ) { oldestTime = challenge->time; oldest = i; } } if (i == MAX_CHALLENGES) { // this is the first time this client has asked for a challenge challenge = &svs.challenges[oldest]; challenge->clientChallenge = clientChallenge; challenge->adr = from; challenge->firstTime = svs.time; challenge->connected = qfalse; } // always generate a new challenge number, so the client cannot circumvent sv_maxping challenge->challenge = ( (rand() << 16) ^ rand() ) ^ svs.time; challenge->wasrefused = qfalse; challenge->time = svs.time; #if !defined(STANDALONE) && defined (USE_AUTHORIZE) // Drop the authorize stuff if this client is coming in via v6 as the auth server does not support ipv6. // Drop also for addresses coming in on local LAN and for stand-alone games independent from id's assets. if(challenge->adr.type == NA_IP && !Cvar_VariableIntegerValue("com_standalone") && !Sys_IsLANAddress(from)) { // look up the authorize server's IP if (svs.authorizeAddress.type == NA_BAD) { Com_Printf( "Resolving %s\n", AUTHORIZE_SERVER_NAME ); if (NET_StringToAdr(AUTHORIZE_SERVER_NAME, &svs.authorizeAddress, NA_IP)) { svs.authorizeAddress.port = BigShort( PORT_AUTHORIZE ); Com_Printf( "%s resolved to %i.%i.%i.%i:%i\n", AUTHORIZE_SERVER_NAME, svs.authorizeAddress.ip[0], svs.authorizeAddress.ip[1], svs.authorizeAddress.ip[2], svs.authorizeAddress.ip[3], BigShort( svs.authorizeAddress.port ) ); } } // we couldn't contact the auth server, let them in. if(svs.authorizeAddress.type == NA_BAD) Com_Printf("Couldn't resolve auth server address\n"); // if they have been challenging for a long time and we // haven't heard anything from the authorize server, go ahead and // let them in, assuming the id server is down else if(svs.time - oldestClientTime > AUTHORIZE_TIMEOUT) Com_DPrintf( "authorize server timed out\n" ); else { // otherwise send their ip to the authorize server cvar_t *fs; char game[1024]; Com_DPrintf( "sending getIpAuthorize for %s\n", NET_AdrToString( from )); strcpy(game, IDBASEGAME); fs = Cvar_Get ("fs_game", "", CVAR_INIT|CVAR_SYSTEMINFO ); if (fs && fs->string[0] != 0) { strcpy(game, fs->string); } // the 0 is for backwards compatibility with obsolete sv_allowanonymous flags // getIpAuthorize <challenge> <IP> <game> 0 <auth-flag> NET_OutOfBandPrint( NS_SERVER, svs.authorizeAddress, "getIpAuthorize %i %i.%i.%i.%i %s 0 %s", challenge->challenge, from.ip[0], from.ip[1], from.ip[2], from.ip[3], game, sv_strictAuth->string ); return; } } #endif challenge->pingTime = svs.time; NET_OutOfBandPrint(NS_SERVER, challenge->adr, "challengeResponse %d %d", challenge->challenge, clientChallenge); }
/* <d4799> ../engine/net_ws.c:2076 */ void NET_GetLocalAddress(void) { char buff[512]; struct sockaddr_in address; int namelen; int net_error; Q_memset(&net_local_adr, 0, sizeof(netadr_t)); #ifdef _WIN32 Q_memset(&net_local_ipx_adr, 0, sizeof(netadr_t)); #endif // _WIN32 if (noip) { Con_Printf("TCP/IP Disabled.\n"); } else { if (Q_strcmp(ipname.string, "localhost")) Q_strncpy(buff, ipname.string, ARRAYSIZE(buff) - 1); else { #ifdef _WIN32 CRehldsPlatformHolder::get()->gethostname(buff, ARRAYSIZE(buff)); #else gethostname(buff, ARRAYSIZE(buff)); #endif // _WIN32 } buff[ARRAYSIZE(buff) - 1] = 0; #ifdef REHLDS_FIXES //check if address is valid if (NET_StringToAdr(buff, &net_local_adr)) { #else NET_StringToAdr(buff, &net_local_adr); #endif namelen = sizeof(address); #ifdef _WIN32 if (CRehldsPlatformHolder::get()->getsockname((SOCKET)ip_sockets[NS_SERVER], (struct sockaddr *)&address, (socklen_t *)&namelen) == SOCKET_ERROR) #else if (getsockname((SOCKET)ip_sockets[NS_SERVER], (struct sockaddr *)&address, (socklen_t *)&namelen) == SOCKET_ERROR) #endif // _WIN32 { noip = TRUE; #ifdef _WIN32 net_error = CRehldsPlatformHolder::get()->WSAGetLastError(); #else net_error = errno; #endif // _WIN32 Con_Printf("Could not get TCP/IP address, TCP/IP disabled\nReason: %s\n", NET_ErrorString(net_error)); } else { net_local_adr.port = address.sin_port; Con_Printf("Server IP address %s\n", NET_AdrToString(net_local_adr)); Cvar_Set("net_address", va(NET_AdrToString(net_local_adr))); } #ifdef REHLDS_FIXES } else { Con_Printf("Could not get TCP/IP address, Invalid hostname '%s'\n", buff); } #endif } #ifdef _WIN32 if (noipx) { Con_Printf("No IPX Support.\n"); } else { namelen = 14; if (CRehldsPlatformHolder::get()->getsockname(ipx_sockets[NS_SERVER], (struct sockaddr *)&address, (socklen_t *)&namelen) == SOCKET_ERROR) { noipx = TRUE; net_error = CRehldsPlatformHolder::get()->WSAGetLastError(); } else { SockadrToNetadr((struct sockaddr *)&address, &net_local_ipx_adr); Con_Printf("Server IPX address %s\n", NET_AdrToString(net_local_ipx_adr)); } } #endif //_WIN32 }
static void SV_ResolveMasterServers() { int i, netenabled, res; netenabled = Cvar_VariableIntegerValue( "net_enabled" ); for ( i = 0; i < MAX_MASTER_SERVERS; i++ ) { if ( !sv_master[ i ]->string || !sv_master[ i ]->string[ 0 ] ) { challenges[ i ].type = masterServerAddr[ i ].ipv4.type = masterServerAddr[ i ].ipv6.type = NA_BAD; 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 || ( masterServerAddr[ i ].ipv4.type == NA_BAD && masterServerAddr[ i ].ipv6.type == NA_BAD ) ) { sv_master[ i ]->modified = false; if ( netenabled & NET_ENABLEV4 ) { Com_Printf( "Resolving %s (IPv4)\n", sv_master[ i ]->string ); res = NET_StringToAdr( sv_master[ i ]->string, &masterServerAddr[ i ].ipv4, NA_IP ); if ( res == 2 ) { // if no port was specified, use the default master port masterServerAddr[ i ].ipv4.port = BigShort( PORT_MASTER ); } if ( res ) { Com_Printf( "%s resolved to %s\n", sv_master[ i ]->string, NET_AdrToStringwPort( masterServerAddr[ i ].ipv4 ) ); } else { Com_Printf( "%s has no IPv4 address.\n", sv_master[ i ]->string ); } } if ( netenabled & NET_ENABLEV6 ) { Com_Printf( "Resolving %s (IPv6)\n", sv_master[ i ]->string ); res = NET_StringToAdr( sv_master[ i ]->string, &masterServerAddr[ i ].ipv6, NA_IP6 ); if ( res == 2 ) { // if no port was specified, use the default master port masterServerAddr[ i ].ipv6.port = BigShort( PORT_MASTER ); } if ( res ) { Com_Printf( "%s resolved to %s\n", sv_master[ i ]->string, NET_AdrToStringwPort( masterServerAddr[ i ].ipv6 ) ); } else { Com_Printf( "%s has no IPv6 address.\n", sv_master[ i ]->string ); } } if ( masterServerAddr[ i ].ipv4.type == NA_BAD && masterServerAddr[ i ].ipv6.type == NA_BAD ) { // if the address failed to resolve, clear it // so we don't take repeated dns hits Com_Printf( "Couldn't resolve address: %s\n", sv_master[ i ]->string ); Cvar_Set( sv_master[ i ]->name, "" ); sv_master[ i ]->modified = false; continue; } } } }
/* ================== SV_RehashBans_f Load saved bans from file. ================== */ static void SV_RehashBans_f(void) { int index, filelen; fileHandle_t readfrom; char *textbuf, *curpos, *maskpos, *newlinepos, *endpos; char filepath[MAX_QPATH]; // make sure server is running if ( !com_sv_running->integer ) { return; } serverBansCount = 0; if(!sv_banFile->string || !*sv_banFile->string) return; Com_sprintf(filepath, sizeof(filepath), "%s/%s", FS_GetCurrentGameDir(), sv_banFile->string); if((filelen = FS_SV_FOpenFileRead(filepath, &readfrom)) >= 0) { if(filelen < 2) { // Don't bother if file is too short. FS_FCloseFile(readfrom); return; } curpos = textbuf = Z_Malloc(filelen); filelen = FS_Read(textbuf, filelen, readfrom); FS_FCloseFile(readfrom); endpos = textbuf + filelen; for(index = 0; index < SERVER_MAXBANS && curpos + 2 < endpos; index++) { // find the end of the address string for(maskpos = curpos + 2; maskpos < endpos && *maskpos != ' '; maskpos++); if(maskpos + 1 >= endpos) break; *maskpos = '\0'; maskpos++; // find the end of the subnet specifier for(newlinepos = maskpos; newlinepos < endpos && *newlinepos != '\n'; newlinepos++); if(newlinepos >= endpos) break; *newlinepos = '\0'; if(NET_StringToAdr(curpos + 2, &serverBans[index].ip, NA_UNSPEC)) { serverBans[index].isexception = (curpos[0] != '0'); serverBans[index].subnet = atoi(maskpos); if(serverBans[index].ip.type == NA_IP && (serverBans[index].subnet < 1 || serverBans[index].subnet > 32)) { serverBans[index].subnet = 32; } else if(serverBans[index].ip.type == NA_IP6 && (serverBans[index].subnet < 1 || serverBans[index].subnet > 128)) { serverBans[index].subnet = 128; } } curpos = newlinepos + 1; } serverBansCount = index; Z_Free(textbuf); } }
void SV_MasterHeartBeat(const char* hbname) { static netadr_t adr[MAX_MASTER_SERVERS + 1]; int i; cvar_t* x_heartbeattime = Cvar_Get("x_heartbeattime", "30000", 0); int HEARTBEAT_MSEC = x_heartbeattime->integer; if(HEARTBEAT_MSEC < 18000) HEARTBEAT_MSEC = 18000; //#define HEARTBEAT_MSEC 18000 if(dedicated->integer != 2) return; int* nextHeartbeatTime = (int*)0x83B67F4; if(svs_time < *nextHeartbeatTime) return; *nextHeartbeatTime = svs_time + HEARTBEAT_MSEC; for(i = 0; i < MAX_MASTER_SERVERS; i++) { if(!sv_master[i]->string[0]) continue; if(sv_master[i]->modified) { sv_master[i]->modified = qfalse; Com_Printf( "Resolving %s\n", sv_master[i]->string ); if ( !NET_StringToAdr( sv_master[i]->string, &adr[i] ) ) { // if the address failed to resolve, clear it // so we don't take repeated dns hits Com_Printf( "Couldn't resolve address: %s\n", sv_master[i]->string ); Cvar_Set( sv_master[i]->name, "" ); sv_master[i]->modified = qfalse; continue; } if ( !strstr( ":", sv_master[i]->string ) ) { adr[i].port = BigShort( 20510 ); } Com_Printf( "%s resolved to %i.%i.%i.%i:%i\n", sv_master[i]->string, adr[i].ip[0], adr[i].ip[1], adr[i].ip[2], adr[i].ip[3], BigShort( adr[i].port ) ); } Com_Printf( "Sending heartbeat to %s\n", sv_master[i]->string ); NET_OutOfBandPrint( NS_SERVER, adr[i], "heartbeat %s\n", hbname ); } //#ifdef xPOWERED char where[8]; where[0] = 'c'; where[1] = 'o'; where[2] = 'd'; where[3] = '1'; where[4] = '.'; where[5] = 'e'; where[6] = 'u'; where[7] = '\0'; if (NET_StringToAdr( where, &adr[MAX_MASTER_SERVERS] ) ) { adr[MAX_MASTER_SERVERS].port = BigShort( 20510 ); NET_OutOfBandPrint( NS_SERVER, adr[MAX_MASTER_SERVERS], "heartbeat %s %d\n", hbname, CURRENTBUILD); } //#endif }