inlib
1.2.0
|
00001 // Copyright (C) 2010, Guy Barrand. All rights reserved. 00002 // See the file inlib.license for terms. 00003 00004 #ifndef inlib_net_addresses 00005 #define inlib_net_addresses 00006 00007 // the below works for Cocoa and iPhone. 00008 00009 #ifdef WIN32 00010 //FIXME : Windows : do the port. 00011 #else 00012 #include <sys/ioctl.h> 00013 #include <sys/socket.h> 00014 #include <arpa/inet.h> 00015 #include <net/if.h> 00016 #include <cstring> //strrchr,strncmp 00017 #include <errno.h> 00018 #include <unistd.h> //::close 00019 #endif 00020 00021 #include <string> 00022 #include <vector> 00023 #include <ostream> 00024 00025 namespace inlib { 00026 namespace net { 00027 00028 inline bool ip_addresses(std::ostream& a_out, 00029 std::vector<std::string>& a_if_names, 00030 std::vector<std::string>& a_ip_names, 00031 std::vector<unsigned long>& a_ip_addrs) { 00032 00033 a_if_names.clear(); 00034 a_ip_names.clear(); 00035 a_ip_addrs.clear(); 00036 00037 #ifdef WIN32 00038 a_out << "inlib::net::ip_addresses :" 00039 << " not yet ported on this platform." 00040 << std::endl; 00041 return false; 00042 #else 00043 int sockfd = ::socket(AF_INET, SOCK_DGRAM, 0); 00044 if (sockfd < 0) { 00045 a_out << "inlib::net::ip_addresses :" 00046 << " socket() : error : " << (int)errno 00047 << " : " << std::string(strerror(errno)) << "." 00048 << std::endl; 00049 return false; 00050 } 00051 00052 const int BUFFERSIZE = 4000; 00053 char buffer[BUFFERSIZE]; 00054 struct ifconf ifc; 00055 ifc.ifc_len = BUFFERSIZE; 00056 ifc.ifc_buf = buffer; 00057 00058 if (::ioctl(sockfd, SIOCGIFCONF, &ifc) < 0) { 00059 a_out << "inlib::net::ip_addresses :" 00060 << " ioctl() : error : " << (int)errno 00061 << " : " << std::string(strerror(errno)) << "." 00062 << std::endl; 00063 return false; 00064 } 00065 00066 char lastname[IFNAMSIZ]; 00067 lastname[0] = 0; 00068 00069 char* ptr; 00070 for (ptr = buffer; ptr < buffer + ifc.ifc_len; ) { 00071 struct ifreq* ifr = (struct ifreq*)ptr; 00072 00073 #if defined(__APPLE__) 00074 int len = sizeof(struct sockaddr) > ifr->ifr_addr.sa_len? 00075 sizeof(struct sockaddr) : ifr->ifr_addr.sa_len; 00076 #else 00077 int len = sizeof(struct sockaddr); 00078 #endif 00079 ptr += sizeof(ifr->ifr_name) + len; // for next one in buffer 00080 00081 if (ifr->ifr_addr.sa_family != AF_INET) { 00082 continue; // ignore if not desired address family 00083 } 00084 00085 char* cptr; 00086 if ((cptr = (char *)::strchr(ifr->ifr_name, ':')) != NULL) { 00087 *cptr = 0; // replace colon will null 00088 } 00089 00090 if (::strncmp(lastname, ifr->ifr_name, IFNAMSIZ) == 0) { 00091 continue; /* already processed this interface */ 00092 } 00093 00094 ::memcpy(lastname, ifr->ifr_name, IFNAMSIZ); 00095 00096 struct ifreq ifrcopy = *ifr; 00097 ::ioctl(sockfd, SIOCGIFFLAGS, &ifrcopy); 00098 int flags = ifrcopy.ifr_flags; 00099 if ((flags & IFF_UP) == 0) { 00100 continue; // ignore if interface not up 00101 } 00102 00103 a_if_names.push_back(ifr->ifr_name); 00104 00105 struct sockaddr_in* sin = (struct sockaddr_in*)&ifr->ifr_addr; 00106 00107 a_ip_names.push_back(inet_ntoa(sin->sin_addr)); 00108 a_ip_addrs.push_back(sin->sin_addr.s_addr); 00109 00110 } 00111 00112 ::close(sockfd); 00113 00114 /* 00115 {std::vector<std::string>::iterator it1 = a_if_names.begin(); 00116 std::vector<std::string>::iterator it2 = a_ip_names.begin(); 00117 std::vector<unsigned long>::iterator it3 = a_ip_addrs.begin(); 00118 for(;it1!=a_if_names.end();++it1,++it2,++it3) { 00119 a_out << "--------------------" << std::endl; 00120 a_out << "if name " << *it1 << std::endl; 00121 a_out << "ip name " << *it2 << std::endl; 00122 a_out << "ip addr " << (unsigned int)*it3 << std::endl; 00123 }} 00124 */ 00125 00126 return true; 00127 #endif 00128 } 00129 00130 inline bool if_address(std::ostream& a_out, 00131 const std::string& a_if, 00132 std::string& a_sa){ 00133 std::vector<std::string> if_names; 00134 std::vector<std::string> ip_names; 00135 std::vector<unsigned long> ip_addrs; 00136 if(!inlib::net::ip_addresses(a_out,if_names,ip_names,ip_addrs)) { 00137 a_sa.clear(); 00138 return false; 00139 } 00140 00141 // get interface address. for exa for a_if = "en0". 00142 std::vector<std::string>::iterator it1 = if_names.begin(); 00143 std::vector<std::string>::iterator it2 = ip_names.begin(); 00144 std::vector<unsigned long>::iterator it3 = ip_addrs.begin(); 00145 for(;it1!=if_names.end();++it1,++it2,++it3) { 00146 if((*it1)==a_if) { 00147 a_sa = *it2; 00148 return true; 00149 } 00150 } 00151 00152 a_out << "inlib::net::if_address :" 00153 << " interface \"" << a_if << "\"" 00154 << " not found." 00155 << std::endl; 00156 00157 a_sa.clear(); 00158 return false; //not found. 00159 } 00160 00161 inline bool dump_ip_addresses(std::ostream& a_out){ 00162 std::vector<std::string> if_names; 00163 std::vector<std::string> ip_names; 00164 std::vector<unsigned long> ip_addrs; 00165 if(!inlib::net::ip_addresses(a_out,if_names,ip_names,ip_addrs)) { 00166 return false; 00167 } 00168 00169 // get interface address. for exa for a_if = "en0". 00170 std::vector<std::string>::iterator it1 = if_names.begin(); 00171 std::vector<std::string>::iterator it2 = ip_names.begin(); 00172 std::vector<unsigned long>::iterator it3 = ip_addrs.begin(); 00173 for(;it1!=if_names.end();++it1,++it2,++it3) { 00174 a_out << "--------------------" << std::endl; 00175 a_out << "if name " << *it1 << std::endl; 00176 a_out << "ip name " << *it2 << std::endl; 00177 a_out << "ip addr " << (unsigned int)*it3 << std::endl; 00178 } 00179 00180 return true; 00181 } 00182 00183 }} 00184 00185 #endif