posix/coil/Routing.cpp
Go to the documentation of this file.
1 // -*- C++ -*-
20 #include <stdio.h>
21 #include <netdb.h> // gethostbyname
22 #include <arpa/inet.h> // inet_ntoa
23 #include <netinet/in.h> // sockaddr_in
24 #include <sys/wait.h>
25 
26 #include <coil/Routing.h>
27 #include <coil/stringutil.h>
28 #include <coil/config_coil.h>
29 
30 namespace coil
31 {
39  bool dest_to_endpoint(std::string dest_addr, std::string& endpoint)
40  {
41  std::string dest_if;
42  if (!find_dest_ifname(dest_addr, dest_if))
43  {
44  return false;
45  }
46  return ifname_to_ipaddr(dest_if, endpoint);
47  }
48 
56  bool find_dest_ifname(std::string dest_addr, std::string& dest_if)
57  {
58  // This logic should be replaced by direct retrieving using
59  // routing interface like AFROUTE or sysctl.
60  struct ::hostent *hostent;
61  struct ::sockaddr_in addr;
62 
63  hostent = gethostbyname(dest_addr.c_str());
64  addr.sin_addr.s_addr = **(unsigned int **)(hostent->h_addr_list);
65  dest_addr = inet_ntoa(addr.sin_addr);
66 
67 #if defined(COIL_OS_FREEBSD) || defined(COIL_OS_DARWIN) || defined(COIL_OS_CYGWIN) || defined(COIL_OS_QNX)
68  std::string cmd("PATH=/bin:/sbin:/usr/bin:/usr/sbin "
69  "route get ");
70  const char* match_str = "interface";
71  const char* delimiter = ":";
72  size_t ifname_pos(1);
73  cmd += dest_addr;
74  cmd += " 2> /dev/null";
75 #endif // COIL_OS_IS_FREEBSD || COIL_OS_DARWIN || COIL_OS_CYGWIN || COIL_OS_QNX
76 #if defined(COIL_OS_LINUX)
77  std::string cmd("PATH=/bin:/sbin:/usr/bin:/usr/sbin "
78  "ip route get ");
79  const char* match_str = "dev ";
80  const char* delimiter = " ";
81  size_t ifname_pos(2);
82  cmd += dest_addr;
83  cmd += " 2> /dev/null";
84 #endif // COIL_OS_IS_LINUX
85 
86  FILE* fp;
87  if ((fp = popen(cmd.c_str(), "r")) == NULL)
88  {
89  return false;
90  }
91 
92  do
93  {
94  char str[512];
95  fgets(str, 512, fp);
96  std::string line(str);
97 
98  if (std::string::npos == line.find(match_str)) { continue; }
99 
100  line.erase(line.end() - 1);
101  coil::vstring vs(coil::split(line, delimiter));
102 
103 #if defined(COIL_OS_FREEBSD) || defined(COIL_OS_DARWIN) || defined(COIL_OS_CYGWIN) || defined(COIL_OS_QNX)
104  if (vs.size() > ifname_pos)
105  {
106  dest_if = vs[ifname_pos];
107  pclose(fp);
108  wait(NULL);
109  return true;
110  }
111 #endif // COIL_OS_FREEBSD || COIL_OS_DARWIN || COIL_OS_CYGWIN || COIL_OS_QNX
112 #if defined(COIL_OS_LINUX)
113  for (int i(0); i < vs.size(); ++i)
114  {
115  if (vs[i] == "dev")
116  {
117  dest_if = vs[i + 1];
118  pclose(fp);
119  return true;
120  }
121  }
122 #endif // COIL_OS_LINUX
123  } while (!feof(fp));
124  pclose(fp);
125  wait(NULL);
126  return false;
127  }
128 
136  bool ifname_to_ipaddr(std::string ifname, std::string& ipaddr)
137  {
138  std::string cmd("ifconfig ");
139  cmd += ifname;
140  cmd += " 2> /dev/null";
141 
142  FILE* fp;
143  if ((fp = popen(cmd.c_str(), "r")) == NULL)
144  {
145  return false;
146  }
147 
148  do
149  {
150  char str[512];
151  fgets(str, 512, fp);
152  std::string line(str);
153 
154  if (std::string::npos == line.find("inet ")) { continue; }
155 
156  line.erase(line.end() - 1);
157  coil::eraseHeadBlank(line);
158  coil::vstring vs(coil::split(line, " "));
159  if (vs.size() == 6)
160  {
161  ipaddr = vs[1];
162  pclose(fp);
163  wait(NULL);
164  return true;
165  }
166  } while (!feof(fp));
167  pclose(fp);
168  wait(NULL);
169  return false;
170  }
171 
172 }; // namespace coil
bool ifname_to_ipaddr(std::string ifname, std::string &ipaddr)
Get IP address from a network interface name.
void eraseHeadBlank(std::string &str)
Erase the head blank characters of string.
Definition: stringutil.cpp:267
vstring split(const std::string &input, const std::string &delimiter, bool ignore_empty)
Split string by delimiter.
Definition: stringutil.cpp:346
bool find_dest_ifname(std::string dest_addr, std::string &dest_if)
Getting network interface name from destination address.
std::vector< std::string > vstring
Definition: stringutil.h:37
list cmd
Definition: omniwxs.py:88
FILE * popen(const char *cmd, const char *mode)
void pclose(FILE *fd)
bool dest_to_endpoint(std::string dest_addr, std::string &endpoint)
Getting network interface name from destination address.
Common Object Interface Layer.


openrtm_aist
Author(s): Noriaki Ando
autogenerated on Mon Feb 28 2022 23:00:44