From af5c31a4f590a09de27362b13e49738dd0b9a4a1 Mon Sep 17 00:00:00 2001 From: thunder2 Date: Mon, 1 Jul 2013 15:12:06 +0000 Subject: [PATCH] Use the best network interface to route an ip instead of the first interface in getLocalInterfaces on Windows. git-svn-id: http://svn.code.sf.net/p/retroshare/code/trunk@6469 b45a01b8-16f6-495d-af2f-9b41ad6348cc --- libretroshare/src/pqi/p3netmgr.cc | 2 +- libretroshare/src/pqi/pqinetwork.cc | 54 ++++++++++++++++++++++------- libretroshare/src/pqi/pqinetwork.h | 4 +-- libretroshare/src/util/rswin.h | 13 +++++++ 4 files changed, 57 insertions(+), 16 deletions(-) diff --git a/libretroshare/src/pqi/p3netmgr.cc b/libretroshare/src/pqi/p3netmgr.cc index 557d62e15..aa2a3361c 100644 --- a/libretroshare/src/pqi/p3netmgr.cc +++ b/libretroshare/src/pqi/p3netmgr.cc @@ -905,7 +905,7 @@ bool p3NetMgrIMPL::checkNetAddress() struct in_addr prefAddr; struct sockaddr_in oldAddr; - validAddr = getPreferredInterface(prefAddr); + validAddr = getPreferredInterface(mLocalAddr.sin_addr, prefAddr); /* if we don't have a valid address - reset */ if (!validAddr) diff --git a/libretroshare/src/pqi/pqinetwork.cc b/libretroshare/src/pqi/pqinetwork.cc index 3a59a2351..b57db7ce9 100644 --- a/libretroshare/src/pqi/pqinetwork.cc +++ b/libretroshare/src/pqi/pqinetwork.cc @@ -147,7 +147,7 @@ std::string socket_errorType(int err) #include #include -bool getLocalInterfaces(std::list &addrs) +bool getLocalInterfaces(struct in_addr &/*routeAddr*/, std::list &addrs) { int sock = 0; struct ifreq ifreq; @@ -328,18 +328,23 @@ std::string socket_errorType(int err) // A function to determine the interfaces on your computer.... // No idea of how to do this in windows.... // see if it compiles. -bool getLocalInterfaces(std::list &addrs) +bool getLocalInterfaces(struct in_addr &routeAddr, std::list &addrs) { + // Get the best interface for transport to routeAddr + // This interface should be first in list! + DWORD bestInterface; + if (GetBestInterface((IPAddr) routeAddr.s_addr, &bestInterface) != NO_ERROR) + { + bestInterface = 0; + } /* USE MIB IPADDR Interface */ PMIB_IPADDRTABLE iptable = NULL; DWORD dwSize = 0; - if (GetIpAddrTable(iptable, &dwSize, 0) != - ERROR_INSUFFICIENT_BUFFER) + if (GetIpAddrTable(iptable, &dwSize, 0) != ERROR_INSUFFICIENT_BUFFER) { - pqioutput(PQL_ALERT, pqinetzone, - "Cannot Find Windoze Interfaces!"); + pqioutput(PQL_ALERT, pqinetzone, "Cannot Find Windoze Interfaces!"); exit(0); } @@ -348,15 +353,38 @@ bool getLocalInterfaces(std::list &addrs) struct in_addr addr; - for(unsigned int i = 0; i < iptable -> dwNumEntries; i++) + for (unsigned int i = 0; i < iptable -> dwNumEntries; i++) { + MIB_IPADDRROW &ipaddr = iptable->table[i]; + std::string out; - addr.s_addr = iptable->table[i].dwAddr; - rs_sprintf(out, "Iface(%ld) => %s\n", iptable->table[i].dwIndex, rs_inet_ntoa(addr).c_str()); - pqioutput(PQL_DEBUG_BASIC, pqinetzone, out); + addr.s_addr = ipaddr.dwAddr; + rs_sprintf(out, "Iface(%ld) => %s\n", ipaddr.dwIndex, rs_inet_ntoa(addr).c_str()); - addrs.push_back(addr); + unsigned short wType = ipaddr.unused2; // should be wType + if (wType & MIB_IPADDR_DISCONNECTED) + { + pqioutput(PQL_DEBUG_BASIC, pqinetzone, "Interface disconnected, " + out); + continue; + } + + if (wType & MIB_IPADDR_DELETED) + { + pqioutput(PQL_DEBUG_BASIC, pqinetzone, "Interface deleted, " + out); + continue; + } + + if (ipaddr.dwIndex == bestInterface) + { + pqioutput(PQL_DEBUG_BASIC, pqinetzone, "Best address, " + out); + addrs.push_front(addr); + } + else + { + pqioutput(PQL_DEBUG_BASIC, pqinetzone, out); + addrs.push_back(addr); + } } free (iptable); @@ -529,7 +557,7 @@ int inaddr_cmp(struct sockaddr_in addr1, unsigned long addr2) } -bool getPreferredInterface(struct in_addr &prefAddr) // returns best addr. +bool getPreferredInterface(in_addr &routeAddr, struct in_addr &prefAddr) // returns best addr. { std::list addrs; std::list::iterator it; @@ -544,7 +572,7 @@ bool getPreferredInterface(struct in_addr &prefAddr) // returns best addr. bool found_priv = false; bool found_ext = false; - if (!getLocalInterfaces(addrs)) + if (!getLocalInterfaces(routeAddr, addrs)) { return false; } diff --git a/libretroshare/src/pqi/pqinetwork.h b/libretroshare/src/pqi/pqinetwork.h index 10bdcdb7e..9c1be7473 100644 --- a/libretroshare/src/pqi/pqinetwork.h +++ b/libretroshare/src/pqi/pqinetwork.h @@ -101,8 +101,8 @@ int sockaddr_cmp(struct sockaddr_in &addr1, struct sockaddr_in &addr2 ); int inaddr_cmp(struct sockaddr_in addr1, struct sockaddr_in addr2 ); int inaddr_cmp(struct sockaddr_in addr1, unsigned long); -bool getPreferredInterface(struct in_addr &prefAddr); // returns best addr. -bool getLocalInterfaces(std::list &addrs); // returns all possible addrs. +bool getPreferredInterface(struct in_addr &routeAddr, struct in_addr &prefAddr); // returns best addr. +bool getLocalInterfaces(in_addr &routeAddr, std::list &addrs); // returns all possible addrs. // checks (addr1 & 255.255.255.0) == (addr2 & 255.255.255.0) bool isSameSubnet(struct in_addr *addr1, struct in_addr *addr2); diff --git a/libretroshare/src/util/rswin.h b/libretroshare/src/util/rswin.h index f8c3e189b..9642bb351 100644 --- a/libretroshare/src/util/rswin.h +++ b/libretroshare/src/util/rswin.h @@ -45,6 +45,19 @@ // For win32 systems (tested on MingW+Ubuntu) #define stat64 _stati64 +// Should be in Iphlpapi.h, but mingw doesn't seem to have these +// Values copied directly from: +// http://msdn.microsoft.com/en-us/library/aa366845(v=vs.85).aspx +// (Title: MIB_IPADDRROW structure) + +#ifndef MIB_IPADDR_DISCONNECTED +#define MIB_IPADDR_DISCONNECTED 0x0008 // Address is on disconnected interface +#endif + +#ifndef MIB_IPADDR_DELETED +#define MIB_IPADDR_DELETED 0x0040 // Address is being deleted +#endif + #endif // WINDOWS_SYS #endif // RSWIN_H_