]> de.git.xonotic.org Git - xonotic/darkplaces.git/blobdiff - net_dgrm.c
fixed forged packet identification to only care about address (not port) and do so...
[xonotic/darkplaces.git] / net_dgrm.c
index fe34fba0d94bc64e1fcce33877da354387a80575..53ab0bdac3a5c207374190f57b35cc987c758b45 100644 (file)
@@ -81,8 +81,8 @@ struct
        qbyte                   data[MAX_DATAGRAM];
 } packetBuffer;
 
-
-//#ifdef DEBUG
+/*
+#ifdef DEBUG
 char *StrAddr (struct qsockaddr *addr)
 {
        static char buf[34];
@@ -93,7 +93,8 @@ char *StrAddr (struct qsockaddr *addr)
                sprintf (buf + n * 2, "%02x", *p++);
        return buf;
 }
-//#endif
+#endif
+*/
 
 
 #ifdef BAN_TEST
@@ -136,7 +137,7 @@ void NET_Ban_f (void)
                        break;
 
                case 2:
-                       if (Q_strcasecmp(Cmd_Argv(1), "off") == 0)
+                       if (strcasecmp(Cmd_Argv(1), "off") == 0)
                                banAddr = 0x00000000;
                        else
                                banAddr = inet_addr(Cmd_Argv(1));
@@ -318,6 +319,7 @@ int Datagram_GetMessage (qsocket_t *sock)
        struct qsockaddr readaddr;
        unsigned int    sequence;
        unsigned int    count;
+       int                             temp;
 
        if (!sock->canSend)
                if ((net_time - sock->lastSendTime) > 1.0)
@@ -330,20 +332,31 @@ int       Datagram_GetMessage (qsocket_t *sock)
                if (length == 0)
                        break;
 
-               if (length == -1)
+               if ((int)length == -1)
                {
                        Con_Printf("Read error\n");
                        return -1;
                }
 
-               if (sfunc.AddrCompare(&readaddr, &sock->addr) != 0)
+               if ((temp = sfunc.AddrCompare(&readaddr, &sock->addr)) != 0)
                {
-#ifdef DEBUG
-                       Con_DPrintf("Forged packet received\n");
-                       Con_DPrintf("Expected: %s\n", StrAddr (&sock->addr));
-                       Con_DPrintf("Received: %s\n", StrAddr (&readaddr));
-#endif
-                       continue;
+                       char tempaddress1[64], tempaddress2[64];
+                       if (temp == 1)
+                       {
+                               if (developer_networking.integer)
+                               {
+                                       dfunc.GetNameFromAddr (&sock->addr, tempaddress1);
+                                       dfunc.GetNameFromAddr (&readaddr, tempaddress2);
+                                       Con_Printf("Packet from wrong port received but accepted (Expected: %s Received: %s)\n", tempaddress1, tempaddress2);
+                               }
+                       }
+                       else
+                       {
+                               dfunc.GetNameFromAddr (&sock->addr, tempaddress1);
+                               dfunc.GetNameFromAddr (&readaddr, tempaddress2);
+                               Con_Printf("Forged packet received (Expected: %s Received: %s)\n", tempaddress1, tempaddress2);
+                               continue;
+                       }
                }
 
                if (length < NET_HEADERSIZE)
@@ -491,7 +504,7 @@ void NET_Stats_f (void)
        else
        {
                for (s = net_activeSockets; s; s = s->next)
-                       if (Q_strcasecmp(Cmd_Argv(1), s->address) == 0)
+                       if (strcasecmp(Cmd_Argv(1), s->address) == 0)
                                break;
                if (s == NULL)
                        return;
@@ -499,7 +512,7 @@ void NET_Stats_f (void)
        }
 }
 
