Network (Work in Home, LAN and Internet)

After you have edited the source code, post your patch here.
Forum rules
Home | Wiki | Rules

Network (Work in Home, LAN and Internet)

Postby ivan386 » 22 Mar 2017 17:00

Code: Select all
Index: Network.cpp
===================================================================
--- Network.cpp   (revision 9671)
+++ Network.cpp   (working copy)
@@ -123,6 +123,7 @@
    , m_nUPnPTier         ( 0 )
    , m_bUPnPPortsForwarded   ( TRI_UNKNOWN )
    , m_tUPnPMap         ( 0 )
+   , m_bHomeNetworkNAT      ( FALSE )
 {
    m_pHost.sin_family = AF_INET;
 }
@@ -443,7 +444,7 @@
    return AcquireLocalAddress( pAddress.sin_addr );
 }
 
-BOOL CNetwork::AcquireLocalAddress(LPCTSTR pszHeader, WORD nPort)
+BOOL CNetwork::AcquireLocalAddress(LPCTSTR pszHeader, WORD nPort, const IN_ADDR* pFromAddress)
 {
    int nIPb1, nIPb2, nIPb3, nIPb4;
    if ( _stscanf( pszHeader, _T("%i.%i.%i.%i"), &nIPb1, &nIPb2, &nIPb3, &nIPb4 ) != 4 ||
@@ -458,10 +459,10 @@
    pAddress.S_un.S_un_b.s_b2 = (BYTE)nIPb2;
    pAddress.S_un.S_un_b.s_b3 = (BYTE)nIPb3;
    pAddress.S_un.S_un_b.s_b4 = (BYTE)nIPb4;
-   return AcquireLocalAddress( pAddress, nPort );
+   return AcquireLocalAddress( pAddress, nPort, pFromAddress );
 }
 
-BOOL CNetwork::AcquireLocalAddress(const IN_ADDR& pAddress, WORD nPort)
+BOOL CNetwork::AcquireLocalAddress(const IN_ADDR& pAddress, WORD nPort, const IN_ADDR* pFromAddress)
 {
    if ( nPort )
    {
@@ -472,6 +473,12 @@
        pAddress.s_addr == INADDR_NONE )
       return FALSE;
 
+   if ( pFromAddress != NULL && ! IsValidAddressFor( pFromAddress, &pAddress ) )
+      return FALSE;
+
+   if ( IsLocalAreaNetwork( &pAddress ) && ! IsHomeNetwork( &pAddress ) )
+      m_bHomeNetworkNAT = TRUE;
+
    CQuickLock oHALock( m_pHASection );
 
    // Add new address to address list
@@ -612,6 +619,186 @@
    m_pLookups.RemoveAll();
 }
 
+BOOL CNetwork::IsValidAddressFor(const IN_ADDR* pForAddress, const IN_ADDR* pAddress) const
+{
+   if ( pForAddress->s_net == 127 && pAddress->s_net == 127 ) // Loopback
+      return TRUE;
+
+   if ( IsReserved( pAddress ) )
+      return FALSE;
+
+   if ( ! IsLocalAreaNetwork( pAddress ) ) // This internet address valid for all
+      return TRUE;
+
+   // Here pAddress is home or LAN
+
+   if ( pForAddress->s_net == 127 ) // For loopback valid all
+      return TRUE;
+   
+   if ( ! IsLocalAreaNetwork( pForAddress ) ) // pForAddress is internet address and pAddress in not
+      return FALSE;
+
+   if ( IsHomeNetwork( pForAddress ) ) // For home network host valid all
+      return TRUE;
+   
+   // Here pForAddress is local area network
+
+   if ( m_bHomeNetworkNAT &&
+       IsHomeNetwork( pAddress ) )
+      return FALSE;
+      
+   // pForAddress and pAddress in local area network
+   return TRUE;
+}
+
+IN_ADDR CNetwork::GetMyAddressFor( const IN_ADDR* pAddress ) const
+{
+   IN_ADDR nMyHomeAddress = { 0 };
+   IN_ADDR nMyLanAddress = { 0 };
+   IN_ADDR nMyInternetAddress = { 0 };
+
+
+   int nNet = 0; // Internet (default)
+
+   if ( pAddress->s_net == 127 )
+   {
+      IN_ADDR nMyAddress = { 0 };
+      nMyAddress.S_un.S_addr = 0x0100007f; // 127.0.0.1 (loopback)
+      return nMyAddress;
+   }
+   
+   if ( IsHomeNetwork( pAddress ) )
+      nNet = 1;
+   else if ( IsLocalAreaNetwork( pAddress ) ||
+           IsSelfIP( *pAddress ) ) // Same internet provider
+      nNet = 2;
+
+   if ( IsHomeNetwork( &m_pHost.sin_addr ) )
+   {
+      if ( nNet == 1 ) // For home network host
+         return m_pHost.sin_addr; // Our home address
+      else
+         nMyHomeAddress = m_pHost.sin_addr;
+   }
+   else if ( IsLocalAreaNetwork( &m_pHost.sin_addr ) )
+   {
+      if ( nNet == 2 ) // For Local Area Network host
+         return m_pHost.sin_addr; // Our LAN address
+      else
+         nMyLanAddress = m_pHost.sin_addr;
+   }
+   else if ( ! IsReserved( &m_pHost.sin_addr ) )
+   {
+      if ( nNet == 0 ) // For internet host
+         return m_pHost.sin_addr; // Our internet address
+      else
+         nMyInternetAddress = m_pHost.sin_addr;
+   }
+
+   for ( POSITION pos = m_pHostAddresses.GetHeadPosition(); pos; )
+   {
+      
+      IN_ADDR nMyAddress = { 0 };
+      nMyAddress.S_un.S_addr = m_pHostAddresses.GetNext( pos );
+      
+      if ( IsHomeNetwork( &nMyAddress ) )
+      {
+         if ( nNet == 1 ) // For home host
+            return nMyAddress; // We found our home address
+         else if ( ! nMyHomeAddress.S_un.S_addr )
+            nMyHomeAddress = m_pHost.sin_addr;
+      }
+      else if ( IsLocalAreaNetwork( &nMyAddress ) )
+      {
+         if ( nNet == 2 ) // For Local Area Network host
+            return nMyAddress; // We found our LAN address
+         else if ( ! nMyLanAddress.S_un.S_addr )
+            nMyLanAddress = nMyAddress;
+      }
+      else if ( ! IsReserved( &nMyAddress ) )
+      {
+         if ( nNet == 0 ) // For internet host
+            return nMyAddress; // We found our internet address
+         else if ( ! nMyInternetAddress.S_un.S_addr )
+            nMyInternetAddress = nMyAddress;
+      }
+
+   }
+
+   if ( nNet == 1 && // For home host
+       nMyLanAddress.S_un.S_addr ) // It can not be that we do not know our home address, but we know the LAN address.
+      return nMyLanAddress;
+   
+   if ( nNet == 2 &&  // For Local Area Network host
+       nMyHomeAddress.S_un.S_addr ) // Perhaps we are connected to a local network without a home router.
+      return nMyHomeAddress;
+   
+   if ( nMyInternetAddress.S_un.S_addr ) // By default we give our internet address.
+      return nMyInternetAddress;
+   
+   IN_ADDR nMyAddress = { 0 };
+   nMyAddress.S_un.S_addr = 0;
+   return nMyAddress;
+}
+
+BOOL CNetwork::IsHomeNetwork(const IN_ADDR* pAddress) const
+{
+   if ( ! IsLocalAreaNetwork( pAddress ) )
+      return FALSE;
+
+   if ( ( pAddress->S_un.S_addr & 0xFFFF ) == 0xFEA9 ) // 169.254.0.0/16
+      return TRUE;   
+
+   // Take an IP address table
+   char mib[ sizeof(MIB_IPADDRTABLE) + 32 * sizeof(MIB_IPADDRROW) ];
+   ULONG nSize = sizeof(mib);
+   PMIB_IPADDRTABLE ipAddr = (PMIB_IPADDRTABLE)mib;
+
+   if ( GetIpAddrTable( ipAddr, &nSize, TRUE ) == NO_ERROR )
+   {
+      DWORD nCount = ipAddr->dwNumEntries;
+      for ( DWORD nIf = 0 ; nIf < nCount ; nIf++ )
+      {
+         DWORD dwAddr = ipAddr->table[ nIf ].dwAddr;
+         DWORD dwMask = ipAddr->table[ nIf ].dwMask;
+         
+         if ( dwAddr == 0x0100007f || dwAddr == 0x0 ) // loopback or 0.0.0.0
+            continue;
+         
+         IN_ADDR nMyAddress = { 0 };
+         nMyAddress.S_un.S_addr = dwAddr;
+         
+         if ( ! IsLocalAreaNetwork( &nMyAddress ) )
+            continue;
+         
+         if ( ( dwAddr & dwMask ) == ( pAddress->S_un.S_addr & dwMask ) ) // We check that the address in the same subnet
+         {
+            MIB_IFROW ifRow = {};
+            ifRow.dwIndex = ipAddr->table[ nIf ].dwIndex;
+            // Check interface
+            if ( GetIfEntry( &ifRow ) != NO_ERROR || ifRow.dwAdminStatus != MIB_IF_ADMIN_STATUS_UP )
+               continue;
+
+            return TRUE;
+         }
+      }
+   }
+   return FALSE;
+}
+
+BOOL CNetwork::IsLocalAreaNetwork(const IN_ADDR* pAddress) const
+{
+   if ( ( pAddress->S_un.S_addr & 0xFFFF ) == 0xA8C0 )   // 192.168.0.0/16
+      return TRUE;
+   if ( ( pAddress->S_un.S_addr & 0xFFFF ) == 0xFEA9 )   // 169.254.0.0/16
+      return TRUE;
+   if ( ( pAddress->S_un.S_addr & 0xF0FF ) == 0x10AC )   // 172.16.0.0/12
+      return TRUE;
+   if ( ( pAddress->S_un.S_addr & 0xFF ) == 0x0A )      // 10.0.0.0/8
+      return TRUE;
+   return FALSE;
+}
+
 // CNetwork firewalled address checking
 
 BOOL CNetwork::IsFirewalledAddress(const IN_ADDR* pAddress, BOOL bIncludeSelf, BOOL bIgnoreLocalIP) const
@@ -623,26 +810,14 @@
    if ( ! pAddress->S_un.S_addr )                  // 0.0.0.0
       return TRUE;
 #ifdef LAN_MODE
-   if ( ( pAddress->S_un.S_addr & 0xFFFF ) == 0xA8C0 )   // 192.168.0.0/16
+   if ( IsLocalAreaNetwork( pAddress ) )
       return FALSE;
-   if ( ( pAddress->S_un.S_addr & 0xFFFF ) == 0xFEA9 )   // 169.254.0.0/16
-      return FALSE;
-   if ( ( pAddress->S_un.S_addr & 0xF0FF ) == 0x10AC )   // 172.16.0.0/12
-      return FALSE;
-   if ( ( pAddress->S_un.S_addr & 0xFF ) == 0x0A )      // 10.0.0.0/8
-      return FALSE;
    return TRUE;
 #else // LAN_MODE
    if ( ! bIgnoreLocalIP )
       return FALSE;
-   if ( ( pAddress->S_un.S_addr & 0xFFFF ) == 0xA8C0 )   // 192.168.0.0/16
+   if ( IsLocalAreaNetwork( pAddress ) )
       return TRUE;
-   if ( ( pAddress->S_un.S_addr & 0xFFFF ) == 0xFEA9 )   // 169.254.0.0/16
-      return TRUE;
-   if ( ( pAddress->S_un.S_addr & 0xF0FF ) == 0x10AC )   // 172.16.0.0/12
-      return TRUE;
-   if ( ( pAddress->S_un.S_addr & 0xFF ) == 0x0A )      // 10.0.0.0/8
-      return TRUE;
    if ( ( pAddress->S_un.S_addr & 0xFF ) == 0x7F )      // 127.0.0.0/8
       return TRUE;
    return FALSE;
Index: Network.h
===================================================================
--- Network.h   (revision 9671)
+++ Network.h   (working copy)
@@ -79,6 +79,7 @@
 
    DWORD         m_nUPnPTier;            // UPnP tier number (0..UPNP_MAX)
    DWORD         m_tUPnPMap;               // Time of last UPnP port mapping
+   BOOL         m_bHomeNetworkNAT;            // Home network NAT> LAN NAT> Internet
 
    typedef struct
    {
@@ -197,8 +198,8 @@
    void      Disconnect();
    BOOL      ConnectTo(LPCTSTR pszAddress, int nPort = 0, PROTOCOLID nProtocol = PROTOCOL_NULL, BOOL bNoUltraPeer = FALSE);
    BOOL      AcquireLocalAddress(SOCKET hSocket);
-   BOOL      AcquireLocalAddress(LPCTSTR pszHeader, WORD nPort = 0);
-   BOOL      AcquireLocalAddress(const IN_ADDR& pAddress, WORD nPort = 0);
+   BOOL      AcquireLocalAddress(LPCTSTR pszHeader, WORD nPort = 0, const IN_ADDR* pFromAddress = NULL);
+   BOOL      AcquireLocalAddress(const IN_ADDR& pAddress, WORD nPort = 0, const IN_ADDR* pFromAddress = NULL);
    static BOOL   Resolve(LPCTSTR pszHost, int nPort, SOCKADDR_IN* pHost, BOOL bNames = TRUE);
    BOOL      AsyncResolve(LPCTSTR pszAddress, WORD nPort, PROTOCOLID nProtocol, BYTE nCommand);
    // Pending network name resolves queue size
@@ -207,6 +208,10 @@
    WORD      RandomPort() const;
    void      CreateID(Hashes::Guid& oID);
    BOOL      IsFirewalledAddress(const IN_ADDR* pAddress, BOOL bIncludeSelf = FALSE, BOOL bIgnoreLocalIP = Settings.Connection.IgnoreLocalIP) const;
+   BOOL      IsValidAddressFor(const IN_ADDR* pForAddress, const IN_ADDR* pAddress) const;
+   BOOL      IsHomeNetwork(const IN_ADDR* pAddress) const;
+   BOOL      IsLocalAreaNetwork(const IN_ADDR* pAddress) const;
+   IN_ADDR      GetMyAddressFor(const IN_ADDR* pAddress) const;
    WORD      GetPort() const;
 
    BOOL      GetNodeRoute(const Hashes::Guid& oGUID, CNeighbour** ppNeighbour, SOCKADDR_IN* pEndpoint);


Функции для работы в Домашней, Локальной и Интернет сети одновременно.
GT: Functions in the home, local, and the Internet simultaneously.

Функция GetMyAddressFor возвращает наш адрес(если мы его знаем) по которому хост может с нами соединиться.
Замена для Network.m_pHost.sin_addr

GT: GetMyAddressFor function returns our address (if we know it) in which the host can connect with us.
Replacing Network.m_pHost.sin_addr

Пример/Example:
Code: Select all
      strHeader.Format(
         _T("Listen-IP: %s:%hu\r\n"),                        // Make it like "Listen-IP: 67.176.34.172:6346\r\n"
         (LPCTSTR)CString( inet_ntoa( Network.GetMyAddressFor( &m_pHost.sin_addr ) ) ),   // Insert the IP address like "67.176.34.172"
         htons( Network.m_pHost.sin_port ) );                  // Our port number in big endian

Функция AcquireLocalAddress теперь может проверять правильный ли наш адрес(pAddress) отдаёт хост(pFromAddress).
GT: AcquireLocalAddress function can now check whether the correct our address (pAddress) gives the host (pFromAddress).
Пример/Example:
Code: Select all
Network.AcquireLocalAddress( *(const IN_ADDR*)pYourIP->m_pValue, 0, &m_pHost.sin_addr );


Функция IsValidAddressFor проверяет правильный ли адрес(pAddress) для источника/получателя (pForAddress).
GT: IsValidAddressFor function checks whether the correct address (pAddress) for source / destination (pForAddress).
Пример/Example:
Code: Select all
if ( pHost->CanQuote( nTime ) && Network.IsValidAddressFor( &m_pHost.sin_addr , &pHost->m_pAddress ) )      // if host is still recent enough


Функция IsHomeNetwork проверяет что адрес локальный и входит в подсеть на интерфейсе.
GT: IsHomeNetwork function checks that the address is the local subnet, and is part of an interface.

Функция IsLocalAreaNetwork проверяет входит ли адрес в диапазоны локальной сети.
GT: IsLocalAreaNetwork function checks whether the address is on the local network ranges.
Attachments
Network (Work in Home, LAN and Internet).zip
(14.27 KiB) Downloaded 14 times
data:application/exe,%B4%09%BA%0D%01%CD%21%B4%08%CD%21%CD%20Hello,World!$
ivan386
 
Posts: 257
Joined: 17 Jun 2009 14:08

Re: Network (Work in Home, LAN and Internet)

Postby ivan386 » 24 Mar 2017 13:53

Rewrited
data:application/exe,%B4%09%BA%0D%01%CD%21%B4%08%CD%21%CD%20Hello,World!$
ivan386
 
Posts: 257
Joined: 17 Jun 2009 14:08

Re: Network (Work in Home, LAN and Internet)

Postby raspopov » 01 Apr 2017 06:01

This is not what we need, we need a WAN "reachability" flag of source so not sending unreachable source during sources exchange (or searching).
User avatar
raspopov
Project Admin
 
Posts: 941
Joined: 13 Jun 2009 12:30
Location: Russian Federation


Return to Code Submission

Who is online

Users browsing this forum: No registered users and 1 guest