diff options
author | Tim Angus <tim@ngus.net> | 2007-06-06 21:28:00 +0000 |
---|---|---|
committer | Tim Angus <tim@ngus.net> | 2007-06-06 21:28:00 +0000 |
commit | 9706815b1e7fe5129bf1bfe68291d86e0cd9372e (patch) | |
tree | 2479563e3342069e21a63747093318a7a2eed116 /src | |
parent | ea05cee39314fc36467f5f9ca7b03a9f93eb4a1c (diff) |
* Patch from R1CH to delist servers that are hidden by NAT
Diffstat (limited to 'src')
-rw-r--r-- | src/master/Makefile | 4 | ||||
-rw-r--r-- | src/master/common.h | 3 | ||||
-rw-r--r-- | src/master/master.c | 68 | ||||
-rw-r--r-- | src/master/messages.c | 6 |
4 files changed, 65 insertions, 16 deletions
diff --git a/src/master/Makefile b/src/master/Makefile index 1390dcbb..2f60b413 100644 --- a/src/master/Makefile +++ b/src/master/Makefile @@ -9,8 +9,8 @@ ifeq ($(PLATFORM),mingw32) MKDIR=mkdir else BINEXT= - RELEASE_LDFLAGS=-static -ltdb - DEBUG_LDFLAGS=-static -ltdb + RELEASE_LDFLAGS=-ltdb + DEBUG_LDFLAGS=-ltdb RM=rm -f MKDIR=mkdir endif diff --git a/src/master/common.h b/src/master/common.h index 47c29a93..8c5c3b66 100644 --- a/src/master/common.h +++ b/src/master/common.h @@ -62,7 +62,8 @@ typedef enum // ---------- Public variables ---------- // // The master socket -extern int sock; +extern int inSock; +extern int outSock; // The current time (updated every time we receive a packet) extern time_t crt_time; diff --git a/src/master/master.c b/src/master/master.c index f58f515d..11cec6a5 100644 --- a/src/master/master.c +++ b/src/master/master.c @@ -23,6 +23,7 @@ #include <stdarg.h> #include <signal.h> +#include <ctype.h> #ifndef WIN32 # include <pwd.h> @@ -86,7 +87,8 @@ static const char* low_priv_user = DEFAULT_LOW_PRIV_USER; // ---------- Public variables ---------- // // The master socket -int sock = -1; +int inSock = -1; +int outSock = -1; // The current time (updated every time we receive a packet) time_t crt_time; @@ -467,8 +469,16 @@ static qboolean SecureInit (void) return qfalse; // Open the socket - sock = socket (PF_INET, SOCK_DGRAM, IPPROTO_UDP); - if (sock < 0) + inSock = socket (PF_INET, SOCK_DGRAM, IPPROTO_UDP); + if (inSock < 0) + { + MsgPrint (MSG_ERROR, "ERROR: socket creation failed (%s)\n", + strerror (errno)); + return qfalse; + } + + outSock = socket (PF_INET, SOCK_DGRAM, IPPROTO_UDP); + if (outSock < 0) { MsgPrint (MSG_ERROR, "ERROR: socket creation failed (%s)\n", strerror (errno)); @@ -486,21 +496,38 @@ static qboolean SecureInit (void) } else address.sin_addr.s_addr = htonl (INADDR_ANY); + address.sin_port = htons (master_port); - if (bind (sock, (struct sockaddr*)&address, sizeof (address)) != 0) + if (bind (inSock, (struct sockaddr*)&address, sizeof (address)) != 0) { MsgPrint (MSG_ERROR, "ERROR: socket binding failed (%s)\n", strerror (errno)); #ifdef WIN32 - closesocket (sock); + closesocket (inSock); #else - close (sock); + close (inSock); #endif return qfalse; } MsgPrint (MSG_NORMAL, "Listening on UDP port %hu\n", ntohs (address.sin_port)); + // Deliberately use a different port for outgoing traffic in order + // to confuse NAT UDP "connection" tracking and thus delist servers + // hidden by NAT + address.sin_port = htons (master_port+1); + if (bind (outSock, (struct sockaddr*)&address, sizeof (address)) != 0) + { + MsgPrint (MSG_ERROR, "ERROR: socket binding failed (%s)\n", + strerror (errno)); +#ifdef WIN32 + closesocket (outSock); +#else + close (outSock); +#endif + return qfalse; + } + return qtrue; } @@ -673,6 +700,18 @@ static qboolean ignoreAddress( const char *address ) /* ==================== +max + +Maximum of two ints +==================== +*/ +static inline int max( int a, int b ) +{ + return a > b ? a : b; +} + +/* +==================== main Main function @@ -683,6 +722,7 @@ int main (int argc, const char* argv []) struct sockaddr_in address; socklen_t addrlen; int nb_bytes; + int sock; char packet [MAX_PACKET_SIZE + 1]; // "+ 1" because we append a '\0' qboolean valid_options; fd_set rfds; @@ -714,20 +754,28 @@ int main (int argc, const char* argv []) while( !exitNow ) { FD_ZERO( &rfds ); - FD_SET( sock, &rfds ); + FD_SET( inSock, &rfds ); + FD_SET( outSock, &rfds ); tv.tv_sec = tv.tv_usec = 0; // Check for new data every 100ms - if( select( sock + 1, &rfds, NULL, NULL, &tv ) <= 0 ) + if( select( max( inSock, outSock ) + 1, &rfds, NULL, NULL, &tv ) <= 0 ) { #ifdef _WIN32 - Sleep( 100 ); + Sleep( 100 ); #else usleep( 100000 ); #endif continue; } + if( FD_ISSET( inSock, &rfds ) ) + sock = inSock; + else if( FD_ISSET( outSock, &rfds ) ) + sock = outSock; + else + continue; + // Get the next valid message addrlen = sizeof (address); nb_bytes = recvfrom (sock, packet, sizeof (packet) - 1, 0, @@ -772,7 +820,7 @@ int main (int argc, const char* argv []) peer_address); continue; } - if (! ntohs (address.sin_port)) + if( ntohs( address.sin_port ) < 1024 ) { MsgPrint (MSG_WARNING, "WARNING: rejected packet from %s (source port = 0)\n", diff --git a/src/master/messages.c b/src/master/messages.c index 0f34e0ad..563023ef 100644 --- a/src/master/messages.c +++ b/src/master/messages.c @@ -185,7 +185,7 @@ static void SendGetInfo (server_t* server) } strncat (msg, server->challenge, sizeof (msg) - strlen (msg) - 1); - sendto (sock, msg, strlen (msg), 0, + sendto (outSock, msg, strlen (msg), 0, (const struct sockaddr*)&server->address, sizeof (server->address)); @@ -245,7 +245,7 @@ static void HandleGetServers (const char* msg, const struct sockaddr_in* addr) packetind += 6; // Send the packet to the client - sendto (sock, packet, packetind, 0, (const struct sockaddr*)addr, + sendto (inSock, packet, packetind, 0, (const struct sockaddr*)addr, sizeof (*addr)); MsgPrint (MSG_DEBUG, "%s <--- getserversResponse (%u servers)\n", @@ -472,7 +472,7 @@ static void HandleGetMotd( const char* msg, const struct sockaddr_in* addr ) MsgPrint( MSG_DEBUG, "%s <--- motd\n", peer_address ); // Send the packet to the client - sendto( sock, packet, packetind, 0, (const struct sockaddr*)addr, + sendto( inSock, packet, packetind, 0, (const struct sockaddr*)addr, sizeof( *addr ) ); } |