-
+/*
 static qboolean testInProgress = false;
 static int             testPollCount;
 static int             testDriver;
@@ -526,7 +539,7 @@ static void Test_Poll(void)
        while (1)
        {
                len = dfunc.Read (testSocket, net_message.data, net_message.maxsize, &clientaddr);
-               if (len < sizeof(int))
+               if (len < (int)sizeof(int))
                        break;
 
                net_message.cursize = len;
@@ -536,7 +549,7 @@ static void Test_Poll(void)
                MSG_ReadLong();
                if (control == -1)
                        break;
-               if ((control & (~NETFLAG_LENGTH_MASK)) !=  NETFLAG_CTL)
+               if ((control & (~NETFLAG_LENGTH_MASK)) != (int)NETFLAG_CTL)
                        break;
                if ((control & NETFLAG_LENGTH_MASK) != len)
                        break;
@@ -581,7 +594,7 @@ static void Test_f (void)
        if (host && hostCacheCount)
        {
                for (n = 0; n < hostCacheCount; n++)
-                       if (Q_strcasecmp (host, hostcache[n].name) == 0)
+                       if (strcasecmp (host, hostcache[n].name) == 0)
                        {
                                if (hostcache[n].driver != myDriverLevel)
                                        continue;
@@ -650,7 +663,7 @@ static void Test2_Poll(void)
        name[0] = 0;
 
        len = dfunc.Read (test2Socket, net_message.data, net_message.maxsize, &clientaddr);
-       if (len < sizeof(int))
+       if (len < (int)sizeof(int))
                goto Reschedule;
 
        net_message.cursize = len;
@@ -660,7 +673,7 @@ static void Test2_Poll(void)
        MSG_ReadLong();
        if (control == -1)
                goto Error;
-       if ((control & (~NETFLAG_LENGTH_MASK)) !=  NETFLAG_CTL)
+       if ((control & (~NETFLAG_LENGTH_MASK)) != (int)NETFLAG_CTL)
                goto Error;
        if ((control & NETFLAG_LENGTH_MASK) != len)
                goto Error;
@@ -711,7 +724,7 @@ static void Test2_f (void)
        if (host && hostCacheCount)
        {
                for (n = 0; n < hostCacheCount; n++)
-                       if (Q_strcasecmp (host, hostcache[n].name) == 0)
+                       if (strcasecmp (host, hostcache[n].name) == 0)
                        {
                                if (hostcache[n].driver != myDriverLevel)
                                        continue;
@@ -753,7 +766,7 @@ JustDoIt:
        SZ_Clear(&net_message);
        SchedulePollProcedure(&test2PollProcedure, 0.05);
 }
-
+*/
 
 int Datagram_Init (void)
 {
@@ -779,8 +792,8 @@ int Datagram_Init (void)
 #ifdef BAN_TEST
        Cmd_AddCommand ("ban", NET_Ban_f);
 #endif
-       Cmd_AddCommand ("test", Test_f);
-       Cmd_AddCommand ("test2", Test2_f);
+       //Cmd_AddCommand ("test", Test_f);
+       //Cmd_AddCommand ("test2", Test2_f);
 
        return 0;
 }
@@ -841,16 +854,16 @@ static qsocket_t *_Datagram_CheckNewConnections (void)
        SZ_Clear(&net_message);
 
        len = dfunc.Read (acceptsock, net_message.data, net_message.maxsize, &clientaddr);
-       if (len < sizeof(int))
+       if (len < (int)sizeof(int))
                return NULL;
        net_message.cursize = len;
 
        MSG_BeginReading ();
        control = BigLong(*((int *)net_message.data));
        MSG_ReadLong();
-       
+
        // Messages starting by 0xFFFFFFFF are master server messages
-       if (control == 0xFFFFFFFF)
+       if ((unsigned int)control == 0xFFFFFFFF)
        {
                int responsesize = Master_HandleMessage();
                if (responsesize > 0)
@@ -860,7 +873,7 @@ static qsocket_t *_Datagram_CheckNewConnections (void)
                }
                return NULL;
        }
-       if ((control & (~NETFLAG_LENGTH_MASK)) !=  NETFLAG_CTL)
+       if ((control & (~NETFLAG_LENGTH_MASK)) != (int)NETFLAG_CTL)
                return NULL;
        if ((control & NETFLAG_LENGTH_MASK) != len)
                return NULL;
