IBR-DTNSuite
0.8
|
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 }