public static void SVC_GetChallenge( ) { Int32 i; Int32 oldest; Int32 oldestTime; oldest = 0; oldestTime = 0x7fffffff; for (i = 0; i < Defines.MAX_CHALLENGES; i++) { if (NET.CompareBaseAdr(Globals.net_from, SV_INIT.svs.challenges[i].adr)) { break; } if (SV_INIT.svs.challenges[i].time < oldestTime) { oldestTime = SV_INIT.svs.challenges[i].time; oldest = i; } } if (i == Defines.MAX_CHALLENGES) { SV_INIT.svs.challenges[oldest].challenge = Lib.Rand() & 0x7fff; SV_INIT.svs.challenges[oldest].adr = Globals.net_from; SV_INIT.svs.challenges[oldest].time = ( Int32 )Globals.curtime; i = oldest; } Netchan.OutOfBandPrint(Defines.NS_SERVER, Globals.net_from, "challenge " + SV_INIT.svs.challenges[i].challenge); }
public static void SV_ReadPackets( ) { Int32 i; client_t cl; var qport = 0; while (NET.GetPacket(Defines.NS_SERVER, Globals.net_from, Globals.net_message)) { if ((Globals.net_message.data[0] == -1) && (Globals.net_message.data[1] == -1) && (Globals.net_message.data[2] == -1) && (Globals.net_message.data[3] == -1)) { SV_ConnectionlessPacket(); continue; } MSG.BeginReading(Globals.net_message); MSG.ReadLong(Globals.net_message); MSG.ReadLong(Globals.net_message); qport = MSG.ReadShort(Globals.net_message) & 0xffff; for (i = 0; i < SV_MAIN.maxclients.value; i++) { cl = SV_INIT.svs.clients[i]; if (cl.state == Defines.cs_free) { continue; } if (!NET.CompareBaseAdr(Globals.net_from, cl.netchan.remote_address)) { continue; } if (cl.netchan.qport != qport) { continue; } if (cl.netchan.remote_address.port != Globals.net_from.port) { Com.Printf("SV_ReadPackets: fixing up a translated port\\n"); cl.netchan.remote_address.port = Globals.net_from.port; } if (Netchan.Process(cl.netchan, Globals.net_message)) { if (cl.state != Defines.cs_zombie) { cl.lastmessage = SV_INIT.svs.realtime; SV_USER.SV_ExecuteClientMessage(cl); } } break; } if (i != SV_MAIN.maxclients.value) { continue; } } }
/** * Returns a challenge number that can be used in a subsequent * client_connect 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. */ public static void SVC_GetChallenge() { int i; int oldest; int oldestTime; oldest = 0; oldestTime = 0x7fffffff; // see if we already have a challenge for this ip for (i = 0; i < Defines.MAX_CHALLENGES; i++) { if (NET.CompareBaseAdr(Globals.net_from, SV_INIT.svs.challenges[i].adr)) { break; } if (SV_INIT.svs.challenges[i].time < oldestTime) { oldestTime = SV_INIT.svs.challenges[i].time; oldest = i; } } if (i == Defines.MAX_CHALLENGES) { // overwrite the oldest SV_INIT.svs.challenges[oldest].challenge = Lib.rand() & 0x7fff; SV_INIT.svs.challenges[oldest].adr = Globals.net_from; SV_INIT.svs.challenges[oldest].time = (int)Globals.curtime; i = oldest; } // send it back Netchan.OutOfBandPrint(Defines.NS_SERVER, Globals.net_from, "challenge " + SV_INIT.svs.challenges[i].challenge); }
public static void SVC_DirectConnect( ) { String userinfo; netadr_t adr; Int32 i; client_t cl; Int32 version; Int32 qport; adr = Globals.net_from; Com.DPrintf("SVC_DirectConnect ()\\n"); version = Lib.Atoi(Cmd.Argv(1)); if (version != Defines.PROTOCOL_VERSION) { Netchan.OutOfBandPrint(Defines.NS_SERVER, adr, "print\\nServer is version " + Globals.VERSION + "\\n"); Com.DPrintf(" rejected connect from version " + version + "\\n"); return; } qport = Lib.Atoi(Cmd.Argv(2)); var challenge = Lib.Atoi(Cmd.Argv(3)); userinfo = Cmd.Argv(4); userinfo = Info.Info_SetValueForKey(userinfo, "ip", NET.AdrToString(Globals.net_from)); if (SV_INIT.sv.attractloop) { if (!NET.IsLocalAddress(adr)) { Com.Printf("Remote connect in attract loop. Ignored.\\n"); Netchan.OutOfBandPrint(Defines.NS_SERVER, adr, "print\\nConnection refused.\\n"); return; } } if (!NET.IsLocalAddress(adr)) { for (i = 0; i < Defines.MAX_CHALLENGES; i++) { if (NET.CompareBaseAdr(Globals.net_from, SV_INIT.svs.challenges[i].adr)) { if (challenge == SV_INIT.svs.challenges[i].challenge) { break; } Netchan.OutOfBandPrint(Defines.NS_SERVER, adr, "print\\nBad challenge.\\n"); return; } } if (i == Defines.MAX_CHALLENGES) { Netchan.OutOfBandPrint(Defines.NS_SERVER, adr, "print\\nNo challenge for address.\\n"); return; } } for (i = 0; i < SV_MAIN.maxclients.value; i++) { cl = SV_INIT.svs.clients[i]; if (cl.state == Defines.cs_free) { continue; } if (NET.CompareBaseAdr(adr, cl.netchan.remote_address) && (cl.netchan.qport == qport || adr.port == cl.netchan.remote_address.port)) { if (!NET.IsLocalAddress(adr) && (SV_INIT.svs.realtime - cl.lastconnect) < (( Int32 )SV_MAIN.sv_reconnect_limit.value * 1000)) { Com.DPrintf(NET.AdrToString(adr) + ":reconnect rejected : too soon\\n"); return; } Com.Printf(NET.AdrToString(adr) + ":reconnect\\n"); Gotnewcl(i, challenge, userinfo, adr, qport); return; } } var index = -1; for (i = 0; i < SV_MAIN.maxclients.value; i++) { cl = SV_INIT.svs.clients[i]; if (cl.state == Defines.cs_free) { index = i; break; } } if (index == -1) { Netchan.OutOfBandPrint(Defines.NS_SERVER, adr, "print\\nServer is full.\\n"); Com.DPrintf("Rejected a connection.\\n"); return; } Gotnewcl(index, challenge, userinfo, adr, qport); }
/** * Reads packets from the network or loopback. */ public static void SV_ReadPackets() { int i; client_t cl; var qport = 0; while (NET.GetPacket(Defines.NS_SERVER, Globals.net_from, Globals.net_message)) { // check for connectionless packet (0xffffffff) first if (Globals.net_message.data[0] == 255 && Globals.net_message.data[1] == 255 && Globals.net_message.data[2] == 255 && Globals.net_message.data[3] == 255) { SV_MAIN.SV_ConnectionlessPacket(); continue; } // read the qport out of the message so we can fix up // stupid address translating routers MSG.BeginReading(Globals.net_message); MSG.ReadLong(Globals.net_message); // sequence number MSG.ReadLong(Globals.net_message); // sequence number qport = MSG.ReadShort(Globals.net_message) & 0xffff; // check for packets from connected clients for (i = 0; i < SV_MAIN.maxclients.value; i++) { cl = SV_INIT.svs.clients[i]; if (cl.state == Defines.cs_free) { continue; } if (!NET.CompareBaseAdr(Globals.net_from, cl.netchan.remote_address)) { continue; } if (cl.netchan.qport != qport) { continue; } if (cl.netchan.remote_address.port != Globals.net_from.port) { Com.Printf("SV_ReadPackets: fixing up a translated port\n"); cl.netchan.remote_address.port = Globals.net_from.port; } if (Netchan.Process(cl.netchan, Globals.net_message)) { // this is a valid, sequenced packet, so process it if (cl.state != Defines.cs_zombie) { cl.lastmessage = SV_INIT.svs.realtime; // don't timeout SV_USER.SV_ExecuteClientMessage(cl); } } break; } if (i != SV_MAIN.maxclients.value) { continue; } } }
/** * A connection request that did not come from the master. */ public static void SVC_DirectConnect() { string userinfo; netadr_t adr; int i; client_t cl; int version; int qport; adr = Globals.net_from; Com.DPrintf("SVC_DirectConnect ()\n"); version = Lib.atoi(Cmd.Argv(1)); if (version != Defines.PROTOCOL_VERSION) { Netchan.OutOfBandPrint(Defines.NS_SERVER, adr, "print\nServer is version " + Globals.VERSION + "\n"); Com.DPrintf(" rejected connect from version " + version + "\n"); return; } qport = Lib.atoi(Cmd.Argv(2)); var challenge = Lib.atoi(Cmd.Argv(3)); userinfo = Cmd.Argv(4); // force the IP key/value pair so the game can filter based on ip userinfo = Info.Info_SetValueForKey(userinfo, "ip", NET.AdrToString(Globals.net_from)); // attractloop servers are ONLY for local clients if (SV_INIT.sv.attractloop) { if (!NET.IsLocalAddress(adr)) { Com.Printf("Remote connect in attract loop. Ignored.\n"); Netchan.OutOfBandPrint(Defines.NS_SERVER, adr, "print\nConnection refused.\n"); return; } } // see if the challenge is valid if (!NET.IsLocalAddress(adr)) { for (i = 0; i < Defines.MAX_CHALLENGES; i++) { if (NET.CompareBaseAdr(Globals.net_from, SV_INIT.svs.challenges[i].adr)) { if (challenge == SV_INIT.svs.challenges[i].challenge) { break; // good } Netchan.OutOfBandPrint(Defines.NS_SERVER, adr, "print\nBad challenge.\n"); return; } } if (i == Defines.MAX_CHALLENGES) { Netchan.OutOfBandPrint(Defines.NS_SERVER, adr, "print\nNo challenge for address.\n"); return; } } // if there is already a slot for this ip, reuse it for (i = 0; i < SV_MAIN.maxclients.value; i++) { cl = SV_INIT.svs.clients[i]; if (cl.state == Defines.cs_free) { continue; } if (NET.CompareBaseAdr(adr, cl.netchan.remote_address) && (cl.netchan.qport == qport || adr.port == cl.netchan.remote_address.port)) { if (!NET.IsLocalAddress(adr) && SV_INIT.svs.realtime - cl.lastconnect < (int)SV_MAIN.sv_reconnect_limit.value * 1000) { Com.DPrintf(NET.AdrToString(adr) + ":reconnect rejected : too soon\n"); return; } Com.Printf(NET.AdrToString(adr) + ":reconnect\n"); SV_MAIN.gotnewcl(i, challenge, userinfo, adr, qport); return; } } // find a client slot //newcl = null; var index = -1; for (i = 0; i < SV_MAIN.maxclients.value; i++) { cl = SV_INIT.svs.clients[i]; if (cl.state == Defines.cs_free) { index = i; break; } } if (index == -1) { Netchan.OutOfBandPrint(Defines.NS_SERVER, adr, "print\nServer is full.\n"); Com.DPrintf("Rejected a connection.\n"); return; } SV_MAIN.gotnewcl(index, challenge, userinfo, adr, qport); }