Routing.cpp
Go to the documentation of this file.
00001 // -*- C++ -*-
00020 #include <stdio.h>
00021 #include <netdb.h>      // gethostbyname
00022 #include <arpa/inet.h>  // inet_ntoa
00023 #include <netinet/in.h> // sockaddr_in
00024 #include <sys/wait.h>
00025 
00026 #include <coil/Routing.h>
00027 #include <coil/stringutil.h>
00028 #include <coil/config_coil.h>
00029 
00030 namespace coil
00031 {
00039   bool dest_to_endpoint(std::string dest_addr, std::string& endpoint)
00040   {
00041     std::string dest_if;
00042     if (!find_dest_ifname(dest_addr, dest_if))
00043       {
00044         return false;
00045       }
00046     return ifname_to_ipaddr(dest_if, endpoint);
00047   }
00048 
00056   bool find_dest_ifname(std::string dest_addr, std::string& dest_if)
00057   {
00058     // This logic should be replaced by direct retrieving using
00059     // routing interface like AFROUTE or sysctl.
00060     struct ::hostent *hostent;
00061     struct ::sockaddr_in addr;
00062     
00063     hostent = gethostbyname(dest_addr.c_str());
00064     addr.sin_addr.s_addr = **(unsigned int **)(hostent->h_addr_list);
00065     dest_addr = inet_ntoa(addr.sin_addr);
00066     
00067 #if defined(COIL_OS_FREEBSD) || defined(COIL_OS_DARWIN) || defined(COIL_OS_CYGWIN)
00068     std::string cmd("PATH=/bin:/sbin:/usr/bin:/usr/sbin "
00069                     "route get ");
00070     const char* match_str = "interface";
00071     const char* delimiter = ":";
00072     size_t ifname_pos(1);
00073     cmd += dest_addr;
00074     cmd += " 2> /dev/null";
00075 #endif // COIL_OS_IS_FREEBSD || COIL_OS_DARWIN || COIL_OS_CYGWIN
00076 #if defined(COIL_OS_LINUX)
00077     std::string cmd("PATH=/bin:/sbin:/usr/bin:/usr/sbin "
00078                     "ip route get ");
00079     const char* match_str = "dev ";
00080     const char* delimiter = " ";
00081     size_t ifname_pos(2);
00082     cmd += dest_addr;
00083     cmd += " 2> /dev/null";
00084 #endif // COIL_OS_IS_LINUX    
00085     
00086     FILE* fp;
00087     if ((fp = popen(cmd.c_str(), "r")) == NULL)
00088       {
00089         return false;
00090       }
00091 
00092     do
00093       {
00094         char str[512];
00095         fgets(str, 512, fp);
00096         std::string line(str);
00097         
00098         if (std::string::npos == line.find(match_str)) { continue; }
00099         
00100         line.erase(line.end() - 1);
00101         coil::vstring vs(coil::split(line, delimiter));
00102 
00103 #if defined(COIL_OS_FREEBSD) || defined(COIL_OS_DARWIN) || defined(COIL_OS_CYGWIN)
00104         if (vs.size() > ifname_pos)
00105           {
00106             dest_if = vs[ifname_pos];
00107             pclose(fp);
00108             wait(NULL);
00109             return true;
00110           }
00111 #endif // COIL_OS_FREEBSD || COIL_OS_DARWIN || COIL_OS_CYGWIN
00112 #if defined(COIL_OS_LINUX)
00113         for (int i(0); i < vs.size(); ++i)
00114           {
00115             if (vs[i] == "dev")
00116               {
00117                 dest_if = vs[i + 1];
00118                 return true;
00119               }
00120           }
00121 #endif // COIL_OS_LINUX
00122       } while (!feof(fp));
00123     pclose(fp);
00124     wait(NULL);
00125     return false;
00126   }
00127 
00135   bool ifname_to_ipaddr(std::string ifname, std::string& ipaddr)
00136   {
00137     std::string cmd("ifconfig ");
00138     cmd += ifname;
00139     cmd += " 2> /dev/null";
00140     
00141     FILE* fp;
00142     if ((fp = popen(cmd.c_str(), "r")) == NULL)
00143       {
00144         return false;
00145       }
00146     
00147     do
00148       {
00149         char str[512];
00150         fgets(str, 512, fp);
00151         std::string line(str);
00152         
00153         if (std::string::npos == line.find("inet ")) { continue; }
00154         
00155         line.erase(line.end() - 1);
00156         coil::eraseHeadBlank(line);
00157         coil::vstring vs(coil::split(line, " "));
00158         if (vs.size() == 6)
00159           {
00160             ipaddr = vs[1];
00161             pclose(fp);
00162             wait(NULL);
00163             return true;
00164           }
00165       } while (!feof(fp));
00166     pclose(fp);
00167     wait(NULL);
00168     return false;
00169   }
00170   
00171 }; // namespace coil


openrtm_aist
Author(s): Noriaki Ando
autogenerated on Thu Aug 27 2015 14:16:38