inlib  1.2.0
/Users/barrand/private/dev/softinex/old/inexlib-1.2/inlib/inlib/net/addresses
Go to the documentation of this file.
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
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines