net_utils.cc
Go to the documentation of this file.
1 /*
2  * This file is part of the rc_dynamics_api package.
3  *
4  * Copyright (c) 2017 Roboception GmbH
5  * All rights reserved
6  *
7  * Author: Christian Emmerich
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions are met:
11  *
12  * 1. Redistributions of source code must retain the above copyright notice,
13  * this list of conditions and the following disclaimer.
14  *
15  * 2. Redistributions in binary form must reproduce the above copyright notice,
16  * this list of conditions and the following disclaimer in the documentation
17  * and/or other materials provided with the distribution.
18  *
19  * 3. Neither the name of the copyright holder nor the names of its contributors
20  * may be used to endorse or promote products derived from this software without
21  * specific prior written permission.
22  *
23  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
24  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
27  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
28  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
29  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
30  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
31  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
32  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33  * POSSIBILITY OF SUCH DAMAGE.
34  */
35 
36 #include "net_utils.h"
37 
38 #include <string.h>
39 
40 #ifdef WIN32
41 #include <winsock2.h>
42 #include <iphlpapi.h>
43 #include <mstcpip.h>
44 #pragma comment(lib, "IPHLPAPI.lib")
45 #pragma comment(lib, "ntdll.lib")
46 #else
47 #include <ifaddrs.h>
48 #include <arpa/inet.h>
49 #include <unistd.h>
50 #endif
51 
52 namespace rc
53 {
54 using namespace std;
55 
56 uint32_t ipToUInt(const std::string& ip)
57 {
58  int a, b, c, d;
59  uint32_t addr = 0;
60 
61  if (sscanf(ip.c_str(), "%d.%d.%d.%d", &a, &b, &c, &d) != 4)
62  {
63  return 0;
64  }
65 
66  addr = a << 24;
67  addr |= b << 16;
68  addr |= c << 8;
69  addr |= d;
70  return addr;
71 }
72 
73 bool isIPInRange(const std::string& ip, const std::string& network, const std::string& mask)
74 {
75  uint32_t ip_addr = ipToUInt(ip);
76  uint32_t network_addr = ipToUInt(network);
77  uint32_t mask_addr = ipToUInt(mask);
78 
79  uint32_t net_lower = (network_addr & mask_addr);
80  uint32_t net_upper = (net_lower | (~mask_addr));
81 
82  if (ip_addr >= net_lower && ip_addr <= net_upper)
83  {
84  return true;
85  }
86 
87  return false;
88 }
89 
90 #ifdef WIN32
91 
92 bool getThisHostsIP(string& this_hosts_ip, const string& other_hosts_ip, const string& network_interface)
93 {
94  this_hosts_ip = "";
95 
96  // convert string IP to integer representation
97 
98  DWORD dwOtherHostsIP = 0;
99  if (other_hosts_ip.size() > 0)
100  {
101  dwOtherHostsIP = htonl(ipToUInt(other_hosts_ip));
102  }
103 
104  // get index of network interface with given interface name
105 
106  DWORD ifindex = 0xffff;
107 
108  if (network_interface.size() > 0)
109  {
110  PIP_ADAPTER_ADDRESSES addr = 0;
111  ULONG addr_size = 0;
112 
113  for (int i = 0; i < 3; i++)
114  {
115  if (addr_size > 0)
116  {
117  addr = reinterpret_cast<PIP_ADAPTER_ADDRESSES>(malloc(addr_size));
118  }
119 
120  if (addr == 0)
121  {
122  addr_size = 0;
123  }
124 
125  ULONG ret = GetAdaptersAddresses(AF_INET, 0, 0, addr, &addr_size);
126 
127  if (ret == ERROR_SUCCESS)
128  {
129  break;
130  }
131 
132  free(addr);
133  addr = 0;
134  }
135 
136  PIP_ADAPTER_ADDRESSES p = addr;
137 
138  std::wstring wNetworkInterface(network_interface.begin(), network_interface.end());
139 
140  while (p != 0)
141  {
142  if (network_interface.compare(p->AdapterName) == 0 || wNetworkInterface.compare(p->FriendlyName) == 0)
143  {
144  ifindex = p->IfIndex;
145  break;
146  }
147 
148  p = p->Next;
149  }
150 
151  free(addr);
152 
153  if (ifindex == 0xffff)
154  {
155  return false;
156  }
157  }
158 
159  // get table with IPv4 to network interface mappings
160 
161  PMIB_IPADDRTABLE table = 0;
162  ULONG table_size = 0;
163 
164  for (int i = 0; i < 5; i++)
165  {
166  int result = GetIpAddrTable(table, &table_size, false);
167 
168  if (result == NO_ERROR)
169  {
170  break;
171  }
172  else if (result == ERROR_INSUFFICIENT_BUFFER)
173  {
174  free(table);
175  table = static_cast<PMIB_IPADDRTABLE>(malloc(table_size));
176  }
177  }
178 
179  if (table == 0)
180  {
181  return false;
182  }
183 
184  // got through table of mappings
185 
186  bool found_valid = false;
187  for (unsigned int i = 0; i < table->dwNumEntries; i++)
188  {
189  PMIB_IPADDRROW row = &table->table[i];
190 
191  // filter out loopback device
192 
193  if (row->dwAddr == htonl(INADDR_LOOPBACK))
194  {
195  continue;
196  }
197 
198  // if network interface name is given, then filter by this interface
199 
200  if (ifindex == 0xffff || ifindex == row->dwIndex)
201  {
202  // find network interface that can reach the specified other hosts IP
203 
204  if ((row->dwAddr & row->dwMask) == (dwOtherHostsIP & row->dwMask))
205  {
206  IN_ADDR addr;
207  char tmp[80];
208  addr.S_un.S_addr = row->dwAddr;
209  RtlIpv4AddressToStringA(&addr, tmp);
210  this_hosts_ip = string(tmp);
211 
212  found_valid = true;
213 
214  break;
215  }
216  }
217  }
218 
219  // free resources
220 
221  free(table);
222 
223  return found_valid;
224 }
225 
226 bool isValidIPAddress(const std::string& ip)
227 {
228  LPCTSTR tp = 0;
229  IN_ADDR addr;
230 
231  return RtlIpv4StringToAddressA(ip.c_str(), TRUE, &tp, &addr) == 0;
232 }
233 
234 #else
235 
236 bool getThisHostsIP(string& this_hosts_ip, const string& other_hosts_ip, const string& network_interface)
237 {
238  // scan all network interfaces (for the desired one)
239  struct ifaddrs* if_addr_struct = NULL;
240  struct ifaddrs* ifa = NULL;
241  void* tmp_addr_ptr = NULL;
242  getifaddrs(&if_addr_struct);
243  bool found_valid = false;
244  char address_buffer[INET_ADDRSTRLEN], netmask_buffer[INET_ADDRSTRLEN];
245  for (ifa = if_addr_struct; ifa != NULL; ifa = ifa->ifa_next)
246  {
247  // check if any valid IP4 address
248 
249  if (!ifa->ifa_addr || ifa->ifa_addr->sa_family != AF_INET)
250  continue;
251 
252  tmp_addr_ptr = &((struct sockaddr_in*)ifa->ifa_addr)->sin_addr;
253  inet_ntop(AF_INET, tmp_addr_ptr, address_buffer, INET_ADDRSTRLEN);
254 
255  // if network interface name is given, then filter by this interface
256 
257  if (network_interface.size() == 0 || strcmp(network_interface.c_str(), ifa->ifa_name) == 0)
258  {
259  // find network interface that can reach the specified other hosts IP
260 
261  tmp_addr_ptr = &((struct sockaddr_in*)ifa->ifa_netmask)->sin_addr;
262  inet_ntop(AF_INET, tmp_addr_ptr, netmask_buffer, INET_ADDRSTRLEN);
263  if (isIPInRange(address_buffer, other_hosts_ip, netmask_buffer))
264  {
265  found_valid = true;
266  break;
267  }
268  }
269  }
270 
271  if (found_valid)
272  {
273  this_hosts_ip = string(address_buffer);
274  }
275 
276  return found_valid;
277 }
278 
279 bool isValidIPAddress(const std::string& ip)
280 {
281  // use inet_pton to check if given string is a valid IP address
282  static struct sockaddr_in sa;
283  return TEMP_FAILURE_RETRY(inet_pton(AF_INET, ip.c_str(), &(sa.sin_addr))) == 1;
284 }
285 
286 #endif
287 }
bool getThisHostsIP(string &this_hosts_ip, const string &other_hosts_ip, const string &network_interface)
Definition: net_utils.cc:236
bool isValidIPAddress(const std::string &ip)
Checks if given string is a valid IP address.
Definition: net_utils.cc:279
uint32_t ipToUInt(const std::string &ip)
Converts a string-represented ip into uint (e.g.
Definition: net_utils.cc:56
bool isIPInRange(const std::string &ip, const std::string &network, const std::string &mask)
Checks if a given ip is in range of a network defined by ip/subnet taken from: https://www.stev.org/post/ccheckanipaddressisinaipmask.
Definition: net_utils.cc:73


rc_dynamics_api
Author(s): Heiko Hirschmueller , Christian Emmerich , Felix Endres
autogenerated on Sat Mar 6 2021 03:53:19