1 /* 2 * libjingle 3 * Copyright 2004--2005, Google Inc. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are met: 7 * 8 * 1. Redistributions of source code must retain the above copyright notice, 9 * this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright notice, 11 * this list of conditions and the following disclaimer in the documentation 12 * and/or other materials provided with the distribution. 13 * 3. The name of the author may not be used to endorse or promote products 14 * derived from this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 18 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 19 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 20 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 22 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 23 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 24 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 25 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 */ 27 28 #include "talk/base/socketaddress.h" 29 30 #ifdef POSIX 31 #include <sys/types.h> 32 #include <sys/socket.h> 33 #include <netinet/in.h> 34 #if defined(OPENBSD) 35 #include <netinet/in_systm.h> 36 #endif 37 #include <netinet/ip.h> 38 #include <arpa/inet.h> 39 #include <netdb.h> 40 #include <unistd.h> 41 #endif 42 43 #include <sstream> 44 45 #include "talk/base/byteorder.h" 46 #include "talk/base/common.h" 47 #include "talk/base/logging.h" 48 #include "talk/base/nethelpers.h" 49 50 #ifdef WIN32 51 #include "talk/base/win32.h" 52 #endif 53 54 namespace talk_base { 55 56 SocketAddress::SocketAddress() { 57 Clear(); 58 } 59 60 SocketAddress::SocketAddress(const std::string& hostname, int port) { 61 SetIP(hostname); 62 SetPort(port); 63 } 64 65 SocketAddress::SocketAddress(uint32 ip_as_host_order_integer, int port) { 66 SetIP(IPAddress(ip_as_host_order_integer)); 67 SetPort(port); 68 } 69 70 SocketAddress::SocketAddress(const IPAddress& ip, int port) { 71 SetIP(ip); 72 SetPort(port); 73 } 74 75 SocketAddress::SocketAddress(const SocketAddress& addr) { 76 this->operator=(addr); 77 } 78 79 void SocketAddress::Clear() { 80 hostname_.clear(); 81 literal_ = false; 82 ip_ = IPAddress(); 83 port_ = 0; 84 scope_id_ = 0; 85 } 86 87 bool SocketAddress::IsNil() const { 88 return hostname_.empty() && IPIsUnspec(ip_) && 0 == port_; 89 } 90 91 bool SocketAddress::IsComplete() const { 92 return (!IPIsAny(ip_)) && (0 != port_); 93 } 94 95 SocketAddress& SocketAddress::operator=(const SocketAddress& addr) { 96 hostname_ = addr.hostname_; 97 ip_ = addr.ip_; 98 port_ = addr.port_; 99 literal_ = addr.literal_; 100 scope_id_ = addr.scope_id_; 101 return *this; 102 } 103 104 void SocketAddress::SetIP(uint32 ip_as_host_order_integer) { 105 hostname_.clear(); 106 literal_ = false; 107 ip_ = IPAddress(ip_as_host_order_integer); 108 scope_id_ = 0; 109 } 110 111 void SocketAddress::SetIP(const IPAddress& ip) { 112 hostname_.clear(); 113 literal_ = false; 114 ip_ = ip; 115 scope_id_ = 0; 116 } 117 118 void SocketAddress::SetIP(const std::string& hostname) { 119 hostname_ = hostname; 120 literal_ = IPFromString(hostname, &ip_); 121 if (!literal_) { 122 ip_ = IPAddress(); 123 } 124 scope_id_ = 0; 125 } 126 127 void SocketAddress::SetResolvedIP(uint32 ip_as_host_order_integer) { 128 ip_ = IPAddress(ip_as_host_order_integer); 129 scope_id_ = 0; 130 } 131 132 void SocketAddress::SetResolvedIP(const IPAddress& ip) { 133 ip_ = ip; 134 scope_id_ = 0; 135 } 136 137 void SocketAddress::SetPort(int port) { 138 ASSERT((0 <= port) && (port < 65536)); 139 port_ = port; 140 } 141 142 uint32 SocketAddress::ip() const { 143 return ip_.v4AddressAsHostOrderInteger(); 144 } 145 146 const IPAddress& SocketAddress::ipaddr() const { 147 return ip_; 148 } 149 150 uint16 SocketAddress::port() const { 151 return port_; 152 } 153 154 std::string SocketAddress::HostAsURIString() const { 155 // If the hostname was a literal IP string, it may need to have square 156 // brackets added (for SocketAddress::ToString()). 157 if (!literal_ && !hostname_.empty()) 158 return hostname_; 159 if (ip_.family() == AF_INET6) { 160 return "[" + ip_.ToString() + "]"; 161 } else { 162 return ip_.ToString(); 163 } 164 } 165 166 std::string SocketAddress::HostAsSensitiveURIString() const { 167 // If the hostname was a literal IP string, it may need to have square 168 // brackets added (for SocketAddress::ToString()). 169 if (!literal_ && !hostname_.empty()) 170 return hostname_; 171 if (ip_.family() == AF_INET6) { 172 return "[" + ip_.ToSensitiveString() + "]"; 173 } else { 174 return ip_.ToSensitiveString(); 175 } 176 } 177 178 std::string SocketAddress::PortAsString() const { 179 std::ostringstream ost; 180 ost << port_; 181 return ost.str(); 182 } 183 184 std::string SocketAddress::ToString() const { 185 std::ostringstream ost; 186 ost << *this; 187 return ost.str(); 188 } 189 190 std::string SocketAddress::ToSensitiveString() const { 191 std::ostringstream ost; 192 ost << HostAsSensitiveURIString() << ":" << port(); 193 return ost.str(); 194 } 195 196 bool SocketAddress::FromString(const std::string& str) { 197 if (str.at(0) == '[') { 198 std::string::size_type closebracket = str.rfind(']'); 199 if (closebracket != std::string::npos) { 200 std::string::size_type colon = str.find(':', closebracket); 201 if (colon != std::string::npos && colon > closebracket) { 202 SetPort(strtoul(str.substr(colon + 1).c_str(), NULL, 10)); 203 SetIP(str.substr(1, closebracket - 1)); 204 } else { 205 return false; 206 } 207 } 208 } else { 209 std::string::size_type pos = str.find(':'); 210 if (std::string::npos == pos) 211 return false; 212 SetPort(strtoul(str.substr(pos + 1).c_str(), NULL, 10)); 213 SetIP(str.substr(0, pos)); 214 } 215 return true; 216 } 217 218 std::ostream& operator<<(std::ostream& os, const SocketAddress& addr) { 219 os << addr.HostAsURIString() << ":" << addr.port(); 220 return os; 221 } 222 223 bool SocketAddress::IsAnyIP() const { 224 return IPIsAny(ip_); 225 } 226 227 bool SocketAddress::IsLoopbackIP() const { 228 return IPIsLoopback(ip_) || (IPIsAny(ip_) && 229 0 == strcmp(hostname_.c_str(), "localhost")); 230 } 231 232 bool SocketAddress::IsPrivateIP() const { 233 return IPIsPrivate(ip_); 234 } 235 236 bool SocketAddress::IsUnresolvedIP() const { 237 return IPIsUnspec(ip_) && !literal_ && !hostname_.empty(); 238 } 239 240 bool SocketAddress::operator==(const SocketAddress& addr) const { 241 return EqualIPs(addr) && EqualPorts(addr); 242 } 243 244 bool SocketAddress::operator<(const SocketAddress& addr) const { 245 if (ip_ < addr.ip_) 246 return true; 247 else if (addr.ip_ < ip_) 248 return false; 249 250 // We only check hostnames if both IPs are zero. This matches EqualIPs() 251 if (addr.IsAnyIP()) { 252 if (hostname_ < addr.hostname_) 253 return true; 254 else if (addr.hostname_ < hostname_) 255 return false; 256 } 257 258 return port_ < addr.port_; 259 } 260 261 bool SocketAddress::EqualIPs(const SocketAddress& addr) const { 262 return (ip_ == addr.ip_) && 263 ((!IPIsAny(ip_)) || (hostname_ == addr.hostname_)); 264 } 265 266 bool SocketAddress::EqualPorts(const SocketAddress& addr) const { 267 return (port_ == addr.port_); 268 } 269 270 size_t SocketAddress::Hash() const { 271 size_t h = 0; 272 h ^= HashIP(ip_); 273 h ^= port_ | (port_ << 16); 274 return h; 275 } 276 277 void SocketAddress::ToSockAddr(sockaddr_in* saddr) const { 278 memset(saddr, 0, sizeof(*saddr)); 279 if (ip_.family() != AF_INET) { 280 saddr->sin_family = AF_UNSPEC; 281 return; 282 } 283 saddr->sin_family = AF_INET; 284 saddr->sin_port = HostToNetwork16(port_); 285 if (IPIsAny(ip_)) { 286 saddr->sin_addr.s_addr = INADDR_ANY; 287 } else { 288 saddr->sin_addr = ip_.ipv4_address(); 289 } 290 } 291 292 bool SocketAddress::FromSockAddr(const sockaddr_in& saddr) { 293 if (saddr.sin_family != AF_INET) 294 return false; 295 SetIP(NetworkToHost32(saddr.sin_addr.s_addr)); 296 SetPort(NetworkToHost16(saddr.sin_port)); 297 literal_ = false; 298 return true; 299 } 300 301 static size_t ToSockAddrStorageHelper(sockaddr_storage* addr, 302 IPAddress ip, int port, int scope_id) { 303 memset(addr, 0, sizeof(sockaddr_storage)); 304 addr->ss_family = ip.family(); 305 if (addr->ss_family == AF_INET6) { 306 sockaddr_in6* saddr = reinterpret_cast<sockaddr_in6*>(addr); 307 saddr->sin6_addr = ip.ipv6_address(); 308 saddr->sin6_port = HostToNetwork16(port); 309 saddr->sin6_scope_id = scope_id; 310 return sizeof(sockaddr_in6); 311 } else if (addr->ss_family == AF_INET) { 312 sockaddr_in* saddr = reinterpret_cast<sockaddr_in*>(addr); 313 saddr->sin_addr = ip.ipv4_address(); 314 saddr->sin_port = HostToNetwork16(port); 315 return sizeof(sockaddr_in); 316 } 317 return 0; 318 } 319 320 size_t SocketAddress::ToDualStackSockAddrStorage(sockaddr_storage *addr) const { 321 return ToSockAddrStorageHelper(addr, ip_.AsIPv6Address(), port_, scope_id_); 322 } 323 324 size_t SocketAddress::ToSockAddrStorage(sockaddr_storage* addr) const { 325 return ToSockAddrStorageHelper(addr, ip_, port_, scope_id_); 326 } 327 328 std::string SocketAddress::IPToString(uint32 ip_as_host_order_integer) { 329 return IPAddress(ip_as_host_order_integer).ToString(); 330 } 331 332 std::string IPToSensitiveString(uint32 ip_as_host_order_integer) { 333 return IPAddress(ip_as_host_order_integer).ToSensitiveString(); 334 } 335 336 bool SocketAddress::StringToIP(const std::string& hostname, uint32* ip) { 337 in_addr addr; 338 if (talk_base::inet_pton(AF_INET, hostname.c_str(), &addr) == 0) 339 return false; 340 *ip = NetworkToHost32(addr.s_addr); 341 return true; 342 } 343 344 bool SocketAddress::StringToIP(const std::string& hostname, IPAddress* ip) { 345 in_addr addr4; 346 if (talk_base::inet_pton(AF_INET, hostname.c_str(), &addr4) > 0) { 347 if (ip) { 348 *ip = IPAddress(addr4); 349 } 350 return true; 351 } 352 353 in6_addr addr6; 354 if (talk_base::inet_pton(AF_INET6, hostname.c_str(), &addr6) > 0) { 355 if (ip) { 356 *ip = IPAddress(addr6); 357 } 358 return true; 359 } 360 return false; 361 } 362 363 uint32 SocketAddress::StringToIP(const std::string& hostname) { 364 uint32 ip = 0; 365 StringToIP(hostname, &ip); 366 return ip; 367 } 368 369 bool SocketAddressFromSockAddrStorage(const sockaddr_storage& addr, 370 SocketAddress* out) { 371 if (!out) { 372 return false; 373 } 374 if (addr.ss_family == AF_INET) { 375 const sockaddr_in* saddr = reinterpret_cast<const sockaddr_in*>(&addr); 376 *out = SocketAddress(IPAddress(saddr->sin_addr), 377 NetworkToHost16(saddr->sin_port)); 378 return true; 379 } else if (addr.ss_family == AF_INET6) { 380 const sockaddr_in6* saddr = reinterpret_cast<const sockaddr_in6*>(&addr); 381 *out = SocketAddress(IPAddress(saddr->sin6_addr), 382 NetworkToHost16(saddr->sin6_port)); 383 out->SetScopeID(saddr->sin6_scope_id); 384 return true; 385 } 386 return false; 387 } 388 389 SocketAddress EmptySocketAddressWithFamily(int family) { 390 if (family == AF_INET) { 391 return SocketAddress(IPAddress(INADDR_ANY), 0); 392 } else if (family == AF_INET6) { 393 return SocketAddress(IPAddress(in6addr_any), 0); 394 } 395 return SocketAddress(); 396 } 397 398 } // namespace talk_base 399