diff --git a/libretroshare/src/pqi/p3netmgr.cc b/libretroshare/src/pqi/p3netmgr.cc index 8b34333e2..df33f01be 100644 --- a/libretroshare/src/pqi/p3netmgr.cc +++ b/libretroshare/src/pqi/p3netmgr.cc @@ -925,7 +925,9 @@ bool p3NetMgrIMPL::checkNetAddress() } else { - validAddr = getPreferredInterface(mLocalAddr, prefAddr); + std::list addrs; + validAddr = getLocalAddresses(addrs); + if (validAddr) prefAddr = addrs.front(); } diff --git a/libretroshare/src/pqi/pqinetwork.cc b/libretroshare/src/pqi/pqinetwork.cc index 7637cd268..22509356d 100644 --- a/libretroshare/src/pqi/pqinetwork.cc +++ b/libretroshare/src/pqi/pqinetwork.cc @@ -38,7 +38,8 @@ #include "util/rsdebug.h" #include "util/rsstring.h" -#include +#include "util/rsnet.h" + static const int pqinetzone = 96184; /***** @@ -144,78 +145,6 @@ std::string socket_errorType(int err) return std::string("UNKNOWN ERROR CODE - ASK RS-DEVS TO ADD IT!"); } -#include -#include - -bool getLocalInterfaces_ipv4(struct in_addr &/*routeAddr*/, std::list &addrs) -{ - int sock = 0; - struct ifreq ifreq; - - struct if_nameindex *iflist = if_nameindex(); - struct if_nameindex *ifptr = iflist; - - //need a socket for ioctl() - if( (sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) - { - pqioutput(PQL_ALERT, pqinetzone, - "Cannot Determine Local Addresses!"); - return false; - } - - if (!ifptr) - { - pqioutput(PQL_ALERT, pqinetzone, - "getLocalInterfaces(): ERROR if_nameindex == NULL"); - return false; - } - - // loop through the interfaces. - for(; ifptr->if_index != 0; ++ifptr) - { - //copy in the interface name to look up address of - strncpy(ifreq.ifr_name, ifptr->if_name, IF_NAMESIZE); - - if(ioctl(sock, SIOCGIFADDR, &ifreq) != 0) - { - std::string out; - rs_sprintf(out, "Cannot Determine Address for Iface: %s", ifptr -> if_name); - pqioutput(PQL_DEBUG_BASIC, pqinetzone, out); - } - else - { - struct sockaddr_in *aptr = - (struct sockaddr_in *) &ifreq.ifr_addr; - std::string astr =rs_inet_ntoa(aptr -> sin_addr); - - std::string out; - rs_sprintf(out, "Iface: %s\n Address: %s", ifptr -> if_name, astr.c_str()); - pqioutput(PQL_DEBUG_BASIC, pqinetzone, out); - - // Now check wether the interface is up and running. If not, we don't use it!! - // - if(ioctl(sock,SIOCGIFFLAGS,&ifreq) != 0) - { - std::cerr << "Could not get flags from interface " << ifptr -> if_name << std::endl ; - continue ; - } -#ifdef NET_DEBUG - std::cout << out.str() ; - std::cout << "flags = " << ifreq.ifr_flags << std::endl ; -#endif - if((ifreq.ifr_flags & IFF_UP) == 0) continue ; - if((ifreq.ifr_flags & IFF_RUNNING) == 0) continue ; - - addrs.push_back(aptr->sin_addr); - } - } - // free socket -> or else run out of fds. - close(sock); - - if_freenameindex(iflist); - return (addrs.size() > 0); -} - /********************************** WINDOWS/UNIX SPECIFIC PART ******************/ #else @@ -434,396 +363,32 @@ in_addr_t inet_network(const char *inet_name) #endif /********************************** WINDOWS/UNIX SPECIFIC PART ******************/ -#include +#include +#include +#include -// This returns in Net Byte Order. -// NB: Linux man page claims it is in Host Byte order, but -// this is blatantly wrong!..... (for Debian anyway) -// Making this consistent with the Actual behavior (rather than documented). -in_addr_t pqi_inet_netof(struct in_addr addr) +bool getLocalAddresses(std::list & addrs) { - // decide if A class address. - unsigned long haddr = ntohl(addr.s_addr); - unsigned long abit = haddr & 0xff000000UL; - unsigned long bbit = haddr & 0xffff0000UL; - unsigned long cbit = haddr & 0xffffff00UL; + struct ifaddrs *ifsaddrs, *ifa; + if(getifaddrs(&ifsaddrs) != 0) exit(1); -#ifdef NET_DEBUG - std::cerr << "inet_netof(" << rs_inet_ntoa(addr) << ") "; -#endif - - if (!((haddr >> 31) | 0x0UL)) // MSB = 0 - { -#ifdef NET_DEBUG - std::cerr << " Type A " << std::endl; - std::cerr << "\tShifted(31): " << (haddr >> 31); - std::cerr << " Xord(0x0UL): " << - !((haddr >> 31) | 0x0UL) << std::endl; -#endif - - return htonl(abit); - } - else if (!((haddr >> 30) ^ 0x2UL)) // 2MSBs = 10 - { -#ifdef NET_DEBUG - std::cerr << " Type B " << std::endl; - std::cerr << "\tShifted(30): " << (haddr >> 30); - std::cerr << " Xord(0x2UL): " << - !((haddr >> 30) | 0x2UL) << std::endl; -#endif - - return htonl(bbit); - } - else if (!((haddr >> 29) ^ 0x6UL)) // 3MSBs = 110 - { -#ifdef NET_DEBUG - std::cerr << " Type C " << std::endl; - std::cerr << "\tShifted(29): " << (haddr >> 29); - std::cerr << " Xord(0x6UL): " << - !((haddr >> 29) | 0x6UL) << std::endl; -#endif - - return htonl(cbit); - } - else if (!((haddr >> 28) ^ 0xeUL)) // 4MSBs = 1110 - { -#ifdef NET_DEBUG - std::cerr << " Type Multicast " << std::endl; - std::cerr << "\tShifted(28): " << (haddr >> 28); - std::cerr << " Xord(0xeUL): " << - !((haddr >> 29) | 0xeUL) << std::endl; -#endif - - return addr.s_addr; // return full address. - } - else if (!((haddr >> 27) ^ 0x1eUL)) // 5MSBs = 11110 - { -#ifdef NET_DEBUG - std::cerr << " Type Reserved " << std::endl; - std::cerr << "\tShifted(27): " << (haddr >> 27); - std::cerr << " Xord(0x1eUL): " << - !((haddr >> 27) | 0x1eUL) << std::endl; -#endif - - return addr.s_addr; // return full address. - } - return htonl(abit); -} - -int sockaddr_cmp(struct sockaddr_in &addr1, struct sockaddr_in &addr2 ) -{ - if (addr1.sin_family != addr2.sin_family) - return addr1.sin_family - addr2.sin_family; - if (addr1.sin_addr.s_addr != addr2.sin_addr.s_addr) - return (addr1.sin_addr.s_addr - addr2.sin_addr.s_addr); - if (addr1.sin_port != addr2.sin_port) - return (addr1.sin_port - addr2.sin_port); - return 0; -} - -int inaddr_cmp(struct sockaddr_in addr1, struct sockaddr_in addr2 ) -{ -#ifdef NET_DEBUG - std::string out; - rs_sprintf(out, "inaddr_cmp(%s-%lu,%s-%lu)", rs_inet_ntoa(addr1.sin_addr).c_str(), addr1.sin_addr.s_addr, rs_inet_ntoa(addr2.sin_addr).c_str(), addr2.sin_addr.s_addr); - pqioutput(PQL_DEBUG_BASIC, pqinetzone, out); -#endif - - - if (addr1.sin_addr.s_addr == addr2.sin_addr.s_addr) - { - return 0; - } - if (addr1.sin_addr.s_addr < addr2.sin_addr.s_addr) - return -1; - return 1; -} - -int inaddr_cmp(struct sockaddr_in addr1, unsigned long addr2) -{ -#ifdef NET_DEBUG - struct in_addr inaddr_tmp; - inaddr_tmp.s_addr = addr2; - - std::string out; - rs_sprintf(out, "inaddr_cmp2(%s vs %s /or/ %10x vs %10x)", rs_inet_ntoa(addr1.sin_addr).c_str(), rs_inet_ntoa(inaddr_tmp).c_str(), addr1.sin_addr.s_addr, addr2); - pqioutput(PQL_DEBUG_BASIC, pqinetzone, out); -#endif - - if (addr1.sin_addr.s_addr == addr2) - { - return 0; - } - if (addr1.sin_addr.s_addr < addr2) - return -1; - return 1; -} - -bool getPreferredInterface_ipv4(in_addr &routeAddr, struct in_addr &prefAddr) // returns best addr. -{ - std::list addrs; - std::list::iterator it; - struct in_addr addr_zero, addr_loop, addr_priv, addr_ext; - -#ifdef NET_DEBUG - struct in_addr addr; -#endif - - bool found_zero = false; - bool found_loopback = false; - bool found_priv = false; - bool found_ext = false; - - if (!getLocalInterfaces_ipv4(routeAddr, addrs)) - { - return false; - } - - memset(&addr_zero, 0, sizeof(addr_zero)); - memset(&addr_loop, 0, sizeof(addr_loop)); - memset(&addr_priv, 0, sizeof(addr_priv)); - memset(&addr_ext, 0, sizeof(addr_ext)); - -#ifdef NET_DEBUG - memset(&addr, 0, sizeof(addr)); -#endif - - // find the first of each of these. - // if ext - take first. - // if no ext -> first priv - // if no priv -> first loopback. - -#ifdef NET_DEBUG - std::cerr << "getPreferredInterface() " << addrs.size() << " interfaces." << std::endl; -#endif - - for(it = addrs.begin(); it != addrs.end(); ++it) - { - struct in_addr addr = *it; - -#ifdef NET_DEBUG - std::cerr << "Examining addr: " << rs_inet_ntoa(addr); - std::cerr << " => " << (uint32_t) addr.s_addr << std::endl ; -#endif - - // for windows silliness (returning 0.0.0.0 as valid addr!). - if (addr.s_addr == 0) + addrs.clear(); + for ( ifa = ifsaddrs; ifa; ifa = ifa->ifa_next ) + if ( (ifa->ifa_flags & IFF_UP) && !(ifa->ifa_flags & IFF_LOOPBACK) ) { - if (!found_zero) - { -#ifdef NET_DEBUG - std::cerr << "\tFound Zero Address" << std::endl ; -#endif - - found_zero = true; - addr_zero = addr; - } + sockaddr_storage * tmp = new sockaddr_storage; + if (sockaddr_storage_copyip(* tmp, * (const struct sockaddr_storage *) ifa->ifa_addr)) + addrs.push_back(*tmp); + else delete tmp; } - else if (isLoopbackNet(&addr)) - { - if (!found_loopback) - { -#ifdef NET_DEBUG - std::cerr << "\tFound Loopback Address" << std::endl ; -#endif - found_loopback = true; - addr_loop = addr; - } - } - else if (isPrivateNet(&addr)) - { - if (!found_priv) - { -#ifdef NET_DEBUG - std::cerr << "\tFound Private Address" << std::endl ; -#endif + freeifaddrs(ifsaddrs); - found_priv = true; - addr_priv = addr; - } - } - else - { - if (!found_ext) - { -#ifdef NET_DEBUG - std::cerr << "\tFound Other Address (Ext?) " << std::endl ; -#endif - found_ext = true; - addr_ext = addr; - } - } - } - - if(found_ext) // external address is best. - { - prefAddr = addr_ext; - return true; - } - - if (found_priv) - { - prefAddr = addr_priv; - return true; - } - - // next bit can happen under windows, - // a general address is still - // preferable to a loopback device. - if (found_zero) - { - prefAddr = addr_zero; - return true; - } - - if (found_loopback) - { - prefAddr = addr_loop; - return true; - } - - // shound be 255.255.255.255 (error). - prefAddr.s_addr = 0xffffffff; - return false; + return (!addrs.empty()); } - -bool getPreferredInterface(const struct sockaddr_storage & existAddr, struct sockaddr_storage & prefAddr) -{ - struct in_addr existing_addr; - struct in_addr pref_addr; - - { - struct sockaddr_in *eaddr = (sockaddr_in *) &existAddr; - if (eaddr->sin_family != AF_INET) - { - std::cerr << "getPreferredInterface() ERROR only valid for IPv4 for now"; - return false; // TODO:IPV6 - } - existing_addr = eaddr->sin_addr; - } - - if (getPreferredInterface_ipv4(existing_addr, pref_addr)) - { - /* store into prefAddr */ - sockaddr_storage_clear(prefAddr); - struct sockaddr_in *addr = (sockaddr_in *) &prefAddr; - addr->sin_family = AF_INET; - addr->sin_addr = pref_addr; - addr->sin_port = htons(0); - - return true; - } - return false; -} - - -bool getLocalInterfaces(struct sockaddr_storage &existAddr, std::list &addrs) -{ - struct in_addr existing_addr; - std::list local_addrs; - - { - struct sockaddr_in *eaddr = (sockaddr_in *) &existAddr; - if (eaddr->sin_family != AF_INET) - { - std::cerr << "getLocalInterfaces() ERROR only valid for IPv4 for now"; - return false; // TODO:IPV6 - } - existing_addr = eaddr->sin_addr; - } - - if (getLocalInterfaces_ipv4(existing_addr, local_addrs)) - { - std::list::iterator it; - for(it = local_addrs.begin(); it != local_addrs.end(); ++it) - { - /* store into prefAddr */ - - sockaddr_storage localAddr; - sockaddr_storage_clear(localAddr); - struct sockaddr_in *addr = (sockaddr_in *) &localAddr; - addr->sin_family = AF_INET; - addr->sin_addr = *it; - addr->sin_port = htons(0); - addrs.push_back(localAddr); - } - return true; - } - return false; -} - - -/* This just might be portable!!! will see!!! - * Unfortunately this is usable on winXP+, determined by: (_WIN32_WINNT >= 0x0501) - * but not older platforms.... which must use gethostbyname. - * - * include it for now..... - */ - -bool LookupDNSAddr(std::string name, struct sockaddr_in &addr) -{ - -#if 1 - char service[100]; - struct addrinfo hints_st; - struct addrinfo *hints = &hints_st; - struct addrinfo *res; - - hints -> ai_flags = 0; // (cygwin don;t like these) AI_ADDRCONFIG | AI_NUMERICSERV; - hints -> ai_family = AF_INET; - hints -> ai_socktype = 0; - hints -> ai_protocol = 0; - hints -> ai_addrlen = 0; - hints -> ai_addr = NULL; - hints -> ai_canonname = NULL; - hints -> ai_next = NULL; - - /* get the port number */ - sprintf(service, "%d", ntohs(addr.sin_port)); - - /* set it to IPV4 */ -#ifdef NET_DEBUG - std::cerr << "LookupDNSAddr() name: " << name << " service: " << service << std::endl; -#endif - - int err = 0; - if (0 != (err = getaddrinfo(name.c_str(), service, hints, &res))) - { -#ifdef NET_DEBUG - std::cerr << "LookupDNSAddr() getaddrinfo failed!" << std::endl; - std::cerr << "Error: " << gai_strerror(err) << std::endl; -#endif - return false; - } - - if ((res) && (res->ai_family == AF_INET)) - { - addr = *((struct sockaddr_in *) res->ai_addr); - freeaddrinfo(res); - -#ifdef NET_DEBUG - std::cerr << "LookupDNSAddr() getaddrinfo found address" << std::endl; - std::cerr << "addr: " << rs_inet_ntoa(addr.sin_addr) << std::endl; - std::cerr << "port: " << ntohs(addr.sin_port) << std::endl; -#endif - return true; - } - -#ifdef NET_DEBUG - std::cerr << "getaddrinfo failed - no address" << std::endl; -#endif - -#endif -#ifdef NET_DEBUG - //std::cerr << "getaddrinfo disabled" << std::endl; -#endif - return false; -} - /************************************************************* * Socket Library Wrapper Functions * to get over the crapness of the windows. diff --git a/libretroshare/src/pqi/pqinetwork.h b/libretroshare/src/pqi/pqinetwork.h index 45ab305c1..e7adcc472 100644 --- a/libretroshare/src/pqi/pqinetwork.h +++ b/libretroshare/src/pqi/pqinetwork.h @@ -93,21 +93,11 @@ extern int errno; /* Define extern errno, to duplicate unix behaviour */ #include // Same def - different functions... - void showSocketError(std::string &out); std::string socket_errorType(int err); -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(const struct sockaddr_storage &existAddr, struct sockaddr_storage &prefAddr); // returns best addr. -bool getLocalInterfaces(struct sockaddr_storage &existAddr, std::list &addrs); // returns all possible addrs. - -in_addr_t pqi_inet_netof(struct in_addr addr); // our implementation. - -bool LookupDNSAddr(std::string name, struct sockaddr_in &addr); +bool getLocalAddresses(std::list & addrs); /* universal socket interface */ diff --git a/libretroshare/src/util/rsnet.h b/libretroshare/src/util/rsnet.h index d6ea0862c..4640fcafe 100644 --- a/libretroshare/src/util/rsnet.h +++ b/libretroshare/src/util/rsnet.h @@ -81,7 +81,7 @@ std::string rs_inet_ntoa(struct in_addr in); // Standard bind, on OSX anyway will not accept a longer socklen for IPv4. // so hidding details behind function. -int universal_bind(int fd, const struct sockaddr *addr, socklen_t socklen); +int universal_bind(int fd, const struct sockaddr *addr, socklen_t socklen); void sockaddr_storage_clear(struct sockaddr_storage &addr); diff --git a/libretroshare/src/util/rsnet_ss.cc b/libretroshare/src/util/rsnet_ss.cc index 763415f43..997558883 100644 --- a/libretroshare/src/util/rsnet_ss.cc +++ b/libretroshare/src/util/rsnet_ss.cc @@ -29,8 +29,6 @@ #include "util/rsstring.h" #include "pqi/pqinetwork.h" -#include "util/stacktrace.h" - /***************************** Internal Helper Fns ******************************/ /******************************** Casting **************************************/ @@ -158,8 +156,7 @@ bool sockaddr_storage_zeroip(struct sockaddr_storage &addr) bool sockaddr_storage_copyip(struct sockaddr_storage &dst, const struct sockaddr_storage &src) { #ifdef SS_DEBUG - std::cerr << "sockaddr_storage_copyip()"; - std::cerr << std::endl; + std::cerr << "sockaddr_storage_copyip()" << std::endl; #endif switch(src.ss_family) @@ -171,8 +168,9 @@ bool sockaddr_storage_copyip(struct sockaddr_storage &dst, const struct sockaddr return sockaddr_storage_ipv6_copyip(dst, src); break; default: - std::cerr << "sockaddr_storage_copyip() invalid addr.ss_family"; - std::cerr << std::endl; +#ifdef SS_DEBUG + std::cerr << "sockaddr_storage_copyip() Unknown ss_family: " << src.ss_family << std::endl; +#endif break; } return false; @@ -194,8 +192,7 @@ uint16_t sockaddr_storage_port(const struct sockaddr_storage &addr) return sockaddr_storage_ipv6_port(addr); break; default: - std::cerr << "sockaddr_storage_port() invalid addr.ss_family"; - std::cerr << std::endl; + std::cerr << "sockaddr_storage_port() invalid addr.ss_family" << std::endl; sockaddr_storage_dump(addr); break; } @@ -205,8 +202,7 @@ uint16_t sockaddr_storage_port(const struct sockaddr_storage &addr) bool sockaddr_storage_setport(struct sockaddr_storage &addr, uint16_t port) { #ifdef SS_DEBUG - std::cerr << "sockaddr_storage_setport()"; - std::cerr << std::endl; + std::cerr << "sockaddr_storage_setport()" << std::endl; #endif switch(addr.ss_family) @@ -218,8 +214,7 @@ bool sockaddr_storage_setport(struct sockaddr_storage &addr, uint16_t port) return sockaddr_storage_ipv6_setport(addr, port); break; default: - std::cerr << "sockaddr_storage_setport() invalid addr.ss_family"; - std::cerr << std::endl; + std::cerr << "sockaddr_storage_setport() invalid addr.ss_family" << std::endl; break; } return false; @@ -244,8 +239,7 @@ bool sockaddr_storage_setipv4(struct sockaddr_storage &addr, const sockaddr_in * bool sockaddr_storage_setipv6(struct sockaddr_storage &addr, const sockaddr_in6 *addr_ipv6) { - std::cerr << "sockaddr_storage_setipv6()"; - std::cerr << std::endl; + std::cerr << "sockaddr_storage_setipv6()" << std::endl; sockaddr_storage_clear(addr); struct sockaddr_in6 *ipv6_ptr = to_ipv6_ptr(addr); @@ -703,8 +697,7 @@ bool sockaddr_storage_ipv6_zeroip(struct sockaddr_storage &addr) bool sockaddr_storage_ipv6_copyip(struct sockaddr_storage &dst, const struct sockaddr_storage &src) { #ifdef SS_DEBUG - std::cerr << "sockaddr_storage_ipv6_copyip()"; - std::cerr << std::endl; + std::cerr << "sockaddr_storage_ipv6_copyip()" << std::endl; #endif struct sockaddr_in6 *dst_ptr = to_ipv6_ptr(dst); @@ -923,9 +916,6 @@ void sockaddr_storage_dump(const sockaddr_storage & addr) std::cerr << output.str() << std::endl; } - - - /********************************* Net Checks ***********************************/ bool sockaddr_storage_ipv4_isnull(const struct sockaddr_storage &addr) {