summaryrefslogtreecommitdiff
path: root/src/master
diff options
context:
space:
mode:
authorTim Angus <tim@ngus.net>2007-06-06 21:28:00 +0000
committerTim Angus <tim@ngus.net>2007-06-06 21:28:00 +0000
commit9706815b1e7fe5129bf1bfe68291d86e0cd9372e (patch)
tree2479563e3342069e21a63747093318a7a2eed116 /src/master
parentea05cee39314fc36467f5f9ca7b03a9f93eb4a1c (diff)
* Patch from R1CH to delist servers that are hidden by NAT
Diffstat (limited to 'src/master')
-rw-r--r--src/master/Makefile4
-rw-r--r--src/master/common.h3
-rw-r--r--src/master/master.c68
-rw-r--r--src/master/messages.c6
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 ) );
}