net_utils.cc
Go to the documentation of this file.
00001 /*
00002  * This file is part of the rc_dynamics_api package.
00003  *
00004  * Copyright (c) 2017 Roboception GmbH
00005  * All rights reserved
00006  *
00007  * Author: Christian Emmerich
00008  *
00009  * Redistribution and use in source and binary forms, with or without
00010  * modification, are permitted provided that the following conditions are met:
00011  *
00012  * 1. Redistributions of source code must retain the above copyright notice,
00013  * this list of conditions and the following disclaimer.
00014  *
00015  * 2. Redistributions in binary form must reproduce the above copyright notice,
00016  * this list of conditions and the following disclaimer in the documentation
00017  * and/or other materials provided with the distribution.
00018  *
00019  * 3. Neither the name of the copyright holder nor the names of its contributors
00020  * may be used to endorse or promote products derived from this software without
00021  * specific prior written permission.
00022  *
00023  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00024  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00025  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00026  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
00027  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
00028  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
00029  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00030  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
00031  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00032  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00033  * POSSIBILITY OF SUCH DAMAGE.
00034  */
00035 
00036 #include "net_utils.h"
00037 
00038 #include <string.h>
00039 
00040 #ifdef WIN32
00041 #include <winsock2.h>
00042 #include <iphlpapi.h>
00043 #include <mstcpip.h>
00044 #pragma comment(lib, "IPHLPAPI.lib")
00045 #pragma comment(lib, "ntdll.lib")
00046 #else
00047 #include <ifaddrs.h>
00048 #include <arpa/inet.h>
00049 #include <unistd.h>
00050 #endif
00051 
00052 namespace rc
00053 {
00054 using namespace std;
00055 
00056 uint32_t ipToUInt(const std::string& ip)
00057 {
00058   int a, b, c, d;
00059   uint32_t addr = 0;
00060 
00061   if (sscanf(ip.c_str(), "%d.%d.%d.%d", &a, &b, &c, &d) != 4)
00062   {
00063     return 0;
00064   }
00065 
00066   addr = a << 24;
00067   addr |= b << 16;
00068   addr |= c << 8;
00069   addr |= d;
00070   return addr;
00071 }
00072 
00073 bool isIPInRange(const std::string& ip, const std::string& network, const std::string& mask)
00074 {
00075   uint32_t ip_addr = ipToUInt(ip);
00076   uint32_t network_addr = ipToUInt(network);
00077   uint32_t mask_addr = ipToUInt(mask);
00078 
00079   uint32_t net_lower = (network_addr & mask_addr);
00080   uint32_t net_upper = (net_lower | (~mask_addr));
00081 
00082   if (ip_addr >= net_lower && ip_addr <= net_upper)
00083   {
00084     return true;
00085   }
00086 
00087   return false;
00088 }
00089 
00090 #ifdef WIN32
00091 
00092 bool getThisHostsIP(string& this_hosts_ip, const string& other_hosts_ip, const string& network_interface)
00093 {
00094   this_hosts_ip = "";
00095 
00096   // convert string IP to integer representation
00097 
00098   DWORD dwOtherHostsIP = 0;
00099   if (other_hosts_ip.size() > 0)
00100   {
00101     dwOtherHostsIP = htonl(ipToUInt(other_hosts_ip));
00102   }
00103 
00104   // get index of network interface with given interface name
00105 
00106   DWORD ifindex = 0xffff;
00107 
00108   if (network_interface.size() > 0)
00109   {
00110     PIP_ADAPTER_ADDRESSES addr = 0;
00111     ULONG addr_size = 0;
00112 
00113     for (int i = 0; i < 3; i++)
00114     {
00115       if (addr_size > 0)
00116       {
00117         addr = reinterpret_cast<PIP_ADAPTER_ADDRESSES>(malloc(addr_size));
00118       }
00119 
00120       if (addr == 0)
00121       {
00122         addr_size = 0;
00123       }
00124 
00125       ULONG ret = GetAdaptersAddresses(AF_INET, 0, 0, addr, &addr_size);
00126 
00127       if (ret == ERROR_SUCCESS)
00128       {
00129         break;
00130       }
00131 
00132       free(addr);
00133       addr = 0;
00134     }
00135 
00136     PIP_ADAPTER_ADDRESSES p = addr;
00137 
00138     std::wstring wNetworkInterface(network_interface.begin(), network_interface.end());
00139 
00140     while (p != 0)
00141     {
00142       if (network_interface.compare(p->AdapterName) == 0 || wNetworkInterface.compare(p->FriendlyName) == 0)
00143       {
00144         ifindex = p->IfIndex;
00145         break;
00146       }
00147 
00148       p = p->Next;
00149     }
00150 
00151     free(addr);
00152 
00153     if (ifindex == 0xffff)
00154     {
00155       return false;
00156     }
00157   }
00158 
00159   // get table with IPv4 to network interface mappings
00160 
00161   PMIB_IPADDRTABLE table = 0;
00162   ULONG table_size = 0;
00163 
00164   for (int i = 0; i < 5; i++)
00165   {
00166     int result = GetIpAddrTable(table, &table_size, false);
00167 
00168     if (result == NO_ERROR)
00169     {
00170       break;
00171     }
00172     else if (result == ERROR_INSUFFICIENT_BUFFER)
00173     {
00174       free(table);
00175       table = static_cast<PMIB_IPADDRTABLE>(malloc(table_size));
00176     }
00177   }
00178 
00179   if (table == 0)
00180   {
00181     return false;
00182   }
00183 
00184   // got through table of mappings
00185 
00186   bool found_valid = false;
00187   for (unsigned int i = 0; i < table->dwNumEntries; i++)
00188   {
00189     PMIB_IPADDRROW row = &table->table[i];
00190 
00191     // filter out loopback device
00192 
00193     if (row->dwAddr == htonl(INADDR_LOOPBACK))
00194     {
00195       continue;
00196     }
00197 
00198     // if network interface name is given, then filter by this interface
00199 
00200     if (ifindex == 0xffff || ifindex == row->dwIndex)
00201     {
00202       // find network interface that can reach the specified other hosts IP
00203 
00204       if ((row->dwAddr & row->dwMask) == (dwOtherHostsIP & row->dwMask))
00205       {
00206         IN_ADDR addr;
00207         char tmp[80];
00208         addr.S_un.S_addr = row->dwAddr;
00209         RtlIpv4AddressToStringA(&addr, tmp);
00210         this_hosts_ip = string(tmp);
00211 
00212         found_valid = true;
00213 
00214         break;
00215       }
00216     }
00217   }
00218 
00219   // free resources
00220 
00221   free(table);
00222 
00223   return found_valid;
00224 }
00225 
00226 bool isValidIPAddress(const std::string& ip)
00227 {
00228   LPCTSTR tp = 0;
00229   IN_ADDR addr;
00230 
00231   return RtlIpv4StringToAddressA(ip.c_str(), TRUE, &tp, &addr) == 0;
00232 }
00233 
00234 #else
00235 
00236 bool getThisHostsIP(string& this_hosts_ip, const string& other_hosts_ip, const string& network_interface)
00237 {
00238   // scan all network interfaces (for the desired one)
00239   struct ifaddrs* if_addr_struct = NULL;
00240   struct ifaddrs* ifa = NULL;
00241   void* tmp_addr_ptr = NULL;
00242   getifaddrs(&if_addr_struct);
00243   bool found_valid = false;
00244   char address_buffer[INET_ADDRSTRLEN], netmask_buffer[INET_ADDRSTRLEN];
00245   for (ifa = if_addr_struct; ifa != NULL; ifa = ifa->ifa_next)
00246   {
00247     // check if any valid IP4 address
00248 
00249     if (!ifa->ifa_addr || ifa->ifa_addr->sa_family != AF_INET)
00250       continue;
00251 
00252     tmp_addr_ptr = &((struct sockaddr_in*)ifa->ifa_addr)->sin_addr;
00253     inet_ntop(AF_INET, tmp_addr_ptr, address_buffer, INET_ADDRSTRLEN);
00254 
00255     // if network interface name is given, then filter by this interface
00256 
00257     if (network_interface.size() == 0 || strcmp(network_interface.c_str(), ifa->ifa_name) == 0)
00258     {
00259       // find network interface that can reach the specified other hosts IP
00260 
00261       tmp_addr_ptr = &((struct sockaddr_in*)ifa->ifa_netmask)->sin_addr;
00262       inet_ntop(AF_INET, tmp_addr_ptr, netmask_buffer, INET_ADDRSTRLEN);
00263       if (isIPInRange(address_buffer, other_hosts_ip, netmask_buffer))
00264       {
00265         found_valid = true;
00266         break;
00267       }
00268     }
00269   }
00270 
00271   if (found_valid)
00272   {
00273     this_hosts_ip = string(address_buffer);
00274   }
00275 
00276   return found_valid;
00277 }
00278 
00279 bool isValidIPAddress(const std::string& ip)
00280 {
00281   // use inet_pton to check if given string is a valid IP address
00282   static struct sockaddr_in sa;
00283   return TEMP_FAILURE_RETRY(inet_pton(AF_INET, ip.c_str(), &(sa.sin_addr))) == 1;
00284 }
00285 
00286 #endif
00287 }


rc_dynamics_api
Author(s): Heiko Hirschmueller , Christian Emmerich , Felix Endres
autogenerated on Thu May 9 2019 02:13:50