@@ -1004,7 +1017,7 @@ static qsocket_t *_Datagram_CheckNewConnections (void)
                ret = dfunc.AddrCompare(&clientaddr, &s->addr);
                if (ret >= 0)
                {
-                       // is this a duplicate connection reqeust?
+                       // is this a duplicate connection request?
                        if (ret == 0 && net_time - s->connecttime < 2.0)
                        {
                                // yes, so send a duplicate reply
@@ -1015,6 +1028,13 @@ static qsocket_t *_Datagram_CheckNewConnections (void)
                                dfunc.GetSocketAddr(s->socket, &newaddr);
                                MSG_WriteLong(&net_message, dfunc.GetSocketPort(&newaddr));
                                *((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK));
+                               // LordHavoc: send from s->socket instead of acceptsock, this
+                               // way routers usually identify the connection correctly
+                               // (thanks to faded for provoking me to recite a lengthy
+                               // explanation of NAT nightmares, and realize this easy
+                               // workaround for quake)
+                               dfunc.Write (s->socket, net_message.data, net_message.cursize, &clientaddr);
+                               // LordHavoc: also send from acceptsock, for good measure
                                dfunc.Write (acceptsock, net_message.data, net_message.cursize, &clientaddr);
                                SZ_Clear(&net_message);
                                return NULL;
@@ -1072,6 +1092,12 @@ static qsocket_t *_Datagram_CheckNewConnections (void)
        dfunc.GetSocketAddr(newsock, &newaddr);
        MSG_WriteLong(&net_message, dfunc.GetSocketPort(&newaddr));
        *((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK));
+       // LordHavoc: send from sock->socket instead of acceptsock, this way routers
+       // usually identify the connection correctly (thanks to faded for provoking
+       // me to recite a lengthy explanation of NAT nightmares, and realize this
+       // easy workaround for quake)
+       dfunc.Write (sock->socket, net_message.data, net_message.cursize, &clientaddr);
+       // LordHavoc: also send from acceptsock, for good measure
        dfunc.Write (acceptsock, net_message.data, net_message.cursize, &clientaddr);
        SZ_Clear(&net_message);
 
@@ -1092,15 +1118,16 @@ qsocket_t *Datagram_CheckNewConnections (void)
 
 static qboolean Datagram_HandleServerInfo (struct qsockaddr *readaddr)
 {
-       struct qsockaddr myaddr;
+       //struct qsockaddr myaddr;
        int control;
-       int c, n, i;
+       int c, n;
+       char cname[256];
 
-       if (net_message.cursize < sizeof(int))
+       if (net_message.cursize < (int)sizeof(int))
                return false;
 
        // don't answer our own query
-       dfunc.GetSocketAddr (dfunc.controlSock, &myaddr);
+       //dfunc.GetSocketAddr (dfunc.controlSock, &myaddr);
        //if (dfunc.AddrCompare(readaddr, &myaddr) >= 0)
        //      return false;
 
@@ -1113,7 +1140,7 @@ static qboolean Datagram_HandleServerInfo (struct qsockaddr *readaddr)
        MSG_ReadLong();
        if (control == -1)
                return false;
-       if ((control & (~NETFLAG_LENGTH_MASK)) !=  NETFLAG_CTL)
+       if ((control & (~NETFLAG_LENGTH_MASK)) != (int)NETFLAG_CTL)
                return false;
        if ((control & NETFLAG_LENGTH_MASK) != net_message.cursize)
                return false;
@@ -1122,15 +1149,16 @@ static qboolean Datagram_HandleServerInfo (struct qsockaddr *readaddr)
        if (c != CCREP_SERVER_INFO)
                return false;
 
-       dfunc.GetAddrFromName(MSG_ReadString(), readaddr);
+       // LordHavoc: because the UDP driver reports 0.0.0.0:26000 as the address
+       // string we just ignore it and keep the real address
+       MSG_ReadString();
+       // hostcache only uses text addresses
+       strcpy(cname, dfunc.AddrToString(readaddr));
        // search the cache for this server
        for (n = 0; n < hostCacheCount; n++)
-               if (dfunc.AddrCompare(readaddr, &hostcache[n].addr) == 0)
-                       break;
-
-       // is it already there?
-       if (n < hostCacheCount)
-               return false;;
+               //if (dfunc.AddrCompare(readaddr, &hostcache[n].addr) == 0)
+               if (!strcmp(cname, hostcache[n].cname))
+                       return false;
 
        // add it
        hostCacheCount++;
@@ -1141,22 +1169,24 @@ static qboolean Datagram_HandleServerInfo (struct qsockaddr *readaddr)
        c = MSG_ReadByte();
        if (c != NET_PROTOCOL_VERSION)
        {
-               strcpy(hostcache[n].cname, hostcache[n].name);
-               hostcache[n].cname[14] = 0;
+               strncpy(hostcache[n].cname, hostcache[n].name, sizeof(hostcache[n].cname) - 1);
+               hostcache[n].cname[sizeof(hostcache[n].cname) - 1] = 0;
                strcpy(hostcache[n].name, "*");
-               strcat(hostcache[n].name, hostcache[n].cname);
+               strncat(hostcache[n].name, hostcache[n].cname, sizeof(hostcache[n].name) - 1);
+               hostcache[n].name[sizeof(hostcache[n].name) - 1] = 0;
        }
-       memcpy(&hostcache[n].addr, readaddr, sizeof(struct qsockaddr));
-       hostcache[n].driver = net_driverlevel;
-       hostcache[n].ldriver = net_landriverlevel;
-       strcpy(hostcache[n].cname, dfunc.AddrToString(readaddr));
+       strcpy(hostcache[n].cname, cname);
+       //memcpy(&hostcache[n].addr, readaddr, sizeof(struct qsockaddr));
+       //hostcache[n].driver = net_driverlevel;
+       //hostcache[n].ldriver = net_landriverlevel;
 
+       /*
        // check for a name conflict
        for (i = 0; i < hostCacheCount; i++)
        {
                if (i == n)
                        continue;
-               if (Q_strcasecmp (hostcache[n].name, hostcache[i].name) == 0)
+               if (strcasecmp (hostcache[n].name, hostcache[i].name) == 0)
                {
                        i = strlen(hostcache[n].name);
                        if (i < 15 && hostcache[n].name[i-1] > '8')
@@ -1169,6 +1199,7 @@ static qboolean Datagram_HandleServerInfo (struct qsockaddr *readaddr)
                        i = -1;
                }
        }
+       */
 
        return true;
 }
@@ -1228,25 +1259,20 @@ static qboolean _Datagram_SearchForInetHosts (const char *master)
                                portnum = atoi (port + 1);
                        if (!portnum)
                                portnum = MASTER_PORT;
-                       Con_DPrintf("Datagram_SearchForInetHosts: sending %d byte message to master %s\n", net_message.cursize, master);
+                       Con_DPrintf("Datagram_SearchForInetHosts: sending %d byte message to master %s port %i\n", net_message.cursize, master, portnum);
                        dfunc.SetSocketPort (&masteraddr, portnum);
-                       dfunc.Send (net_message.data, net_message.cursize, &masteraddr);
+                       dfunc.Write (dfunc.controlSock, net_message.data, net_message.cursize, &masteraddr);
                }
        }
 
