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