SocketAddress.cpp 22 KB

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