Fix folly memory leaks found with clang:dev + asan.
[folly.git] / folly / SocketAddress.cpp
1 /*
2  * Copyright 2014 Facebook, Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *   http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #ifndef __STDC_FORMAT_MACROS
18   #define __STDC_FORMAT_MACROS
19 #endif
20
21 #include <folly/SocketAddress.h>
22
23 #include <folly/Hash.h>
24
25 #include <boost/functional/hash.hpp>
26 #include <boost/static_assert.hpp>
27 #include <string.h>
28 #include <stdio.h>
29 #include <errno.h>
30 #include <sstream>
31 #include <string>
32
33 namespace {
34
35 /**
36  * A structure to free a struct addrinfo when it goes out of scope.
37  */
38 struct ScopedAddrInfo {
39   explicit ScopedAddrInfo(struct addrinfo* info) : info(info) {}
40   ~ScopedAddrInfo() {
41     freeaddrinfo(info);
42   }
43
44   struct addrinfo* info;
45 };
46
47 /**
48  * A simple data structure for parsing a host-and-port string.
49  *
50  * Accepts a string of the form "<host>:<port>" or just "<port>",
51  * and contains two string pointers to the host and the port portion of the
52  * string.
53  *
54  * The HostAndPort may contain pointers into the original string.  It is
55  * responsible for the user to ensure that the input string is valid for the
56  * lifetime of the HostAndPort structure.
57  */
58 struct HostAndPort {
59   HostAndPort(const char* str, bool hostRequired)
60     : host(nullptr),
61       port(nullptr),
62       allocated(nullptr) {
63
64     // Look for the last colon
65     const char* colon = strrchr(str, ':');
66     if (colon == nullptr) {
67       // No colon, just a port number.
68       if (hostRequired) {
69         throw std::invalid_argument(
70           "expected a host and port string of the "
71           "form \"<host>:<port>\"");
72       }
73       port = str;
74       return;
75     }
76
77     // We have to make a copy of the string so we can modify it
78     // and change the colon to a NUL terminator.
79     allocated = strdup(str);
80     if (!allocated) {
81       throw std::bad_alloc();
82     }
83
84     char *allocatedColon = allocated + (colon - str);
85     *allocatedColon = '\0';
86     host = allocated;
87     port = allocatedColon + 1;
88     // bracketed IPv6 address, remove the brackets
89     // allocatedColon[-1] is fine, as allocatedColon >= host and
90     // *allocatedColon != *host therefore allocatedColon > host
91     if (*host == '[' && allocatedColon[-1] == ']') {
92       allocatedColon[-1] = '\0';
93       ++host;
94     }
95   }
96
97   ~HostAndPort() {
98     free(allocated);
99   }
100
101   const char* host;
102   const char* port;
103   char* allocated;
104 };
105
106 } // unnamed namespace
107
108 namespace folly {
109
110 bool SocketAddress::isPrivateAddress() const {
111   auto family = getFamily();
112   if (family == AF_INET || family == AF_INET6) {
113     return storage_.addr.isPrivate() ||
114       (storage_.addr.isV6() && storage_.addr.asV6().isLinkLocal());
115   } else if (family == AF_UNIX) {
116     // Unix addresses are always local to a host.  Return true,
117     // since this conforms to the semantics of returning true for IP loopback
118     // addresses.
119     return true;
120   }
121   return false;
122 }
123
124 bool SocketAddress::isLoopbackAddress() const {
125   auto family = getFamily();
126   if (family == AF_INET || family == AF_INET6) {
127     return storage_.addr.isLoopback();
128   } else if (family == AF_UNIX) {
129     // Return true for UNIX addresses, since they are always local to a host.
130     return true;
131   }
132   return false;
133 }
134
135 void SocketAddress::setFromHostPort(const char* host, uint16_t port) {
136   ScopedAddrInfo results(getAddrInfo(host, port, 0));
137   setFromAddrInfo(results.info);
138 }
139
140 void SocketAddress::setFromIpPort(const char* ip, uint16_t port) {
141   ScopedAddrInfo results(getAddrInfo(ip, port, AI_NUMERICHOST));
142   setFromAddrInfo(results.info);
143 }
144
145 void SocketAddress::setFromLocalPort(uint16_t port) {
146   ScopedAddrInfo results(getAddrInfo(nullptr, port, AI_ADDRCONFIG));
147   setFromLocalAddr(results.info);
148 }
149
150 void SocketAddress::setFromLocalPort(const char* port) {
151   ScopedAddrInfo results(getAddrInfo(nullptr, port, AI_ADDRCONFIG));
152   setFromLocalAddr(results.info);
153 }
154
155 void SocketAddress::setFromLocalIpPort(const char* addressAndPort) {
156   HostAndPort hp(addressAndPort, false);
157   ScopedAddrInfo results(getAddrInfo(hp.host, hp.port,
158                                      AI_NUMERICHOST | AI_ADDRCONFIG));
159   setFromLocalAddr(results.info);
160 }
161
162 void SocketAddress::setFromIpPort(const char* addressAndPort) {
163   HostAndPort hp(addressAndPort, true);
164   ScopedAddrInfo results(getAddrInfo(hp.host, hp.port, AI_NUMERICHOST));
165   setFromAddrInfo(results.info);
166 }
167
168 void SocketAddress::setFromHostPort(const char* hostAndPort) {
169   HostAndPort hp(hostAndPort, true);
170   ScopedAddrInfo results(getAddrInfo(hp.host, hp.port, 0));
171   setFromAddrInfo(results.info);
172 }
173
174 void SocketAddress::setFromPath(const char* path, size_t len) {
175   if (getFamily() != AF_UNIX) {
176     storage_.un.init();
177     external_ = true;
178   }
179
180   storage_.un.len = offsetof(struct sockaddr_un, sun_path) + len;
181   if (len > sizeof(storage_.un.addr->sun_path)) {
182     throw std::invalid_argument(
183       "socket path too large to fit into sockaddr_un");
184   } else if (len == sizeof(storage_.un.addr->sun_path)) {
185     // Note that there will be no terminating NUL in this case.
186     // We allow this since getsockname() and getpeername() may return
187     // Unix socket addresses with paths that fit exactly in sun_path with no
188     // terminating NUL.
189     memcpy(storage_.un.addr->sun_path, path, len);
190   } else {
191     memcpy(storage_.un.addr->sun_path, path, len + 1);
192   }
193 }
194
195 void SocketAddress::setFromPeerAddress(int socket) {
196   setFromSocket(socket, getpeername);
197 }
198
199 void SocketAddress::setFromLocalAddress(int socket) {
200   setFromSocket(socket, getsockname);
201 }
202
203 void SocketAddress::setFromSockaddr(const struct sockaddr* address) {
204   uint16_t port;
205   if (address->sa_family == AF_INET) {
206     port = ntohs(((sockaddr_in*)address)->sin_port);
207   } else if (address->sa_family == AF_INET6) {
208     port = ntohs(((sockaddr_in6*)address)->sin6_port);
209   } else if (address->sa_family == AF_UNIX) {
210     // We need an explicitly specified length for AF_UNIX addresses,
211     // to be able to distinguish anonymous addresses from addresses
212     // in Linux's abstract namespace.
213     throw std::invalid_argument(
214       "SocketAddress::setFromSockaddr(): the address "
215       "length must be explicitly specified when "
216       "setting AF_UNIX addresses");
217   } else {
218     throw std::invalid_argument(
219       "SocketAddress::setFromSockaddr() called "
220       "with unsupported address type");
221   }
222   if (getFamily() == AF_UNIX) {
223     storage_.un.free();
224     external_ = false;
225   }
226   storage_.addr = folly::IPAddress(address);
227   port_ = port;
228 }
229
230 void SocketAddress::setFromSockaddr(const struct sockaddr* address,
231                                      socklen_t addrlen) {
232   // Check the length to make sure we can access address->sa_family
233   if (addrlen < (offsetof(struct sockaddr, sa_family) +
234                  sizeof(address->sa_family))) {
235     throw std::invalid_argument(
236       "SocketAddress::setFromSockaddr() called "
237       "with length too short for a sockaddr");
238   }
239
240   if (address->sa_family == AF_INET) {
241     if (addrlen < sizeof(struct sockaddr_in)) {
242       throw std::invalid_argument(
243         "SocketAddress::setFromSockaddr() called "
244         "with length too short for a sockaddr_in");
245     }
246     setFromSockaddr(reinterpret_cast<const struct sockaddr_in*>(address));
247   } else if (address->sa_family == AF_INET6) {
248     if (addrlen < sizeof(struct sockaddr_in6)) {
249       throw std::invalid_argument(
250         "SocketAddress::setFromSockaddr() called "
251         "with length too short for a sockaddr_in6");
252     }
253     setFromSockaddr(reinterpret_cast<const struct sockaddr_in6*>(address));
254   } else if (address->sa_family == AF_UNIX) {
255     setFromSockaddr(reinterpret_cast<const struct sockaddr_un*>(address),
256                     addrlen);
257   } else {
258     throw std::invalid_argument(
259       "SocketAddress::setFromSockaddr() called "
260       "with unsupported address type");
261   }
262 }
263
264 void SocketAddress::setFromSockaddr(const struct sockaddr_in* address) {
265   assert(address->sin_family == AF_INET);
266   setFromSockaddr((sockaddr*)address);
267 }
268
269 void SocketAddress::setFromSockaddr(const struct sockaddr_in6* address) {
270   assert(address->sin6_family == AF_INET6);
271   setFromSockaddr((sockaddr*)address);
272 }
273
274 void SocketAddress::setFromSockaddr(const struct sockaddr_un* address,
275                                      socklen_t addrlen) {
276   assert(address->sun_family == AF_UNIX);
277   if (addrlen > sizeof(struct sockaddr_un)) {
278     throw std::invalid_argument(
279       "SocketAddress::setFromSockaddr() called "
280       "with length too long for a sockaddr_un");
281   }
282
283   prepFamilyChange(AF_UNIX);
284   memcpy(storage_.un.addr, address, addrlen);
285   updateUnixAddressLength(addrlen);
286
287   // Fill the rest with 0s, just for safety
288   if (addrlen < sizeof(struct sockaddr_un)) {
289     char *p = reinterpret_cast<char*>(storage_.un.addr);
290     memset(p + addrlen, 0, sizeof(struct sockaddr_un) - addrlen);
291   }
292 }
293
294 const folly::IPAddress& SocketAddress::getIPAddress() const {
295   auto family = getFamily();
296   if (family != AF_INET && family != AF_INET6) {
297     throw InvalidAddressFamilyException(family);
298   }
299   return storage_.addr;
300 }
301
302 socklen_t SocketAddress::getActualSize() const {
303   switch (getFamily()) {
304     case AF_UNSPEC:
305     case AF_INET:
306       return sizeof(struct sockaddr_in);
307     case AF_INET6:
308       return sizeof(struct sockaddr_in6);
309     case AF_UNIX:
310       return storage_.un.len;
311     default:
312       throw std::invalid_argument(
313         "SocketAddress::getActualSize() called "
314         "with unrecognized address family");
315   }
316 }
317
318 std::string SocketAddress::getFullyQualified() const {
319   auto family = getFamily();
320   if (family != AF_INET && family != AF_INET6) {
321     throw std::invalid_argument("Can't get address str for non ip address");
322   }
323   return storage_.addr.toFullyQualified();
324 }
325
326 std::string SocketAddress::getAddressStr() const {
327   char buf[INET6_ADDRSTRLEN];
328   getAddressStr(buf, sizeof(buf));
329   return buf;
330 }
331
332 void SocketAddress::getAddressStr(char* buf, size_t buflen) const {
333   auto family = getFamily();
334   if (family != AF_INET && family != AF_INET6) {
335     throw std::invalid_argument("Can't get address str for non ip address");
336   }
337   std::string ret = storage_.addr.str();
338   size_t len = std::min(buflen, ret.size());
339   memcpy(buf, ret.data(), len);
340   buf[len] = '\0';
341 }
342
343 uint16_t SocketAddress::getPort() const {
344   switch (getFamily()) {
345     case AF_INET:
346     case AF_INET6:
347       return port_;
348     default:
349       throw std::invalid_argument(
350         "SocketAddress::getPort() called on non-IP "
351         "address");
352   }
353 }
354
355 void SocketAddress::setPort(uint16_t port) {
356   switch (getFamily()) {
357     case AF_INET:
358     case AF_INET6:
359       port_ = port;
360       return;
361     default:
362       throw std::invalid_argument(
363         "SocketAddress::setPort() called on non-IP "
364         "address");
365   }
366 }
367
368 void SocketAddress::convertToIPv4() {
369   if (!tryConvertToIPv4()) {
370     throw std::invalid_argument(
371       "convertToIPv4() called on an addresse that is "
372       "not an IPv4-mapped address");
373   }
374 }
375
376 bool SocketAddress::tryConvertToIPv4() {
377   if (!isIPv4Mapped()) {
378     return false;
379   }
380
381   storage_.addr = folly::IPAddress::createIPv4(storage_.addr);
382   return true;
383 }
384
385 bool SocketAddress::mapToIPv6() {
386   if (getFamily() != AF_INET) {
387     return false;
388   }
389
390   storage_.addr = folly::IPAddress::createIPv6(storage_.addr);
391   return true;
392 }
393
394 std::string SocketAddress::getHostStr() const {
395   return getIpString(0);
396 }
397
398 std::string SocketAddress::getPath() const {
399   if (getFamily() != AF_UNIX) {
400     throw std::invalid_argument(
401       "SocketAddress: attempting to get path "
402       "for a non-Unix address");
403   }
404
405   if (storage_.un.pathLength() == 0) {
406     // anonymous address
407     return std::string();
408   }
409   if (storage_.un.addr->sun_path[0] == '\0') {
410     // abstract namespace
411     return std::string(storage_.un.addr->sun_path, storage_.un.pathLength());
412   }
413
414   return std::string(storage_.un.addr->sun_path,
415                      strnlen(storage_.un.addr->sun_path,
416                              storage_.un.pathLength()));
417 }
418
419 std::string SocketAddress::describe() const {
420   switch (getFamily()) {
421     case AF_UNSPEC:
422       return "<uninitialized address>";
423     case AF_INET:
424     {
425       char buf[NI_MAXHOST + 16];
426       getAddressStr(buf, sizeof(buf));
427       size_t iplen = strlen(buf);
428       snprintf(buf + iplen, sizeof(buf) - iplen, ":%" PRIu16, getPort());
429       return buf;
430     }
431     case AF_INET6:
432     {
433       char buf[NI_MAXHOST + 18];
434       buf[0] = '[';
435       getAddressStr(buf + 1, sizeof(buf) - 1);
436       size_t iplen = strlen(buf);
437       snprintf(buf + iplen, sizeof(buf) - iplen, "]:%" PRIu16, getPort());
438       return buf;
439     }
440     case AF_UNIX:
441     {
442       if (storage_.un.pathLength() == 0) {
443         return "<anonymous unix address>";
444       }
445
446       if (storage_.un.addr->sun_path[0] == '\0') {
447         // Linux supports an abstract namespace for unix socket addresses
448         return "<abstract unix address>";
449       }
450
451       return std::string(storage_.un.addr->sun_path,
452                          strnlen(storage_.un.addr->sun_path,
453                                  storage_.un.pathLength()));
454     }
455     default:
456     {
457       char buf[64];
458       snprintf(buf, sizeof(buf), "<unknown address family %d>",
459                getFamily());
460       return buf;
461     }
462   }
463 }
464
465 bool SocketAddress::operator==(const SocketAddress& other) const {
466   if (other.getFamily() != getFamily()) {
467     return false;
468   }
469
470   switch (getFamily()) {
471     case AF_INET:
472     case AF_INET6:
473       return (other.storage_.addr == storage_.addr) &&
474         (other.port_ == port_);
475     case AF_UNIX:
476     {
477       // anonymous addresses are never equal to any other addresses
478       if (storage_.un.pathLength() == 0 ||
479           other.storage_.un.pathLength() == 0) {
480         return false;
481       }
482
483       if (storage_.un.len != other.storage_.un.len) {
484         return false;
485       }
486       int cmp = memcmp(storage_.un.addr->sun_path,
487                        other.storage_.un.addr->sun_path,
488                        storage_.un.pathLength());
489       return cmp == 0;
490     }
491     default:
492       throw std::invalid_argument(
493         "SocketAddress: unsupported address family "
494         "for comparison");
495   }
496 }
497
498 bool SocketAddress::prefixMatch(const SocketAddress& other,
499     unsigned prefixLength) const {
500   if (other.getFamily() != getFamily()) {
501     return false;
502   }
503   int mask_length = 128;
504   switch (getFamily()) {
505     case AF_INET:
506       mask_length = 32;
507       // fallthrough
508     case AF_INET6:
509     {
510       auto prefix = folly::IPAddress::longestCommonPrefix(
511         {storage_.addr, mask_length},
512         {other.storage_.addr, mask_length});
513       return prefix.second >= prefixLength;
514     }
515     default:
516       return false;
517   }
518 }
519
520
521 size_t SocketAddress::hash() const {
522   size_t seed = folly::hash::twang_mix64(getFamily());
523
524   switch (getFamily()) {
525     case AF_INET:
526     case AF_INET6: {
527       boost::hash_combine(seed, port_);
528       boost::hash_combine(seed, storage_.addr.hash());
529       break;
530     }
531     case AF_UNIX:
532     {
533       enum { kUnixPathMax = sizeof(storage_.un.addr->sun_path) };
534       const char *path = storage_.un.addr->sun_path;
535       size_t pathLength = storage_.un.pathLength();
536       // TODO: this probably could be made more efficient
537       for (unsigned int n = 0; n < pathLength; ++n) {
538         boost::hash_combine(seed, folly::hash::twang_mix64(path[n]));
539       }
540       break;
541     }
542     case AF_UNSPEC:
543     default:
544       throw std::invalid_argument(
545         "SocketAddress: unsupported address family "
546         "for hashing");
547   }
548
549   return seed;
550 }
551
552 struct addrinfo* SocketAddress::getAddrInfo(const char* host,
553                                              uint16_t port,
554                                              int flags) {
555   // getaddrinfo() requires the port number as a string
556   char portString[sizeof("65535")];
557   snprintf(portString, sizeof(portString), "%" PRIu16, port);
558
559   return getAddrInfo(host, portString, flags);
560 }
561
562 struct addrinfo* SocketAddress::getAddrInfo(const char* host,
563                                              const char* port,
564                                              int flags) {
565   struct addrinfo hints;
566   memset(&hints, 0, sizeof(hints));
567   hints.ai_family = AF_UNSPEC;
568   hints.ai_socktype = SOCK_STREAM;
569   hints.ai_flags = AI_PASSIVE | AI_NUMERICSERV | flags;
570
571   struct addrinfo *results;
572   int error = getaddrinfo(host, port, &hints, &results);
573   if (error != 0) {
574     auto os = folly::to<std::string>(
575       "Failed to resolve address for \"", host,  "\": ",
576       gai_strerror(error), " (error=", error,  ")");
577     throw std::system_error(error, std::generic_category(), os);
578   }
579
580   return results;
581 }
582
583 void SocketAddress::setFromAddrInfo(const struct addrinfo* info) {
584   setFromSockaddr(info->ai_addr, info->ai_addrlen);
585 }
586
587 void SocketAddress::setFromLocalAddr(const struct addrinfo* info) {
588   // If an IPv6 address is present, prefer to use it, since IPv4 addresses
589   // can be mapped into IPv6 space.
590   for (const struct addrinfo* ai = info; ai != nullptr; ai = ai->ai_next) {
591     if (ai->ai_family == AF_INET6) {
592       setFromSockaddr(ai->ai_addr, ai->ai_addrlen);
593       return;
594     }
595   }
596
597   // Otherwise, just use the first address in the list.
598   setFromSockaddr(info->ai_addr, info->ai_addrlen);
599 }
600
601 void SocketAddress::setFromSocket(int socket,
602                                   int (*fn)(int, sockaddr*, socklen_t*)) {
603   // If this was previously an AF_UNIX socket, free the external buffer.
604   // TODO: It would be smarter to just remember the external buffer, and then
605   // re-use it or free it depending on if the new address is also a unix
606   // socket.
607   if (getFamily() == AF_UNIX) {
608     storage_.un.free();
609     external_ = false;
610   }
611
612   // Try to put the address into a local storage buffer.
613   sockaddr_storage tmp_sock;
614   socklen_t addrLen = sizeof(tmp_sock);
615   if (fn(socket, (sockaddr*)&tmp_sock, &addrLen) != 0) {
616     folly::throwSystemError("setFromSocket() failed");
617   }
618
619   setFromSockaddr((sockaddr*)&tmp_sock, addrLen);
620 }
621
622 std::string SocketAddress::getIpString(int flags) const {
623   char addrString[NI_MAXHOST];
624   getIpString(addrString, sizeof(addrString), flags);
625   return std::string(addrString);
626 }
627
628 void SocketAddress::getIpString(char *buf, size_t buflen, int flags) const {
629   auto family = getFamily();
630   if (family != AF_INET &&
631       family != AF_INET6) {
632     throw std::invalid_argument(
633       "SocketAddress: attempting to get IP address "
634       "for a non-IP address");
635   }
636
637   sockaddr_storage tmp_sock;
638   storage_.addr.toSockaddrStorage(&tmp_sock, port_);
639   int rc = getnameinfo((sockaddr*)&tmp_sock, sizeof(sockaddr_storage),
640                        buf, buflen, nullptr, 0, flags);
641   if (rc != 0) {
642     auto os = folly::to<std::string>(
643       "getnameinfo() failed in getIpString() error = ",
644       gai_strerror(rc));
645     throw std::system_error(rc, std::generic_category(), os);
646   }
647 }
648
649 void SocketAddress::updateUnixAddressLength(socklen_t addrlen) {
650   if (addrlen < offsetof(struct sockaddr_un, sun_path)) {
651     throw std::invalid_argument(
652       "SocketAddress: attempted to set a Unix socket "
653       "with a length too short for a sockaddr_un");
654   }
655
656   storage_.un.len = addrlen;
657   if (storage_.un.pathLength() == 0) {
658     // anonymous address
659     return;
660   }
661
662   if (storage_.un.addr->sun_path[0] == '\0') {
663     // abstract namespace.  honor the specified length
664   } else {
665     // Call strnlen(), just in case the length was overspecified.
666     socklen_t maxLength = addrlen - offsetof(struct sockaddr_un, sun_path);
667     size_t pathLength = strnlen(storage_.un.addr->sun_path, maxLength);
668     storage_.un.len = offsetof(struct sockaddr_un, sun_path) + pathLength;
669   }
670 }
671
672 bool SocketAddress::operator<(const SocketAddress& other) const {
673   if (getFamily() != other.getFamily()) {
674     return getFamily() < other.getFamily();
675   }
676
677   switch (getFamily()) {
678     case AF_INET:
679     case AF_INET6: {
680       if (port_ != other.port_) {
681         return port_ < other.port_;
682       }
683
684       return
685         storage_.addr < other.storage_.addr;
686     }
687     case AF_UNIX: {
688       // Anonymous addresses can't be compared to anything else.
689       // Return that they are never less than anything.
690       //
691       // Note that this still meets the requirements for a strict weak
692       // ordering, so we can use this operator<() with standard C++ containers.
693       size_t thisPathLength = storage_.un.pathLength();
694       if (thisPathLength == 0) {
695         return false;
696       }
697       size_t otherPathLength = other.storage_.un.pathLength();
698       if (otherPathLength == 0) {
699         return true;
700       }
701
702       // Compare based on path length first, for efficiency
703       if (thisPathLength != otherPathLength) {
704         return thisPathLength < otherPathLength;
705       }
706       int cmp = memcmp(storage_.un.addr->sun_path,
707                        other.storage_.un.addr->sun_path,
708                        thisPathLength);
709       return cmp < 0;
710     }
711     case AF_UNSPEC:
712     default:
713       throw std::invalid_argument(
714         "SocketAddress: unsupported address family for comparing");
715   }
716 }
717
718 size_t hash_value(const SocketAddress& address) {
719   return address.hash();
720 }
721
722 std::ostream& operator<<(std::ostream& os, const SocketAddress& addr) {
723   os << addr.describe();
724   return os;
725 }
726
727 } // folly