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 // Address family constants for STUN (see RFC 5389).
57 static const int kStunFamilyIPv4 = 1;
58 static const int kStunFamilyIPv6 = 2;
59
SocketAddress()60 SocketAddress::SocketAddress() {
61 Clear();
62 }
63
SocketAddress(const std::string & hostname,int port)64 SocketAddress::SocketAddress(const std::string& hostname, int port) {
65 SetIP(hostname);
66 SetPort(port);
67 }
68
SocketAddress(uint32 ip_as_host_order_integer,int port)69 SocketAddress::SocketAddress(uint32 ip_as_host_order_integer, int port) {
70 SetIP(IPAddress(ip_as_host_order_integer));
71 SetPort(port);
72 }
73
SocketAddress(const IPAddress & ip,int port)74 SocketAddress::SocketAddress(const IPAddress& ip, int port) {
75 SetIP(ip);
76 SetPort(port);
77 }
78
SocketAddress(const SocketAddress & addr)79 SocketAddress::SocketAddress(const SocketAddress& addr) {
80 this->operator=(addr);
81 }
82
Clear()83 void SocketAddress::Clear() {
84 hostname_.clear();
85 literal_ = false;
86 ip_ = IPAddress(INADDR_ANY);
87 port_ = 0;
88 }
89
IsNil() const90 bool SocketAddress::IsNil() const {
91 return hostname_.empty() && IPIsAny(ip_) && 0 == port_;
92 }
93
IsComplete() const94 bool SocketAddress::IsComplete() const {
95 return (!IPIsAny(ip_)) && (0 != port_);
96 }
97
operator =(const SocketAddress & addr)98 SocketAddress& SocketAddress::operator=(const SocketAddress& addr) {
99 hostname_ = addr.hostname_;
100 ip_ = addr.ip_;
101 port_ = addr.port_;
102 literal_ = addr.literal_;
103 return *this;
104 }
105
SetIP(uint32 ip_as_host_order_integer)106 void SocketAddress::SetIP(uint32 ip_as_host_order_integer) {
107 hostname_.clear();
108 literal_ = false;
109 ip_ = IPAddress(ip_as_host_order_integer);
110 }
111
SetIP(const IPAddress & ip)112 void SocketAddress::SetIP(const IPAddress& ip) {
113 hostname_.clear();
114 literal_ = false;
115 ip_ = ip;
116 }
117
SetIP(const std::string & hostname)118 void SocketAddress::SetIP(const std::string& hostname) {
119 hostname_ = hostname;
120 literal_ = IPFromString(hostname, &ip_);
121 if (!literal_) {
122 ip_ = IPAddress(INADDR_ANY);
123 }
124 }
125
SetResolvedIP(uint32 ip_as_host_order_integer)126 void SocketAddress::SetResolvedIP(uint32 ip_as_host_order_integer) {
127 ip_ = IPAddress(ip_as_host_order_integer);
128 }
129
SetResolvedIP(const IPAddress & ip)130 void SocketAddress::SetResolvedIP(const IPAddress& ip) {
131 ip_ = ip;
132 }
133
SetPort(int port)134 void SocketAddress::SetPort(int port) {
135 ASSERT((0 <= port) && (port < 65536));
136 port_ = port;
137 }
138
ip() const139 uint32 SocketAddress::ip() const {
140 return ip_.v4AddressAsHostOrderInteger();
141 }
142
ipaddr() const143 const IPAddress& SocketAddress::ipaddr() const {
144 return ip_;
145 }
146
port() const147 uint16 SocketAddress::port() const {
148 return port_;
149 }
150
IPAsString() const151 std::string SocketAddress::IPAsString() const {
152 // If the hostname was a literal IP string, it may need to have square
153 // brackets added (for SocketAddress::ToString()).
154 if (!literal_ && !hostname_.empty())
155 return hostname_;
156 if (ip_.family() == AF_INET6) {
157 return "[" + ip_.ToString() + "]";
158 } else {
159 return ip_.ToString();
160 }
161 }
162
PortAsString() const163 std::string SocketAddress::PortAsString() const {
164 std::ostringstream ost;
165 ost << port_;
166 return ost.str();
167 }
168
ToString() const169 std::string SocketAddress::ToString() const {
170 std::ostringstream ost;
171 ost << IPAsString();
172 ost << ":";
173 ost << port();
174 return ost.str();
175 }
176
FromString(const std::string & str)177 bool SocketAddress::FromString(const std::string& str) {
178 if (str.at(0) == '[') {
179 std::string::size_type closebracket = str.rfind(']');
180 if (closebracket != std::string::npos) {
181 std::string::size_type colon = str.find(':', closebracket);
182 if (colon != std::string::npos && colon > closebracket) {
183 SetPort(strtoul(str.substr(colon + 1).c_str(), NULL, 10));
184 SetIP(str.substr(1, closebracket - 1));
185 } else {
186 return false;
187 }
188 }
189 } else {
190 std::string::size_type pos = str.find(':');
191 if (std::string::npos == pos)
192 return false;
193 SetPort(strtoul(str.substr(pos + 1).c_str(), NULL, 10));
194 SetIP(str.substr(0, pos));
195 }
196 return true;
197 }
198
operator <<(std::ostream & os,const SocketAddress & addr)199 std::ostream& operator<<(std::ostream& os, const SocketAddress& addr) {
200 os << addr.IPAsString() << ":" << addr.port();
201 return os;
202 }
203
IsAnyIP() const204 bool SocketAddress::IsAnyIP() const {
205 return IPIsAny(ip_);
206 }
207
IsLoopbackIP() const208 bool SocketAddress::IsLoopbackIP() const {
209 return IPIsLoopback(ip_) || (IPIsAny(ip_) &&
210 0 == strcmp(hostname_.c_str(), "localhost"));
211 }
212
IsLocalIP() const213 bool SocketAddress::IsLocalIP() const {
214 if (IsLoopbackIP())
215 return true;
216
217 std::vector<IPAddress> ips;
218 if (IPIsAny(ip_)) {
219 if (!hostname_.empty()
220 && (0 == stricmp(hostname_.c_str(), GetHostname().c_str()))) {
221 return true;
222 }
223 } else if (GetLocalIPs(&ips)) {
224 for (size_t i = 0; i < ips.size(); ++i) {
225 if (ips[i] == ip_) {
226 return true;
227 }
228 }
229 }
230 return false;
231 }
232
IsPrivateIP() const233 bool SocketAddress::IsPrivateIP() const {
234 return IPIsPrivate(ip_);
235 }
236
IsUnresolvedIP() const237 bool SocketAddress::IsUnresolvedIP() const {
238 return IsAny() && !literal_ && !hostname_.empty();
239 }
240
ResolveIP(bool force,int * error)241 bool SocketAddress::ResolveIP(bool force, int* error) {
242 if (hostname_.empty()) {
243 // nothing to resolve
244 } else if (!force && !IsAny()) {
245 // already resolved
246 } else {
247 LOG_F(LS_VERBOSE) << "(" << hostname_ << ")";
248 int errcode = 0;
249 if (hostent* pHost = SafeGetHostByName(hostname_.c_str(), &errcode)) {
250 if (IPFromHostEnt(pHost, &ip_)) {
251 LOG_F(LS_VERBOSE) << "(" << hostname_ << ") resolved to: "
252 << ip_.ToString();
253 }
254 FreeHostEnt(pHost);
255 } else {
256 LOG_F(LS_ERROR) << "(" << hostname_ << ") err: " << errcode;
257 }
258 if (error) {
259 *error = errcode;
260 }
261 }
262 return (!IPIsAny(ip_));
263 }
264
operator ==(const SocketAddress & addr) const265 bool SocketAddress::operator==(const SocketAddress& addr) const {
266 return EqualIPs(addr) && EqualPorts(addr);
267 }
268
operator <(const SocketAddress & addr) const269 bool SocketAddress::operator<(const SocketAddress& addr) const {
270 if (ip_ < addr.ip_)
271 return true;
272 else if (addr.ip_ < ip_)
273 return false;
274
275 // We only check hostnames if both IPs are zero. This matches EqualIPs()
276 if (addr.IsAnyIP()) {
277 if (hostname_ < addr.hostname_)
278 return true;
279 else if (addr.hostname_ < hostname_)
280 return false;
281 }
282
283 return port_ < addr.port_;
284 }
285
EqualIPs(const SocketAddress & addr) const286 bool SocketAddress::EqualIPs(const SocketAddress& addr) const {
287 return (ip_ == addr.ip_) &&
288 ((!IPIsAny(ip_)) || (hostname_ == addr.hostname_));
289 }
290
EqualPorts(const SocketAddress & addr) const291 bool SocketAddress::EqualPorts(const SocketAddress& addr) const {
292 return (port_ == addr.port_);
293 }
294
Hash() const295 size_t SocketAddress::Hash() const {
296 size_t h = 0;
297 h ^= HashIP(ip_);
298 h ^= port_ | (port_ << 16);
299 return h;
300 }
301
ToSockAddr(sockaddr_in * saddr) const302 void SocketAddress::ToSockAddr(sockaddr_in* saddr) const {
303 memset(saddr, 0, sizeof(*saddr));
304 if (ip_.family() != AF_INET) {
305 saddr->sin_family = AF_UNSPEC;
306 return;
307 }
308 saddr->sin_family = AF_INET;
309 saddr->sin_port = HostToNetwork16(port_);
310 if (IPIsAny(ip_)) {
311 saddr->sin_addr.s_addr = INADDR_ANY;
312 } else {
313 saddr->sin_addr = ip_.ipv4_address();
314 }
315 }
316
FromSockAddr(const sockaddr_in & saddr)317 bool SocketAddress::FromSockAddr(const sockaddr_in& saddr) {
318 if (saddr.sin_family != AF_INET)
319 return false;
320 SetIP(NetworkToHost32(saddr.sin_addr.s_addr));
321 SetPort(NetworkToHost16(saddr.sin_port));
322 literal_ = false;
323 return true;
324 }
325
ToSockAddrStorageHelper(sockaddr_storage * addr,IPAddress ip,int port,int scope_id)326 static size_t ToSockAddrStorageHelper(sockaddr_storage* addr,
327 IPAddress ip, int port, int scope_id) {
328 memset(addr, 0, sizeof(sockaddr_storage));
329 addr->ss_family = ip.family();
330 if (addr->ss_family == AF_INET6) {
331 sockaddr_in6* saddr = reinterpret_cast<sockaddr_in6*>(addr);
332 saddr->sin6_addr = ip.ipv6_address();
333 saddr->sin6_port = HostToNetwork16(port);
334 saddr->sin6_scope_id = scope_id;
335 return sizeof(sockaddr_in6);
336 } else if (addr->ss_family == AF_INET) {
337 sockaddr_in* saddr = reinterpret_cast<sockaddr_in*>(addr);
338 saddr->sin_addr = ip.ipv4_address();
339 saddr->sin_port = HostToNetwork16(port);
340 return sizeof(sockaddr_in);
341 }
342 return 0;
343 }
344
ToDualStackSockAddrStorage(sockaddr_storage * addr) const345 size_t SocketAddress::ToDualStackSockAddrStorage(sockaddr_storage *addr) const {
346 return ToSockAddrStorageHelper(addr, ip_.AsIPv6Address(), port_, scope_id_);
347 }
348
ToSockAddrStorage(sockaddr_storage * addr) const349 size_t SocketAddress::ToSockAddrStorage(sockaddr_storage* addr) const {
350 return ToSockAddrStorageHelper(addr, ip_, port_, scope_id_);
351 }
352
IPToString(uint32 ip_as_host_order_integer)353 std::string SocketAddress::IPToString(uint32 ip_as_host_order_integer) {
354 std::ostringstream ost;
355 ost << ((ip_as_host_order_integer >> 24) & 0xff);
356 ost << '.';
357 ost << ((ip_as_host_order_integer >> 16) & 0xff);
358 ost << '.';
359 ost << ((ip_as_host_order_integer >> 8) & 0xff);
360 ost << '.';
361 ost << ((ip_as_host_order_integer >> 0) & 0xff);
362 return ost.str();
363 }
364
StringToIP(const std::string & hostname,uint32 * ip)365 bool SocketAddress::StringToIP(const std::string& hostname, uint32* ip) {
366 in_addr addr;
367 if (talk_base::inet_pton(AF_INET, hostname.c_str(), &addr) == 0)
368 return false;
369 *ip = NetworkToHost32(addr.s_addr);
370 return true;
371 }
372
StringToIP(const std::string & hostname,IPAddress * ip)373 bool SocketAddress::StringToIP(const std::string& hostname, IPAddress* ip) {
374 in_addr addr4;
375 if (talk_base::inet_pton(AF_INET, hostname.c_str(), &addr4) > 0) {
376 if (ip) {
377 *ip = IPAddress(addr4);
378 }
379 return true;
380 }
381
382 in6_addr addr6;
383 if (talk_base::inet_pton(AF_INET6, hostname.c_str(), &addr6) > 0) {
384 if (ip) {
385 *ip = IPAddress(addr6);
386 }
387 return true;
388 }
389 return false;
390 }
391
StringToIP(const std::string & hostname)392 uint32 SocketAddress::StringToIP(const std::string& hostname) {
393 uint32 ip = 0;
394 StringToIP(hostname, &ip);
395 return ip;
396 }
397
GetHostname()398 std::string SocketAddress::GetHostname() {
399 char hostname[256];
400 if (gethostname(hostname, ARRAY_SIZE(hostname)) == 0)
401 return hostname;
402 return "";
403 }
404
GetLocalIPs(std::vector<IPAddress> * ips)405 bool SocketAddress::GetLocalIPs(std::vector<IPAddress>* ips) {
406 if (!ips) {
407 return false;
408 }
409 ips->clear();
410
411 const std::string hostname = SocketAddress::GetHostname();
412 if (hostname.empty())
413 return false;
414
415 int errcode;
416 if (hostent* pHost = SafeGetHostByName(hostname.c_str(), &errcode)) {
417 for (int i = 0; pHost->h_addr_list[i]; ++i) {
418 IPAddress ip;
419 if (IPFromHostEnt(pHost, i, &ip)) {
420 ips->push_back(ip);
421 }
422 }
423 FreeHostEnt(pHost);
424 return !ips->empty();
425 }
426 LOG(LS_ERROR) << "gethostbyname err: " << errcode;
427 return false;
428 }
429
SocketAddressFromSockAddrStorage(const sockaddr_storage & addr,SocketAddress * out)430 bool SocketAddressFromSockAddrStorage(const sockaddr_storage& addr,
431 SocketAddress* out) {
432 if (!out) {
433 return false;
434 }
435 if (addr.ss_family == AF_INET) {
436 const sockaddr_in* saddr = reinterpret_cast<const sockaddr_in*>(&addr);
437 *out = SocketAddress(IPAddress(saddr->sin_addr),
438 NetworkToHost16(saddr->sin_port));
439 return true;
440 } else if (addr.ss_family == AF_INET6) {
441 const sockaddr_in6* saddr = reinterpret_cast<const sockaddr_in6*>(&addr);
442 *out = SocketAddress(IPAddress(saddr->sin6_addr),
443 NetworkToHost16(saddr->sin6_port));
444 out->SetScopeID(saddr->sin6_scope_id);
445 return true;
446 }
447 return false;
448 }
449 } // namespace talk_base
450