IBR-DTNSuite  0.8
ibrcommon/ibrcommon/net/vaddress.cpp
Go to the documentation of this file.
00001 /*
00002  * vaddress.cpp
00003  *
00004  *  Created on: 14.12.2010
00005  *      Author: morgenro
00006  */
00007 
00008 #include "ibrcommon/config.h"
00009 #include "ibrcommon/net/vaddress.h"
00010 #include "ibrcommon/net/vsocket.h"
00011 #include "ibrcommon/net/LinkManager.h"
00012 #include <arpa/inet.h>
00013 #include <string.h>
00014 #include <sstream>
00015 #include <regex.h>
00016 
00017 #ifndef HAVE_BZERO
00018 #define bzero(s,n) (memset((s), '\0', (n)), (void) 0)
00019 #endif
00020 
00021 namespace ibrcommon
00022 {
00023         const std::string vaddress::__REGEX_IPV4_ADDRESS__ = "^[[:digit:]]\\{1,3\\}.[[:digit:]]\\{1,3\\}.[[:digit:]]\\{1,3\\}.[[:digit:]]\\{1,3\\}$";
00024         const std::string vaddress::__REGEX_IPV6_ADDRESS__ = "^[[:alnum:]:]\\{3,40\\}\\(%[[:alnum:]]*\\)\\{0,1\\}$";
00025 
00026 
00027         vaddress::vaddress(const Family &family)
00028          : _family(family), _address(), _broadcast(false), _iface(0)
00029         {
00030         }
00031 
00032         vaddress::vaddress(const std::string &address)
00033          : _family(VADDRESS_UNSPEC), _address(address), _broadcast(false), _iface(0)
00034         {
00035                 // guess the address family
00036                 regex_t re;
00037 
00038                 // test for ipv4 addresses
00039                 if ( regcomp(&re, __REGEX_IPV4_ADDRESS__.c_str(), 0) )
00040                 {
00041                         // failed
00042                         return;
00043                 }
00044 
00045                 // test against the regular expression
00046                 if (!regexec(&re, address.c_str(), 0, NULL, 0))
00047                 {
00048                         _family = VADDRESS_INET;
00049                         regfree(&re);
00050                         return;
00051                 }
00052 
00053                 regfree(&re);
00054 
00055                 // test for ipv6 addresses
00056                 if ( regcomp(&re, __REGEX_IPV6_ADDRESS__.c_str(), 0) )
00057                 {
00058                         // failed
00059                         return;
00060                 }
00061 
00062                 // test against the regular expression
00063                 if (!regexec(&re, address.c_str(), 0, NULL, 0))
00064                 {
00065                         _family = VADDRESS_INET6;
00066                         regfree(&re);
00067                         return;
00068                 }
00069 
00070                 regfree(&re);
00071 
00072                 // test for unix file
00073                 ibrcommon::File f(address);
00074                 if (f.exists())
00075                 {
00076                         _family = VADDRESS_UNIX;
00077                 }
00078         }
00079 
00080         vaddress::vaddress(const Family &family, const std::string &address, const int iface, const bool broadcast)
00081          : _family(family), _address(address), _broadcast(broadcast), _iface(iface)
00082         {
00083         }
00084 
00085         vaddress::vaddress(const Family &family, const std::string &address, const bool broadcast)
00086          : _family(family), _address(address), _broadcast(broadcast), _iface(0)
00087         {
00088         }
00089 
00090         vaddress::~vaddress()
00091         {
00092         }
00093 
00094         // strip off network mask
00095         const std::string vaddress::strip_netmask(const std::string &data)
00096         {
00097                 // search the last slash
00098                 size_t pos = data.find_last_of("/");
00099                 if (pos == std::string::npos) return data;
00100 
00101                 return data.substr(0, pos);
00102         }
00103 
00104         vaddress::Family vaddress::getFamily() const
00105         {
00106                 return _family;
00107         }
00108 
00109         const std::string vaddress::get(bool internal) const
00110         {
00111                 if (_address.length() == 0) throw address_not_set();
00112                 std::string ret = _address;
00113 
00114                 // strip netmask number
00115                 size_t slashpos = _address.find("/");
00116                 if (slashpos != string::npos)
00117                 {
00118                         ret = _address.substr(0, slashpos);
00119                 }
00120 
00121                 if ((_iface > 0) && (internal))
00122                 {
00123                         stringstream ss; ss << ret << "%" << ibrcommon::LinkManager::getInstance().getInterface(_iface);
00124                         ret = ss.str();
00125                 }
00126 
00127                 return ret;
00128         }
00129 
00130         bool vaddress::operator!=(const vaddress &obj) const
00131         {
00132                 if (_family != obj._family) return true;
00133                 if (_address != obj._address) return true;
00134                 return false;
00135         }
00136         
00137         bool vaddress::operator==(const vaddress &obj) const
00138         {
00139                 if (_family != obj._family) return false;
00140                 if (_address != obj._address) return false;
00141                 return true;
00142         }
00143 
00144         bool vaddress::isBroadcast() const
00145         {
00146                 return _broadcast;
00147         }
00148 
00149         struct addrinfo* vaddress::addrinfo(struct addrinfo *hints) const
00150         {
00151                 struct addrinfo *res;
00152 
00153                 if (_family != VADDRESS_UNSPEC)
00154                 {
00155                         hints->ai_family = _family;
00156                 }
00157 
00158                 if (0 != getaddrinfo(get().c_str(), NULL, hints, &res))
00159                         throw vsocket_exception("failed to getaddrinfo with address: " + get());
00160 
00161                 return res;
00162         }
00163 
00164         struct addrinfo* vaddress::addrinfo(struct addrinfo *hints, unsigned int port) const
00165         {
00166                 struct addrinfo *res;
00167 
00168                 if (_family != VADDRESS_UNSPEC)
00169                 {
00170                         hints->ai_family = _family;
00171                 }
00172 
00173                 std::stringstream port_ss; port_ss << port;
00174                 try {
00175                         if (0 != getaddrinfo(get().c_str(), port_ss.str().c_str(), hints, &res))
00176                                 throw vsocket_exception("failed to getaddrinfo with address: " + get());
00177                 }
00178                 catch (const vaddress::address_not_set&)
00179                 {
00180                         if (0 != getaddrinfo(NULL, port_ss.str().c_str(), hints, &res))
00181                                 throw vsocket_exception("failed to getaddrinfo");
00182                 }
00183 
00184                 return res;
00185         }
00186 
00187         bool vaddress::isMulticast() const
00188         {
00189                 try {
00190                         struct sockaddr_in destination;
00191                         bzero(&destination, sizeof(destination));
00192 
00193                         // convert given address
00194                         if (inet_pton(AF_INET, get().c_str(), &destination.sin_addr) <= 0)
00195                         {
00196                                         throw address_not_set("can not parse address");
00197                         }
00198 
00199                         // check if address is in a multicast range
00200                         uint32_t haddr = ntohl((uint32_t&)destination.sin_addr);
00201 
00202                         return (IN_MULTICAST(haddr));
00203                 } catch (const address_not_set&) {
00204                         return false;
00205                 }
00206         }
00207 
00208         const std::string vaddress::toString() const
00209         {
00210                 if (_address.length() == 0) return "<any>";
00211 
00212                 if (_iface > 0)
00213                 {
00214                         stringstream ss; ss << _address << "%" << ibrcommon::LinkManager::getInstance().getInterface(_iface);
00215                         return ss.str();
00216                 }
00217 
00218                 return _address;
00219         }
00220 }