-       while ((ret = dfunc.Recv (net_message.data, net_message.maxsize, &readaddr)) > 0)
-       {
-               net_message.cursize = ret;
-               Con_DPrintf("Datagram_SearchForInetHosts: Recv received %d byte message\n", net_message.cursize);
-               Master_ParseServerList (&dfunc);
-       }
-       
        while ((ret = dfunc.Read (dfunc.controlSock, net_message.data, net_message.maxsize, &readaddr)) > 0)
        {
                net_message.cursize = ret;
                Con_DPrintf("Datagram_SearchForInetHosts: Read received %d byte message\n", net_message.cursize);
                if (Datagram_HandleServerInfo (&readaddr))
                        result = true;
+               else
+                       Master_ParseServerList (&dfunc);
        }
 
        return result;
@@ -1264,7 +1290,7 @@ qboolean Datagram_SearchForInetHosts (const char *master)
                        if (_Datagram_SearchForInetHosts (master))
                                result = true;
        }
-       
+
        return result;
 }
 
@@ -1321,17 +1347,21 @@ static qsocket_t *_Datagram_Connect (const char *host)
                        if (ret > 0)
                        {
                                // is it from the right place?
-                               if (sfunc.AddrCompare(&readaddr, &sendaddr) != 0)
+                               // we don't care if the port matches (this adds support for
+                               // the NAT fix in the server inspired by faded)
+                               if (sfunc.AddrCompare(&readaddr, &sendaddr) < 0)
                                {
-                                       Con_DPrintf("wrong reply address\n");
-                                       Con_DPrintf("Expected: %s\n", StrAddr (&sendaddr));
-                                       Con_DPrintf("Received: %s\n", StrAddr (&readaddr));
+                                       char tempaddress1[64], tempaddress2[64];
+                                       dfunc.GetNameFromAddr (&sendaddr, tempaddress1);
+                                       dfunc.GetNameFromAddr (&readaddr, tempaddress2);
+                                       Con_Printf("wrong reply address (Expected: %s Received: %s)\n", tempaddress1, tempaddress2);
+                                       CL_UpdateScreen ();
                                        CL_UpdateScreen ();
                                        ret = 0;
                                        continue;
                                }
 
-                               if (ret < sizeof(int))
+                               if (ret < (int)sizeof(int))
                                {
                                        ret = 0;
                                        continue;
@@ -1347,7 +1377,7 @@ static qsocket_t *_Datagram_Connect (const char *host)
                                        ret = 0;
                                        continue;
                                }
-                               if ((control & (~NETFLAG_LENGTH_MASK)) !=  NETFLAG_CTL)
+                               if ((control & (~NETFLAG_LENGTH_MASK)) != (int)NETFLAG_CTL)
                                {
                                        ret = 0;
                                        continue;
@@ -1462,6 +1492,7 @@ static void _Datagram_Heartbeat (const char *master)
                portnum = MASTER_PORT;
        dfunc.SetSocketPort (&masteraddr, portnum);
 
+       // FIXME: this is the only use of UDP_Send in the entire engine, add a dfunc.acceptSock to get rid of this function!
        dfunc.Send (net_message.data, net_message.cursize, &masteraddr);
 }