X-Git-Url: http://de.git.xonotic.org/?p=xonotic%2Fdarkplaces.git;a=blobdiff_plain;f=netconn.c;h=3f0796e54e9485027ae685c18c4f981cfc751412;hp=ea6e92c0b90595eafbc5216d044029a24f7bebb9;hb=05b2bea177017a0e9f6a03609e9f9521e2e2941f;hpb=8163f0466cc2e540ac4a2701c8b38fa85562c99e diff --git a/netconn.c b/netconn.c index ea6e92c0..3f0796e5 100755 --- a/netconn.c +++ b/netconn.c @@ -84,10 +84,11 @@ static cvar_t net_slist_favorites = {CVAR_SAVE | CVAR_NQUSERINFOHACK, "net_slist static cvar_t gameversion = {0, "gameversion", "0", "version of game data (mod-specific) to be sent to querying clients"}; static cvar_t gameversion_min = {0, "gameversion_min", "-1", "minimum version of game data (mod-specific), when client and server gameversion mismatch in the server browser the server is shown as incompatible; if -1, gameversion is used alone"}; static cvar_t gameversion_max = {0, "gameversion_max", "-1", "maximum version of game data (mod-specific), when client and server gameversion mismatch in the server browser the server is shown as incompatible; if -1, gameversion is used alone"}; -static cvar_t rcon_restricted_password = {CVAR_PRIVATE, "rcon_restricted_password", "", "password to authenticate rcon commands in restricted mode"}; +static cvar_t rcon_restricted_password = {CVAR_PRIVATE, "rcon_restricted_password", "", "password to authenticate rcon commands in restricted mode; may be set to a string of the form user1:pass1 user2:pass2 user3:pass3 to allow multiple user accounts - the client then has to specify ONE of these combinations"}; static cvar_t rcon_restricted_commands = {0, "rcon_restricted_commands", "", "allowed commands for rcon when the restricted mode password was used"}; static cvar_t rcon_secure_maxdiff = {0, "rcon_secure_maxdiff", "5", "maximum time difference between rcon request and server system clock (to protect against replay attack)"}; extern cvar_t rcon_secure; +extern cvar_t rcon_secure_challengetimeout; /* statistic counters */ static int packetsSent = 0; @@ -131,9 +132,13 @@ cvar_t sv_netport = {0, "port", "26000", "server port for players to connect to" cvar_t net_address = {0, "net_address", "", "network address to open ipv4 ports on (if empty, use default interfaces)"}; cvar_t net_address_ipv6 = {0, "net_address_ipv6", "", "network address to open ipv6 ports on (if empty, use default interfaces)"}; -char net_extresponse[NET_EXTRESPONSE_MAX][1400]; -int net_extresponse_count = 0; -int net_extresponse_last = 0; +char cl_net_extresponse[NET_EXTRESPONSE_MAX][1400]; +int cl_net_extresponse_count = 0; +int cl_net_extresponse_last = 0; + +char sv_net_extresponse[NET_EXTRESPONSE_MAX][1400]; +int sv_net_extresponse_count = 0; +int sv_net_extresponse_last = 0; // ServerList interface serverlist_mask_t serverlist_andmasks[SERVERLIST_ANDMASKCOUNT]; @@ -143,15 +148,16 @@ serverlist_infofield_t serverlist_sortbyfield; int serverlist_sortflags; int serverlist_viewcount = 0; -serverlist_entry_t *serverlist_viewlist[SERVERLIST_VIEWLISTSIZE]; +unsigned short serverlist_viewlist[SERVERLIST_VIEWLISTSIZE]; -int serverlist_cachecount; -serverlist_entry_t serverlist_cache[SERVERLIST_TOTALSIZE]; +int serverlist_maxcachecount = 0; +int serverlist_cachecount = 0; +serverlist_entry_t *serverlist_cache = NULL; qboolean serverlist_consoleoutput; static int nFavorites = 0; -static lhnetaddress_t favorites[256]; +static lhnetaddress_t favorites[MAX_FAVORITESERVERS]; void NetConn_UpdateFavorites(void) { @@ -179,7 +185,7 @@ static void _ServerList_ViewList_Helper_InsertBefore( int index, serverlist_entr for( ; i > index ; i-- ) serverlist_viewlist[ i ] = serverlist_viewlist[ i - 1 ]; - serverlist_viewlist[index] = entry; + serverlist_viewlist[index] = (int)(entry - serverlist_cache); } /// we suppose serverlist_viewcount to be valid, ie > 0 @@ -425,11 +431,11 @@ static void ServerList_ViewList_Insert( serverlist_entry_t *entry ) // two special cases // check whether to insert it as new first item - if( _ServerList_Entry_Compare( entry, serverlist_viewlist[0] ) ) { + if( _ServerList_Entry_Compare( entry, ServerList_GetViewEntry(0) ) ) { _ServerList_ViewList_Helper_InsertBefore( 0, entry ); return; } // check whether to insert it as new last item - else if( !_ServerList_Entry_Compare( entry, serverlist_viewlist[serverlist_viewcount - 1] ) ) { + else if( !_ServerList_Entry_Compare( entry, ServerList_GetViewEntry(serverlist_viewcount - 1) ) ) { _ServerList_ViewList_Helper_InsertBefore( serverlist_viewcount, entry ); return; } @@ -439,7 +445,7 @@ static void ServerList_ViewList_Insert( serverlist_entry_t *entry ) { mid = (start + end) / 2; // test the item that lies in the middle between start and end - if( _ServerList_Entry_Compare( entry, serverlist_viewlist[mid] ) ) + if( _ServerList_Entry_Compare( entry, ServerList_GetViewEntry(mid) ) ) // the item has to be in the upper half end = mid; else @@ -454,7 +460,7 @@ static void ServerList_ViewList_Remove( serverlist_entry_t *entry ) int i; for( i = 0; i < serverlist_viewcount; i++ ) { - if (serverlist_viewlist[i] == entry) + if (ServerList_GetViewEntry(i) == entry) { _ServerList_ViewList_Helper_Remove(i); break; @@ -508,6 +514,11 @@ void ServerList_GetPlayerStatistics(int *numplayerspointer, int *maxplayerspoint static void _ServerList_Test(void) { int i; + if (serverlist_maxcachecount <= 1024) + { + serverlist_maxcachecount = 1024; + serverlist_cache = (serverlist_entry_t *)Mem_Realloc(netconn_mempool, (void *)serverlist_cache, sizeof(serverlist_entry_t) * serverlist_maxcachecount); + } for( i = 0 ; i < 1024 ; i++ ) { memset( &serverlist_cache[serverlist_cachecount], 0, sizeof( serverlist_entry_t ) ); serverlist_cache[serverlist_cachecount].info.ping = 1000 + 1024 - i; @@ -530,6 +541,8 @@ void ServerList_QueryList(qboolean resetcache, qboolean querydp, qboolean queryq serverreplycount = 0; serverlist_cachecount = 0; serverlist_viewcount = 0; + serverlist_maxcachecount = 0; + serverlist_cache = (serverlist_entry_t *)Mem_Realloc(netconn_mempool, (void *)serverlist_cache, sizeof(serverlist_entry_t) * serverlist_maxcachecount); } else { // refresh all entries int n; @@ -648,9 +661,9 @@ int NetConn_SendUnreliableMessage(netconn_t *conn, sizebuf_t *data, protocolvers sendreliable = true; } // outgoing unreliable packet number, and outgoing reliable packet number (0 or 1) - *((int *)(sendbuffer + 0)) = LittleLong((unsigned int)conn->outgoing_unreliable_sequence | ((unsigned int)sendreliable<<31)); + StoreLittleLong(sendbuffer, (unsigned int)conn->outgoing_unreliable_sequence | ((unsigned int)sendreliable<<31)); // last received unreliable packet number, and last received reliable packet number (0 or 1) - *((int *)(sendbuffer + 4)) = LittleLong((unsigned int)conn->qw.incoming_sequence | ((unsigned int)conn->qw.incoming_reliable_sequence<<31)); + StoreLittleLong(sendbuffer + 4, (unsigned int)conn->qw.incoming_sequence | ((unsigned int)conn->qw.incoming_reliable_sequence<<31)); packetLen = 8; conn->outgoing_unreliable_sequence++; // client sends qport in every packet @@ -698,7 +711,6 @@ int NetConn_SendUnreliableMessage(netconn_t *conn, sizebuf_t *data, protocolvers unsigned int packetLen; unsigned int dataLen; unsigned int eom; - unsigned int *header; // if a reliable message fragment has been lost, send it again if (conn->sendMessageLength && (realtime - conn->lastSendTime) > 1.0) @@ -716,9 +728,8 @@ int NetConn_SendUnreliableMessage(netconn_t *conn, sizebuf_t *data, protocolvers packetLen = NET_HEADERSIZE + dataLen; - header = (unsigned int *)sendbuffer; - header[0] = BigLong(packetLen | (NETFLAG_DATA | eom)); - header[1] = BigLong(conn->nq.sendSequence - 1); + StoreBigLong(sendbuffer, packetLen | (NETFLAG_DATA | eom)); + StoreBigLong(sendbuffer + 4, conn->nq.sendSequence - 1); memcpy(sendbuffer + NET_HEADERSIZE, conn->sendMessage, dataLen); conn->outgoing_netgraph[conn->outgoing_packetcounter].reliablebytes += packetLen + 28; @@ -765,9 +776,8 @@ int NetConn_SendUnreliableMessage(netconn_t *conn, sizebuf_t *data, protocolvers packetLen = NET_HEADERSIZE + dataLen; - header = (unsigned int *)sendbuffer; - header[0] = BigLong(packetLen | (NETFLAG_DATA | eom)); - header[1] = BigLong(conn->nq.sendSequence); + StoreBigLong(sendbuffer, packetLen | (NETFLAG_DATA | eom)); + StoreBigLong(sendbuffer + 4, conn->nq.sendSequence); memcpy(sendbuffer + NET_HEADERSIZE, conn->sendMessage, dataLen); conn->nq.sendSequence++; @@ -794,9 +804,8 @@ int NetConn_SendUnreliableMessage(netconn_t *conn, sizebuf_t *data, protocolvers return -1; } - header = (unsigned int *)sendbuffer; - header[0] = BigLong(packetLen | NETFLAG_UNRELIABLE); - header[1] = BigLong(conn->outgoing_unreliable_sequence); + StoreBigLong(sendbuffer, packetLen | NETFLAG_UNRELIABLE); + StoreBigLong(sendbuffer + 4, conn->outgoing_unreliable_sequence); memcpy(sendbuffer + NET_HEADERSIZE, data->data, data->cursize); conn->outgoing_unreliable_sequence++; @@ -855,7 +864,8 @@ void NetConn_OpenClientPort(const char *addressstring, lhnetaddresstype_t addres { cl_sockets[cl_numsockets++] = s; LHNETADDRESS_ToString(LHNET_AddressFromSocket(s), addressstring2, sizeof(addressstring2), true); - Con_Printf("Client opened a socket on address %s\n", addressstring2); + if (addresstype != LHNETADDRESSTYPE_LOOP) + Con_Printf("Client opened a socket on address %s\n", addressstring2); } else { @@ -880,7 +890,9 @@ void NetConn_OpenClientPorts(void) Con_Printf("Client using port %i\n", port); NetConn_OpenClientPort(NULL, LHNETADDRESSTYPE_LOOP, 2); NetConn_OpenClientPort(net_address.string, LHNETADDRESSTYPE_INET4, port); +#ifdef SUPPORTIPV6 NetConn_OpenClientPort(net_address_ipv6.string, LHNETADDRESSTYPE_INET6, port); +#endif } void NetConn_CloseServerPorts(void) @@ -910,7 +922,8 @@ qboolean NetConn_OpenServerPort(const char *addressstring, lhnetaddresstype_t ad { sv_sockets[sv_numsockets++] = s; LHNETADDRESS_ToString(LHNET_AddressFromSocket(s), addressstring2, sizeof(addressstring2), true); - Con_Printf("Server listening on address %s\n", addressstring2); + if (addresstype != LHNETADDRESSTYPE_LOOP) + Con_Printf("Server listening on address %s\n", addressstring2); return true; } else @@ -944,8 +957,12 @@ void NetConn_OpenServerPorts(int opennetports) NetConn_OpenServerPort(NULL, LHNETADDRESSTYPE_LOOP, 1, 1); if (opennetports) { +#ifdef SUPPORTIPV6 qboolean ip4success = NetConn_OpenServerPort(net_address.string, LHNETADDRESSTYPE_INET4, port, 100); NetConn_OpenServerPort(net_address_ipv6.string, LHNETADDRESSTYPE_INET6, port, ip4success ? 1 : 100); +#else + NetConn_OpenServerPort(net_address.string, LHNETADDRESSTYPE_INET4, port, 100); +#endif } if (sv_numsockets == 0) Host_Error("NetConn_OpenServerPorts: unable to open any ports!"); @@ -1022,6 +1039,8 @@ static int clientport2 = -1; static int hostport = -1; void NetConn_UpdateSockets(void) { + int i, j; + if (cls.state != ca_dedicated) { if (clientport2 != cl_netport.integer) @@ -1045,6 +1064,23 @@ void NetConn_UpdateSockets(void) if (sv.active) Con_Print("Changing \"port\" will not take effect until \"map\" command is executed.\n"); } + + for (j = 0;j < MAX_RCONS;j++) + { + i = (cls.rcon_ringpos + j + 1) % MAX_RCONS; + if(cls.rcon_commands[i][0]) + { + if(realtime > cls.rcon_timeout[i]) + { + char s[128]; + LHNETADDRESS_ToString(&cls.rcon_addresses[i], s, sizeof(s), true); + Con_Printf("rcon to %s (for command %s) failed: challenge request timed out\n", s, cls.rcon_commands[i]); + cls.rcon_commands[i][0] = 0; + --cls.rcon_trying; + break; + } + } + } } static int NetConn_ReceivedMessage(netconn_t *conn, unsigned char *data, int length, protocolversion_t protocol, double newtimeout) @@ -1058,7 +1094,7 @@ static int NetConn_ReceivedMessage(netconn_t *conn, unsigned char *data, int len int sequence, sequence_ack; int reliable_ack, reliable_message; int count; - int qport; + //int qport; sequence = LittleLong(*((int *)(data + 0))); sequence_ack = LittleLong(*((int *)(data + 4))); @@ -1071,7 +1107,7 @@ static int NetConn_ReceivedMessage(netconn_t *conn, unsigned char *data, int len if (length < 2) return 0; // TODO: use qport to identify that this client really is who they say they are? (and elsewhere in the code to identify the connection without a port match?) - qport = LittleShort(*((int *)(data + 8))); + //qport = LittleShort(*((int *)(data + 8))); data += 2; length -= 2; } @@ -1133,13 +1169,13 @@ static int NetConn_ReceivedMessage(netconn_t *conn, unsigned char *data, int len unsigned int sequence; int qlength; - qlength = (unsigned int)BigLong(((int *)data)[0]); + qlength = (unsigned int)BuffBigLong(data); flags = qlength & ~NETFLAG_LENGTH_MASK; qlength &= NETFLAG_LENGTH_MASK; // control packets were already handled if (!(flags & NETFLAG_CTL) && qlength == length) { - sequence = BigLong(((int *)data)[1]); + sequence = BuffBigLong(data + 4); packetsReceived++; data += 8; length -= 8; @@ -1199,7 +1235,6 @@ static int NetConn_ReceivedMessage(netconn_t *conn, unsigned char *data, int len unsigned int packetLen; unsigned int dataLen; unsigned int eom; - unsigned int *header; conn->sendMessageLength -= MAX_PACKETFRAGMENT; memmove(conn->sendMessage, conn->sendMessage+MAX_PACKETFRAGMENT, conn->sendMessageLength); @@ -1217,9 +1252,8 @@ static int NetConn_ReceivedMessage(netconn_t *conn, unsigned char *data, int len packetLen = NET_HEADERSIZE + dataLen; - header = (unsigned int *)sendbuffer; - header[0] = BigLong(packetLen | (NETFLAG_DATA | eom)); - header[1] = BigLong(conn->nq.sendSequence); + StoreBigLong(sendbuffer, packetLen | (NETFLAG_DATA | eom)); + StoreBigLong(sendbuffer + 4, conn->nq.sendSequence); memcpy(sendbuffer + NET_HEADERSIZE, conn->sendMessage, dataLen); conn->nq.sendSequence++; @@ -1242,11 +1276,11 @@ static int NetConn_ReceivedMessage(netconn_t *conn, unsigned char *data, int len } else if (flags & NETFLAG_DATA) { - unsigned int temppacket[2]; + unsigned char temppacket[8]; conn->incoming_netgraph[conn->incoming_packetcounter].reliablebytes += originallength + 28; conn->outgoing_netgraph[conn->outgoing_packetcounter].ackbytes += 8 + 28; - temppacket[0] = BigLong(8 | NETFLAG_ACK); - temppacket[1] = BigLong(sequence); + StoreBigLong(temppacket, 8 | NETFLAG_ACK); + StoreBigLong(temppacket + 4, sequence); NetConn_Write(conn->mysocket, (unsigned char *)temppacket, 8, &conn->peeraddress); if (sequence == conn->nq.receiveSequence) { @@ -1350,6 +1384,11 @@ static int NetConn_ClientParsePacket_ServerList_ProcessReply(const char *address if (serverlist_cachecount == SERVERLIST_TOTALSIZE) return -1; + if (serverlist_maxcachecount <= serverlist_cachecount) + { + serverlist_maxcachecount += 64; + serverlist_cache = (serverlist_entry_t *)Mem_Realloc(netconn_mempool, (void *)serverlist_cache, sizeof(serverlist_entry_t) * serverlist_maxcachecount); + } entry = &serverlist_cache[n]; memset(entry, 0, sizeof(*entry)); @@ -1425,13 +1464,19 @@ static qboolean NetConn_ClientParsePacket_ServerList_PrepareQuery( int protocol, if( !strcmp( ipstring, serverlist_cache[ n ].info.cname ) ) break; - entry = &serverlist_cache[n]; - if( n < serverlist_cachecount ) { // the entry has already been queried once or return true; } + if (serverlist_maxcachecount <= n) + { + serverlist_maxcachecount += 64; + serverlist_cache = (serverlist_entry_t *)Mem_Realloc(netconn_mempool, (void *)serverlist_cache, sizeof(serverlist_entry_t) * serverlist_maxcachecount); + } + + entry = &serverlist_cache[n]; + memset(entry, 0, sizeof(entry)); entry->protocol = protocol; // store the data the engine cares about (address and ping) @@ -1554,12 +1599,63 @@ static int NetConn_ClientParsePacket(lhnetsocket_t *mysocket, unsigned char *dat Com_HexDumpToConsole(data, length); } + if (length > 10 && !memcmp(string, "challenge ", 10) && cls.rcon_trying) + { + int i = 0, j; + for (j = 0;j < MAX_RCONS;j++) + { + // note: this value from i is used outside the loop too... + i = (cls.rcon_ringpos + j) % MAX_RCONS; + if(cls.rcon_commands[i][0]) + if (!LHNETADDRESS_Compare(peeraddress, &cls.rcon_addresses[i])) + break; + } + if (j < MAX_RCONS) + { + char buf[1500]; + char argbuf[1500]; + const char *e; + int n; + dpsnprintf(argbuf, sizeof(argbuf), "%s %s", string + 10, cls.rcon_commands[i]); + memcpy(buf, "\377\377\377\377srcon HMAC-MD4 CHALLENGE ", 29); + + e = strchr(rcon_password.string, ' '); + n = e ? e-rcon_password.string : (int)strlen(rcon_password.string); + + if(HMAC_MDFOUR_16BYTES((unsigned char *) (buf + 29), (unsigned char *) argbuf, strlen(argbuf), (unsigned char *) rcon_password.string, n)) + { + int k; + buf[45] = ' '; + strlcpy(buf + 46, argbuf, sizeof(buf) - 46); + NetConn_Write(mysocket, buf, 46 + strlen(buf + 46), peeraddress); + cls.rcon_commands[i][0] = 0; + --cls.rcon_trying; + + for (k = 0;k < MAX_RCONS;k++) + if(cls.rcon_commands[k][0]) + if (!LHNETADDRESS_Compare(peeraddress, &cls.rcon_addresses[k])) + break; + if(k < MAX_RCONS) + { + int l; + NetConn_WriteString(mysocket, "\377\377\377\377getchallenge", peeraddress); + // extend the timeout on other requests as we asked for a challenge + for (l = 0;l < MAX_RCONS;l++) + if(cls.rcon_commands[l][0]) + if (!LHNETADDRESS_Compare(peeraddress, &cls.rcon_addresses[l])) + cls.rcon_timeout[l] = realtime + rcon_secure_challengetimeout.value; + } + + return true; // we used up the challenge, so we can't use this oen for connecting now anyway + } + } + } if (length > 10 && !memcmp(string, "challenge ", 10) && cls.connect_trying) { // darkplaces or quake3 char protocolnames[1400]; Protocol_Names(protocolnames, sizeof(protocolnames)); - Con_Printf("\"%s\" received, sending connect request back to %s\n", string, addressstring2); + Con_DPrintf("\"%s\" received, sending connect request back to %s\n", string, addressstring2); M_Update_Return_Reason("Got challenge response"); // update the server IP in the userinfo (QW servers expect this, and it is used by the reconnect command) InfoString_SetValue(cls.userinfo, sizeof(cls.userinfo), "*ip", addressstring2); @@ -1723,17 +1819,17 @@ static int NetConn_ClientParsePacket(lhnetsocket_t *mysocket, unsigned char *dat } if (!strncmp(string, "extResponse ", 12)) { - ++net_extresponse_count; - if(net_extresponse_count > NET_EXTRESPONSE_MAX) - net_extresponse_count = NET_EXTRESPONSE_MAX; - net_extresponse_last = (net_extresponse_last + 1) % NET_EXTRESPONSE_MAX; - dpsnprintf(net_extresponse[net_extresponse_last], sizeof(net_extresponse[net_extresponse_last]), "'%s' %s", addressstring2, string + 12); + ++cl_net_extresponse_count; + if(cl_net_extresponse_count > NET_EXTRESPONSE_MAX) + cl_net_extresponse_count = NET_EXTRESPONSE_MAX; + cl_net_extresponse_last = (cl_net_extresponse_last + 1) % NET_EXTRESPONSE_MAX; + dpsnprintf(cl_net_extresponse[cl_net_extresponse_last], sizeof(cl_net_extresponse[cl_net_extresponse_last]), "\"%s\" %s", addressstring2, string + 12); return true; } if (!strncmp(string, "ping", 4)) { - if (developer.integer >= 10) - Con_Printf("Received ping from %s, sending ack\n", addressstring2); + if (developer_extra.integer) + Con_DPrintf("Received ping from %s, sending ack\n", addressstring2); NetConn_WriteString(mysocket, "\377\377\377\377ack", peeraddress); return true; } @@ -1823,7 +1919,7 @@ static int NetConn_ClientParsePacket(lhnetsocket_t *mysocket, unsigned char *dat return ret; } // netquake control packets, supported for compatibility only - if (length >= 5 && (control = BigLong(*((int *)data))) && (control & (~NETFLAG_LENGTH_MASK)) == (int)NETFLAG_CTL && (control & NETFLAG_LENGTH_MASK) == length) + if (length >= 5 && (control = BuffBigLong(data)) && (control & (~NETFLAG_LENGTH_MASK)) == (int)NETFLAG_CTL && (control & NETFLAG_LENGTH_MASK) == length) { int n; serverlist_info_t *info; @@ -1837,8 +1933,8 @@ static int NetConn_ClientParsePacket(lhnetsocket_t *mysocket, unsigned char *dat switch (c) { case CCREP_ACCEPT: - if (developer.integer >= 10) - Con_Printf("Datagram_ParseConnectionless: received CCREP_ACCEPT from %s.\n", addressstring2); + if (developer_extra.integer) + Con_DPrintf("Datagram_ParseConnectionless: received CCREP_ACCEPT from %s.\n", addressstring2); if (cls.connect_trying) { lhnetaddress_t clientportaddress; @@ -1851,14 +1947,14 @@ static int NetConn_ClientParsePacket(lhnetsocket_t *mysocket, unsigned char *dat } break; case CCREP_REJECT: - if (developer.integer >= 10) - Con_Printf("Datagram_ParseConnectionless: received CCREP_REJECT from %s.\n", addressstring2); + if (developer_extra.integer) + Con_DPrintf("Datagram_ParseConnectionless: received CCREP_REJECT from %s.\n", addressstring2); cls.connect_trying = false; M_Update_Return_Reason((char *)MSG_ReadString()); break; case CCREP_SERVER_INFO: - if (developer.integer >= 10) - Con_Printf("Datagram_ParseConnectionless: received CCREP_SERVER_INFO from %s.\n", addressstring2); + if (developer_extra.integer) + Con_DPrintf("Datagram_ParseConnectionless: received CCREP_SERVER_INFO from %s.\n", addressstring2); // LordHavoc: because the quake server may report weird addresses // we just ignore it and keep the real address MSG_ReadString(); @@ -1880,19 +1976,19 @@ static int NetConn_ClientParsePacket(lhnetsocket_t *mysocket, unsigned char *dat break; case CCREP_RCON: // RocketGuy: ProQuake rcon support - if (developer.integer >= 10) - Con_Printf("Datagram_ParseConnectionless: received CCREP_RCON from %s.\n", addressstring2); + if (developer_extra.integer) + Con_DPrintf("Datagram_ParseConnectionless: received CCREP_RCON from %s.\n", addressstring2); Con_Printf("%s\n", MSG_ReadString()); break; case CCREP_PLAYER_INFO: // we got a CCREP_PLAYER_INFO?? - //if (developer.integer >= 10) + //if (developer_extra.integer) Con_Printf("Datagram_ParseConnectionless: received CCREP_PLAYER_INFO from %s.\n", addressstring2); break; case CCREP_RULE_INFO: // we got a CCREP_RULE_INFO?? - //if (developer.integer >= 10) + //if (developer_extra.integer) Con_Printf("Datagram_ParseConnectionless: received CCREP_RULE_INFO from %s.\n", addressstring2); break; default: @@ -2024,13 +2120,19 @@ void NetConn_ClientFrame(void) MSG_WriteByte(&net_message, CCREQ_CONNECT); MSG_WriteString(&net_message, "QUAKE"); MSG_WriteByte(&net_message, NET_PROTOCOL_VERSION); - *((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK)); + StoreBigLong(net_message.data, NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK)); NetConn_Write(cls.connect_mysocket, net_message.data, net_message.cursize, &cls.connect_address); SZ_Clear(&net_message); } for (i = 0;i < cl_numsockets;i++) + { while (cl_sockets[i] && (length = NetConn_Read(cl_sockets[i], readbuffer, sizeof(readbuffer), &peeraddress)) > 0) + { +// R_TimeReport("clientreadnetwork"); NetConn_ClientParsePacket(cl_sockets[i], readbuffer, length, &peeraddress); +// R_TimeReport("clientparsepacket"); + } + } NetConn_QueryQueueFrame(); if (cls.netcon && realtime > cls.netcon->timeout && !sv.active) { @@ -2111,7 +2213,7 @@ static qboolean NetConn_BuildStatusResponse(const char* challenge, char* out_msg "%s", fullstatus ? "statusResponse" : "infoResponse", gamename, com_modname, gameversion.integer, svs.maxclients, - nb_clients, nb_bots, sv.name, hostname.string, NET_PROTOCOL_VERSION, + nb_clients, nb_bots, sv.worldbasename, hostname.string, NET_PROTOCOL_VERSION, *qcstatus ? "\\qcstatus\\" : "", qcstatus, challenge ? "\\challenge\\" : "", challenge ? challenge : "", fullstatus ? "\n" : ""); @@ -2292,9 +2394,9 @@ void NetConn_ClearConnectFlood(lhnetaddress_t *peeraddress) } } -typedef qboolean (*rcon_matchfunc_t) (const char *password, const char *hash, const char *s, int slen); +typedef qboolean (*rcon_matchfunc_t) (lhnetaddress_t *peeraddress, const char *password, const char *hash, const char *s, int slen); -qboolean hmac_mdfour_matching(const char *password, const char *hash, const char *s, int slen) +qboolean hmac_mdfour_time_matching(lhnetaddress_t *peeraddress, const char *password, const char *hash, const char *s, int slen) { char mdfourbuf[16]; long t1, t2; @@ -2310,23 +2412,88 @@ qboolean hmac_mdfour_matching(const char *password, const char *hash, const char return !memcmp(mdfourbuf, hash, 16); } -qboolean plaintext_matching(const char *password, const char *hash, const char *s, int slen) +qboolean hmac_mdfour_challenge_matching(lhnetaddress_t *peeraddress, const char *password, const char *hash, const char *s, int slen) +{ + char mdfourbuf[16]; + int i; + + if(slen < (int)(sizeof(challenge[0].string)) - 1) + return false; + + // validate the challenge + for (i = 0;i < MAX_CHALLENGES;i++) + if(challenge[i].time > 0) + if (!LHNETADDRESS_Compare(peeraddress, &challenge[i].address) && !strncmp(challenge[i].string, s, sizeof(challenge[0].string) - 1)) + break; + // if the challenge is not recognized, drop the packet + if (i == MAX_CHALLENGES) + return false; + + if(!HMAC_MDFOUR_16BYTES((unsigned char *) mdfourbuf, (unsigned char *) s, slen, (unsigned char *) password, strlen(password))) + return false; + + if(memcmp(mdfourbuf, hash, 16)) + return false; + + // unmark challenge to prevent replay attacks + challenge[i].time = 0; + + return true; +} + +qboolean plaintext_matching(lhnetaddress_t *peeraddress, const char *password, const char *hash, const char *s, int slen) { return !strcmp(password, hash); } /// returns a string describing the user level, or NULL for auth failure -const char *RCon_Authenticate(const char *password, const char *s, const char *endpos, rcon_matchfunc_t comparator, const char *cs, int cslen) +const char *RCon_Authenticate(lhnetaddress_t *peeraddress, const char *password, const char *s, const char *endpos, rcon_matchfunc_t comparator, const char *cs, int cslen) { - const char *text; + const char *text, *userpass_start, *userpass_end, *userpass_startpass; + static char buf[MAX_INPUTLINE]; qboolean hasquotes; + qboolean restricted = false; + qboolean have_usernames = false; - if(comparator(rcon_password.string, password, cs, cslen)) - return "rcon"; + userpass_start = rcon_password.string; + while((userpass_end = strchr(userpass_start, ' '))) + { + have_usernames = true; + strlcpy(buf, userpass_start, ((size_t)(userpass_end-userpass_start) >= sizeof(buf)) ? (int)(sizeof(buf)) : (int)(userpass_end-userpass_start+1)); + if(buf[0]) + if(comparator(peeraddress, buf, password, cs, cslen)) + goto allow; + userpass_start = userpass_end + 1; + } + if(userpass_start[0]) + { + userpass_end = userpass_start + strlen(userpass_start); + if(comparator(peeraddress, userpass_start, password, cs, cslen)) + goto allow; + } + + restricted = true; + have_usernames = false; + userpass_start = rcon_restricted_password.string; + while((userpass_end = strchr(userpass_start, ' '))) + { + have_usernames = true; + strlcpy(buf, userpass_start, ((size_t)(userpass_end-userpass_start) >= sizeof(buf)) ? (int)(sizeof(buf)) : (int)(userpass_end-userpass_start+1)); + if(buf[0]) + if(comparator(peeraddress, buf, password, cs, cslen)) + goto check; + userpass_start = userpass_end + 1; + } + if(userpass_start[0]) + { + userpass_end = userpass_start + strlen(userpass_start); + if(comparator(peeraddress, userpass_start, password, cs, cslen)) + goto check; + } - if(!comparator(rcon_restricted_password.string, password, cs, cslen)) - return NULL; + return NULL; // DENIED +check: for(text = s; text != endpos; ++text) if((signed char) *text > 0 && ((signed char) *text < (signed char) ' ' || *text == ';')) return NULL; // block possible exploits against the parser/alias expansion @@ -2369,7 +2536,12 @@ match: s += l + 1; } - return "restricted rcon"; +allow: + userpass_startpass = strchr(userpass_start, ':'); + if(have_usernames && userpass_startpass && userpass_startpass < userpass_end) + return va("%srcon (username %.*s)", restricted ? "restricted " : "", (int)(userpass_startpass-userpass_start), userpass_start); + + return va("%srcon", restricted ? "restricted " : ""); } void RCon_Execute(lhnetsocket_t *mysocket, lhnetaddress_t *peeraddress, const char *addressstring2, const char *userlevel, const char *s, const char *endpos) @@ -2416,7 +2588,8 @@ static int NetConn_ServerParsePacket(lhnetsocket_t *mysocket, unsigned char *dat int i, ret, clientnum, best; double besttime; client_t *client; - char *s, *string, response[1400], addressstring2[128], stringbuf[16384]; + char *s, *string, response[1400], addressstring2[128]; + static char stringbuf[16384]; qboolean islocal = (LHNETADDRESS_GetAddressType(peeraddress) == LHNETADDRESSTYPE_LOOP); if (!sv.active) @@ -2445,7 +2618,7 @@ static int NetConn_ServerParsePacket(lhnetsocket_t *mysocket, unsigned char *dat stringbuf[length] = 0; string = stringbuf; - if (developer.integer >= 10) + if (developer_extra.integer) { Con_Printf("NetConn_ServerParsePacket: %s sent us a command:\n", addressstring2); Com_HexDumpToConsole(data, length); @@ -2455,8 +2628,9 @@ static int NetConn_ServerParsePacket(lhnetsocket_t *mysocket, unsigned char *dat { for (i = 0, best = 0, besttime = realtime;i < MAX_CHALLENGES;i++) { - if (!LHNETADDRESS_Compare(peeraddress, &challenge[i].address)) - break; + if(challenge[i].time > 0) + if (!LHNETADDRESS_Compare(peeraddress, &challenge[i].address)) + break; if (besttime > challenge[i].time) besttime = challenge[best = i].time; } @@ -2482,8 +2656,9 @@ static int NetConn_ServerParsePacket(lhnetsocket_t *mysocket, unsigned char *dat return true; // validate the challenge for (i = 0;i < MAX_CHALLENGES;i++) - if (!LHNETADDRESS_Compare(peeraddress, &challenge[i].address) && !strcmp(challenge[i].string, s)) - break; + if(challenge[i].time > 0) + if (!LHNETADDRESS_Compare(peeraddress, &challenge[i].address) && !strcmp(challenge[i].string, s)) + break; // if the challenge is not recognized, drop the packet if (i == MAX_CHALLENGES) return true; @@ -2491,7 +2666,7 @@ static int NetConn_ServerParsePacket(lhnetsocket_t *mysocket, unsigned char *dat // check engine protocol if(!(s = SearchInfostring(string, "protocol")) || strcmp(s, "darkplaces 3")) { - if (developer.integer >= 10) + if (developer_extra.integer) Con_Printf("Datagram_ParseConnectionless: sending \"reject Wrong game protocol.\" to %s.\n", addressstring2); NetConn_WriteString(mysocket, "\377\377\377\377reject Wrong game protocol.", peeraddress); return true; @@ -2508,7 +2683,7 @@ static int NetConn_ServerParsePacket(lhnetsocket_t *mysocket, unsigned char *dat { // client crashed and is coming back, // keep their stuff intact - if (developer.integer >= 10) + if (developer_extra.integer) Con_Printf("Datagram_ParseConnectionless: sending \"accept\" to %s.\n", addressstring2); NetConn_WriteString(mysocket, "\377\377\377\377accept", peeraddress); SV_VM_Begin(); @@ -2519,7 +2694,7 @@ static int NetConn_ServerParsePacket(lhnetsocket_t *mysocket, unsigned char *dat { // client is still trying to connect, // so we send a duplicate reply - if (developer.integer >= 10) + if (developer_extra.integer) Con_Printf("Datagram_ParseConnectionless: sending duplicate accept to %s.\n", addressstring2); NetConn_WriteString(mysocket, "\377\377\377\377accept", peeraddress); } @@ -2537,7 +2712,7 @@ static int NetConn_ServerParsePacket(lhnetsocket_t *mysocket, unsigned char *dat if (!client->active && (conn = NetConn_Open(mysocket, peeraddress))) { // allocated connection - if (developer.integer >= 10) + if (developer_extra.integer) Con_Printf("Datagram_ParseConnectionless: sending \"accept\" to %s.\n", conn->address); NetConn_WriteString(mysocket, "\377\377\377\377accept", peeraddress); // now set up the client @@ -2550,7 +2725,7 @@ static int NetConn_ServerParsePacket(lhnetsocket_t *mysocket, unsigned char *dat } // no empty slots found - server is full - if (developer.integer >= 10) + if (developer_extra.integer) Con_Printf("Datagram_ParseConnectionless: sending \"reject Server is full.\" to %s.\n", addressstring2); NetConn_WriteString(mysocket, "\377\377\377\377reject Server is full.", peeraddress); @@ -2566,8 +2741,8 @@ static int NetConn_ServerParsePacket(lhnetsocket_t *mysocket, unsigned char *dat if (NetConn_BuildStatusResponse(challenge, response, sizeof(response), false)) { - if (developer.integer >= 10) - Con_Printf("Sending reply to master %s - %s\n", addressstring2, response); + if (developer_extra.integer) + Con_DPrintf("Sending reply to master %s - %s\n", addressstring2, response); NetConn_WriteString(mysocket, response, peeraddress); } return true; @@ -2582,8 +2757,8 @@ static int NetConn_ServerParsePacket(lhnetsocket_t *mysocket, unsigned char *dat if (NetConn_BuildStatusResponse(challenge, response, sizeof(response), true)) { - if (developer.integer >= 10) - Con_Printf("Sending reply to client %s - %s\n", addressstring2, response); + if (developer_extra.integer) + Con_DPrintf("Sending reply to client %s - %s\n", addressstring2, response); NetConn_WriteString(mysocket, response, peeraddress); } return true; @@ -2595,11 +2770,30 @@ static int NetConn_ServerParsePacket(lhnetsocket_t *mysocket, unsigned char *dat char *s = strchr(timeval, ' '); char *endpos = string + length + 1; // one behind the NUL, so adding strlen+1 will eventually reach it const char *userlevel; + + if(rcon_secure.integer > 1) + return true; + + if(!s) + return true; // invalid packet + ++s; + + userlevel = RCon_Authenticate(peeraddress, password, s, endpos, hmac_mdfour_time_matching, timeval, endpos - timeval - 1); // not including the appended \0 into the HMAC + RCon_Execute(mysocket, peeraddress, addressstring2, userlevel, s, endpos); + return true; + } + if (length >= 42 && !memcmp(string, "srcon HMAC-MD4 CHALLENGE ", 25)) + { + char *password = string + 25; + char *challenge = string + 42; + char *s = strchr(challenge, ' '); + char *endpos = string + length + 1; // one behind the NUL, so adding strlen+1 will eventually reach it + const char *userlevel; if(!s) return true; // invalid packet ++s; - userlevel = RCon_Authenticate(password, s, endpos, hmac_mdfour_matching, timeval, endpos - timeval - 1); // not including the appended \0 into the HMAC + userlevel = RCon_Authenticate(peeraddress, password, s, endpos, hmac_mdfour_challenge_matching, challenge, endpos - challenge - 1); // not including the appended \0 into the HMAC RCon_Execute(mysocket, peeraddress, addressstring2, userlevel, s, endpos); return true; } @@ -2610,7 +2804,7 @@ static int NetConn_ServerParsePacket(lhnetsocket_t *mysocket, unsigned char *dat char *endpos = string + length + 1; // one behind the NUL, so adding strlen+1 will eventually reach it char password[64]; - if(rcon_secure.integer) + if(rcon_secure.integer > 0) return true; for (i = 0;!ISWHITESPACE(*s);s++) @@ -2621,15 +2815,24 @@ static int NetConn_ServerParsePacket(lhnetsocket_t *mysocket, unsigned char *dat password[i] = 0; if (!ISWHITESPACE(password[0])) { - const char *userlevel = RCon_Authenticate(password, s, endpos, plaintext_matching, NULL, 0); + const char *userlevel = RCon_Authenticate(peeraddress, password, s, endpos, plaintext_matching, NULL, 0); RCon_Execute(mysocket, peeraddress, addressstring2, userlevel, s, endpos); } return true; } + if (!strncmp(string, "extResponse ", 12)) + { + ++sv_net_extresponse_count; + if(sv_net_extresponse_count > NET_EXTRESPONSE_MAX) + sv_net_extresponse_count = NET_EXTRESPONSE_MAX; + sv_net_extresponse_last = (sv_net_extresponse_last + 1) % NET_EXTRESPONSE_MAX; + dpsnprintf(sv_net_extresponse[sv_net_extresponse_last], sizeof(sv_net_extresponse[sv_net_extresponse_last]), "'%s' %s", addressstring2, string + 12); + return true; + } if (!strncmp(string, "ping", 4)) { - if (developer.integer >= 10) - Con_Printf("Received ping from %s, sending ack\n", addressstring2); + if (developer_extra.integer) + Con_DPrintf("Received ping from %s, sending ack\n", addressstring2); NetConn_WriteString(mysocket, "\377\377\377\377ack", peeraddress); return true; } @@ -2644,7 +2847,7 @@ static int NetConn_ServerParsePacket(lhnetsocket_t *mysocket, unsigned char *dat // protocol // (this protects more modern protocols against being used for // Quake packet flood Denial Of Service attacks) - if (length >= 5 && (i = BigLong(*((int *)data))) && (i & (~NETFLAG_LENGTH_MASK)) == (int)NETFLAG_CTL && (i & NETFLAG_LENGTH_MASK) == length && (sv.protocol == PROTOCOL_QUAKE || sv.protocol == PROTOCOL_QUAKEDP || sv.protocol == PROTOCOL_NEHAHRAMOVIE || sv.protocol == PROTOCOL_NEHAHRABJP || sv.protocol == PROTOCOL_NEHAHRABJP2 || sv.protocol == PROTOCOL_NEHAHRABJP3 || sv.protocol == PROTOCOL_DARKPLACES1 || sv.protocol == PROTOCOL_DARKPLACES2 || sv.protocol == PROTOCOL_DARKPLACES3)) + if (length >= 5 && (i = BuffBigLong(data)) && (i & (~NETFLAG_LENGTH_MASK)) == (int)NETFLAG_CTL && (i & NETFLAG_LENGTH_MASK) == length && (sv.protocol == PROTOCOL_QUAKE || sv.protocol == PROTOCOL_QUAKEDP || sv.protocol == PROTOCOL_NEHAHRAMOVIE || sv.protocol == PROTOCOL_NEHAHRABJP || sv.protocol == PROTOCOL_NEHAHRABJP2 || sv.protocol == PROTOCOL_NEHAHRABJP3 || sv.protocol == PROTOCOL_DARKPLACES1 || sv.protocol == PROTOCOL_DARKPLACES2 || sv.protocol == PROTOCOL_DARKPLACES3)) { int c; int protocolnumber; @@ -2658,8 +2861,8 @@ static int NetConn_ServerParsePacket(lhnetsocket_t *mysocket, unsigned char *dat switch (c) { case CCREQ_CONNECT: - if (developer.integer >= 10) - Con_Printf("Datagram_ParseConnectionless: received CCREQ_CONNECT from %s.\n", addressstring2); + if (developer_extra.integer) + Con_DPrintf("Datagram_ParseConnectionless: received CCREQ_CONNECT from %s.\n", addressstring2); if(!islocal && sv_public.integer <= -2) break; @@ -2667,14 +2870,14 @@ static int NetConn_ServerParsePacket(lhnetsocket_t *mysocket, unsigned char *dat protocolnumber = MSG_ReadByte(); if (strcmp(protocolname, "QUAKE") || protocolnumber != NET_PROTOCOL_VERSION) { - if (developer.integer >= 10) - Con_Printf("Datagram_ParseConnectionless: sending CCREP_REJECT \"Incompatible version.\" to %s.\n", addressstring2); + if (developer_extra.integer) + Con_DPrintf("Datagram_ParseConnectionless: sending CCREP_REJECT \"Incompatible version.\" to %s.\n", addressstring2); SZ_Clear(&net_message); // save space for the header, filled in later MSG_WriteLong(&net_message, 0); MSG_WriteByte(&net_message, CCREP_REJECT); MSG_WriteString(&net_message, "Incompatible version.\n"); - *((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK)); + StoreBigLong(net_message.data, NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK)); NetConn_Write(mysocket, net_message.data, net_message.cursize, peeraddress); SZ_Clear(&net_message); break; @@ -2690,14 +2893,14 @@ static int NetConn_ServerParsePacket(lhnetsocket_t *mysocket, unsigned char *dat // (if so, keep their stuff intact) // send a reply - if (developer.integer >= 10) - Con_Printf("Datagram_ParseConnectionless: sending duplicate CCREP_ACCEPT to %s.\n", addressstring2); + if (developer_extra.integer) + Con_DPrintf("Datagram_ParseConnectionless: sending duplicate CCREP_ACCEPT to %s.\n", addressstring2); SZ_Clear(&net_message); // save space for the header, filled in later MSG_WriteLong(&net_message, 0); MSG_WriteByte(&net_message, CCREP_ACCEPT); MSG_WriteLong(&net_message, LHNETADDRESS_GetPort(LHNET_AddressFromSocket(client->netconnection->mysocket))); - *((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK)); + StoreBigLong(net_message.data, NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK)); NetConn_Write(mysocket, net_message.data, net_message.cursize, peeraddress); SZ_Clear(&net_message); @@ -2726,15 +2929,15 @@ static int NetConn_ServerParsePacket(lhnetsocket_t *mysocket, unsigned char *dat // connect to the client // everything is allocated, just fill in the details strlcpy (conn->address, addressstring2, sizeof (conn->address)); - if (developer.integer >= 10) - Con_Printf("Datagram_ParseConnectionless: sending CCREP_ACCEPT to %s.\n", addressstring2); + if (developer_extra.integer) + Con_DPrintf("Datagram_ParseConnectionless: sending CCREP_ACCEPT to %s.\n", addressstring2); // send back the info about the server connection SZ_Clear(&net_message); // save space for the header, filled in later MSG_WriteLong(&net_message, 0); MSG_WriteByte(&net_message, CCREP_ACCEPT); MSG_WriteLong(&net_message, LHNETADDRESS_GetPort(LHNET_AddressFromSocket(conn->mysocket))); - *((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK)); + StoreBigLong(net_message.data, NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK)); NetConn_Write(mysocket, net_message.data, net_message.cursize, peeraddress); SZ_Clear(&net_message); // now set up the client struct @@ -2746,29 +2949,29 @@ static int NetConn_ServerParsePacket(lhnetsocket_t *mysocket, unsigned char *dat } } - if (developer.integer >= 10) - Con_Printf("Datagram_ParseConnectionless: sending CCREP_REJECT \"Server is full.\" to %s.\n", addressstring2); + if (developer_extra.integer) + Con_DPrintf("Datagram_ParseConnectionless: sending CCREP_REJECT \"Server is full.\" to %s.\n", addressstring2); // no room; try to let player know SZ_Clear(&net_message); // save space for the header, filled in later MSG_WriteLong(&net_message, 0); MSG_WriteByte(&net_message, CCREP_REJECT); MSG_WriteString(&net_message, "Server is full.\n"); - *((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK)); + StoreBigLong(net_message.data, NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK)); NetConn_Write(mysocket, net_message.data, net_message.cursize, peeraddress); SZ_Clear(&net_message); break; case CCREQ_SERVER_INFO: - if (developer.integer >= 10) - Con_Printf("Datagram_ParseConnectionless: received CCREQ_SERVER_INFO from %s.\n", addressstring2); + if (developer_extra.integer) + Con_DPrintf("Datagram_ParseConnectionless: received CCREQ_SERVER_INFO from %s.\n", addressstring2); if(!islocal && sv_public.integer <= -1) break; if (sv.active && !strcmp(MSG_ReadString(), "QUAKE")) { int numclients; char myaddressstring[128]; - if (developer.integer >= 10) - Con_Printf("Datagram_ParseConnectionless: sending CCREP_SERVER_INFO to %s.\n", addressstring2); + if (developer_extra.integer) + Con_DPrintf("Datagram_ParseConnectionless: sending CCREP_SERVER_INFO to %s.\n", addressstring2); SZ_Clear(&net_message); // save space for the header, filled in later MSG_WriteLong(&net_message, 0); @@ -2784,14 +2987,14 @@ static int NetConn_ServerParsePacket(lhnetsocket_t *mysocket, unsigned char *dat MSG_WriteByte(&net_message, numclients); MSG_WriteByte(&net_message, svs.maxclients); MSG_WriteByte(&net_message, NET_PROTOCOL_VERSION); - *((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK)); + StoreBigLong(net_message.data, NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK)); NetConn_Write(mysocket, net_message.data, net_message.cursize, peeraddress); SZ_Clear(&net_message); } break; case CCREQ_PLAYER_INFO: - if (developer.integer >= 10) - Con_Printf("Datagram_ParseConnectionless: received CCREQ_PLAYER_INFO from %s.\n", addressstring2); + if (developer_extra.integer) + Con_DPrintf("Datagram_ParseConnectionless: received CCREQ_PLAYER_INFO from %s.\n", addressstring2); if(!islocal && sv_public.integer <= -1) break; if (sv.active) @@ -2816,15 +3019,15 @@ static int NetConn_ServerParsePacket(lhnetsocket_t *mysocket, unsigned char *dat MSG_WriteLong(&net_message, client->frags); MSG_WriteLong(&net_message, (int)(realtime - client->connecttime)); MSG_WriteString(&net_message, client->netconnection ? client->netconnection->address : "botclient"); - *((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK)); + StoreBigLong(net_message.data, NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK)); NetConn_Write(mysocket, net_message.data, net_message.cursize, peeraddress); SZ_Clear(&net_message); } } break; case CCREQ_RULE_INFO: - if (developer.integer >= 10) - Con_Printf("Datagram_ParseConnectionless: received CCREQ_RULE_INFO from %s.\n", addressstring2); + if (developer_extra.integer) + Con_DPrintf("Datagram_ParseConnectionless: received CCREQ_RULE_INFO from %s.\n", addressstring2); if(!islocal && sv_public.integer <= -1) break; if (sv.active) @@ -2846,7 +3049,7 @@ static int NetConn_ServerParsePacket(lhnetsocket_t *mysocket, unsigned char *dat MSG_WriteString(&net_message, var->name); MSG_WriteString(&net_message, var->string); } - *((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK)); + StoreBigLong(net_message.data, NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK)); NetConn_Write(mysocket, net_message.data, net_message.cursize, peeraddress); SZ_Clear(&net_message); } @@ -2931,7 +3134,7 @@ void NetConn_QueryMasters(qboolean querydp, qboolean queryqw) MSG_WriteByte(&net_message, CCREQ_SERVER_INFO); MSG_WriteString(&net_message, "QUAKE"); MSG_WriteByte(&net_message, NET_PROTOCOL_VERSION); - *((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK)); + StoreBigLong(net_message.data, NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK)); NetConn_Write(cl_sockets[i], net_message.data, net_message.cursize, &broadcastaddress); SZ_Clear(&net_message);