SocketAddress.h 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627
  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. #pragma once
  17. #include <sys/types.h>
  18. #include <cstddef>
  19. #include <iosfwd>
  20. #include <string>
  21. #include <folly/IPAddress.h>
  22. #include <folly/Portability.h>
  23. #include <folly/Range.h>
  24. #include <folly/portability/Sockets.h>
  25. namespace folly {
  26. class SocketAddress {
  27. public:
  28. SocketAddress() = default;
  29. /**
  30. * Construct a SocketAddress from a hostname and port.
  31. *
  32. * Note: If the host parameter is not a numeric IP address, hostname
  33. * resolution will be performed, which can be quite slow.
  34. *
  35. * Raises std::system_error on error.
  36. *
  37. * @param host The IP address (or hostname, if allowNameLookup is true)
  38. * @param port The port (in host byte order)
  39. * @pram allowNameLookup If true, attempt to perform hostname lookup
  40. * if the hostname does not appear to be a numeric IP address.
  41. * This is potentially a very slow operation, so is disabled by
  42. * default.
  43. */
  44. SocketAddress(const char* host, uint16_t port, bool allowNameLookup = false) {
  45. // Initialize the address family first,
  46. // since setFromHostPort() and setFromIpPort() will check it.
  47. if (allowNameLookup) {
  48. setFromHostPort(host, port);
  49. } else {
  50. setFromIpPort(host, port);
  51. }
  52. }
  53. SocketAddress(
  54. const std::string& host,
  55. uint16_t port,
  56. bool allowNameLookup = false) {
  57. // Initialize the address family first,
  58. // since setFromHostPort() and setFromIpPort() will check it.
  59. if (allowNameLookup) {
  60. setFromHostPort(host.c_str(), port);
  61. } else {
  62. setFromIpPort(host.c_str(), port);
  63. }
  64. }
  65. SocketAddress(const IPAddress& ipAddr, uint16_t port) {
  66. setFromIpAddrPort(ipAddr, port);
  67. }
  68. SocketAddress(const SocketAddress& addr) {
  69. port_ = addr.port_;
  70. if (addr.getFamily() == AF_UNIX) {
  71. storage_.un.init(addr.storage_.un);
  72. } else {
  73. storage_ = addr.storage_;
  74. }
  75. external_ = addr.external_;
  76. }
  77. SocketAddress& operator=(const SocketAddress& addr) {
  78. if (!external_) {
  79. if (addr.getFamily() != AF_UNIX) {
  80. storage_ = addr.storage_;
  81. } else {
  82. storage_ = addr.storage_;
  83. storage_.un.init(addr.storage_.un);
  84. }
  85. } else {
  86. if (addr.getFamily() == AF_UNIX) {
  87. storage_.un.copy(addr.storage_.un);
  88. } else {
  89. storage_.un.free();
  90. storage_ = addr.storage_;
  91. }
  92. }
  93. port_ = addr.port_;
  94. external_ = addr.external_;
  95. return *this;
  96. }
  97. SocketAddress(SocketAddress&& addr) noexcept {
  98. storage_ = addr.storage_;
  99. port_ = addr.port_;
  100. external_ = addr.external_;
  101. addr.external_ = false;
  102. }
  103. SocketAddress& operator=(SocketAddress&& addr) {
  104. std::swap(storage_, addr.storage_);
  105. std::swap(port_, addr.port_);
  106. std::swap(external_, addr.external_);
  107. return *this;
  108. }
  109. ~SocketAddress() {
  110. if (external_) {
  111. storage_.un.free();
  112. }
  113. }
  114. bool isInitialized() const {
  115. return (getFamily() != AF_UNSPEC);
  116. }
  117. /**
  118. * Return whether this address is within private network.
  119. *
  120. * According to RFC1918, the 10/8 prefix, 172.16/12 prefix, and 192.168/16
  121. * prefix are reserved for private networks.
  122. * fc00::/7 is the IPv6 version, defined in RFC4139. IPv6 link-local
  123. * addresses (fe80::/10) are also considered private addresses.
  124. *
  125. * The loopback addresses 127/8 and ::1 are also regarded as private networks
  126. * for the purpose of this function.
  127. *
  128. * Returns true if this is a private network address, and false otherwise.
  129. */
  130. bool isPrivateAddress() const;
  131. /**
  132. * Return whether this address is a loopback address.
  133. */
  134. bool isLoopbackAddress() const;
  135. void reset() {
  136. if (external_) {
  137. storage_.un.free();
  138. }
  139. storage_.addr = folly::IPAddress();
  140. external_ = false;
  141. }
  142. /**
  143. * Initialize this SocketAddress from a hostname and port.
  144. *
  145. * Note: If the host parameter is not a numeric IP address, hostname
  146. * resolution will be performed, which can be quite slow.
  147. *
  148. * If the hostname resolves to multiple addresses, only the first will be
  149. * returned.
  150. *
  151. * Raises std::system_error on error.
  152. *
  153. * @param host The hostname or IP address
  154. * @param port The port (in host byte order)
  155. */
  156. void setFromHostPort(const char* host, uint16_t port);
  157. void setFromHostPort(const std::string& host, uint16_t port) {
  158. setFromHostPort(host.c_str(), port);
  159. }
  160. /**
  161. * Initialize this SocketAddress from an IP address and port.
  162. *
  163. * This is similar to setFromHostPort(), but only accepts numeric IP
  164. * addresses. If the IP string does not look like an IP address, it throws a
  165. * std::invalid_argument rather than trying to perform a hostname resolution.
  166. *
  167. * Raises std::system_error on error.
  168. *
  169. * @param ip The IP address, as a human-readable string.
  170. * @param port The port (in host byte order)
  171. */
  172. void setFromIpPort(const char* ip, uint16_t port);
  173. void setFromIpPort(const std::string& ip, uint16_t port) {
  174. setFromIpPort(ip.c_str(), port);
  175. }
  176. /**
  177. * Initialize this SocketAddress from an IPAddress struct and port.
  178. *
  179. * @param ip The IP address in IPAddress format
  180. * @param port The port (in host byte order)
  181. */
  182. void setFromIpAddrPort(const IPAddress& ip, uint16_t port);
  183. /**
  184. * Initialize this SocketAddress from a local port number.
  185. *
  186. * This is intended to be used by server code to determine the address to
  187. * listen on.
  188. *
  189. * If the current machine has any IPv6 addresses configured, an IPv6 address
  190. * will be returned (since connections from IPv4 clients can be mapped to the
  191. * IPv6 address). If the machine does not have any IPv6 addresses, an IPv4
  192. * address will be returned.
  193. */
  194. void setFromLocalPort(uint16_t port);
  195. /**
  196. * Initialize this SocketAddress from a local port number.
  197. *
  198. * This version of setFromLocalPort() accepts the port as a string. A
  199. * std::invalid_argument will be raised if the string does not refer to a port
  200. * number. Non-numeric service port names are not accepted.
  201. */
  202. void setFromLocalPort(const char* port);
  203. void setFromLocalPort(const std::string& port) {
  204. return setFromLocalPort(port.c_str());
  205. }
  206. /**
  207. * Initialize this SocketAddress from a local port number and optional IP
  208. * address.
  209. *
  210. * The addressAndPort string may be specified either as "<ip>:<port>", or
  211. * just as "<port>". If the IP is not specified, the address will be
  212. * initialized to 0, so that a server socket bound to this address will
  213. * accept connections on all local IP addresses.
  214. *
  215. * Both the IP address and port number must be numeric. DNS host names and
  216. * non-numeric service port names are not accepted.
  217. */
  218. void setFromLocalIpPort(const char* addressAndPort);
  219. void setFromLocalIpPort(const std::string& addressAndPort) {
  220. return setFromLocalIpPort(addressAndPort.c_str());
  221. }
  222. /**
  223. * Initialize this SocketAddress from an IP address and port number.
  224. *
  225. * The addressAndPort string must be of the form "<ip>:<port>". E.g.,
  226. * "10.0.0.1:1234".
  227. *
  228. * Both the IP address and port number must be numeric. DNS host names and
  229. * non-numeric service port names are not accepted.
  230. */
  231. void setFromIpPort(const char* addressAndPort);
  232. void setFromIpPort(const std::string& addressAndPort) {
  233. return setFromIpPort(addressAndPort.c_str());
  234. }
  235. /**
  236. * Initialize this SocketAddress from a host name and port number.
  237. *
  238. * The addressAndPort string must be of the form "<host>:<port>". E.g.,
  239. * "www.facebook.com:443".
  240. *
  241. * If the host name is not a numeric IP address, a DNS lookup will be
  242. * performed. Beware that the DNS lookup may be very slow. The port number
  243. * must be numeric; non-numeric service port names are not accepted.
  244. */
  245. void setFromHostPort(const char* hostAndPort);
  246. void setFromHostPort(const std::string& hostAndPort) {
  247. return setFromHostPort(hostAndPort.c_str());
  248. }
  249. /**
  250. * Returns the port number from the given socketaddr structure.
  251. *
  252. * Currently only IPv4 and IPv6 are supported.
  253. *
  254. * Returns -1 for unsupported socket families.
  255. */
  256. static int getPortFrom(const struct sockaddr* address);
  257. /**
  258. * Returns the family name from the given socketaddr structure (e.g.: AF_INET6
  259. * for IPv6).
  260. *
  261. * Returns `defaultResult` for unsupported socket families.
  262. */
  263. static const char* getFamilyNameFrom(
  264. const struct sockaddr* address,
  265. const char* defaultResult = nullptr);
  266. /**
  267. * Initialize this SocketAddress from a local unix path.
  268. *
  269. * Raises std::invalid_argument on error.
  270. */
  271. void setFromPath(StringPiece path);
  272. void setFromPath(const char* path, size_t length) {
  273. setFromPath(StringPiece{path, length});
  274. }
  275. /**
  276. * Construct a SocketAddress from a local unix socket path.
  277. *
  278. * Raises std::invalid_argument on error.
  279. *
  280. * @param path The Unix domain socket path.
  281. */
  282. static SocketAddress makeFromPath(StringPiece path) {
  283. SocketAddress addr;
  284. addr.setFromPath(path);
  285. return addr;
  286. }
  287. /**
  288. * Initialize this SocketAddress from a socket's peer address.
  289. *
  290. * Raises std::system_error on error.
  291. */
  292. void setFromPeerAddress(int socket);
  293. /**
  294. * Initialize this SocketAddress from a socket's local address.
  295. *
  296. * Raises std::system_error on error.
  297. */
  298. void setFromLocalAddress(int socket);
  299. /**
  300. * Initialize this folly::SocketAddress from a struct sockaddr.
  301. *
  302. * Raises std::system_error on error.
  303. *
  304. * This method is not supported for AF_UNIX addresses. For unix addresses,
  305. * the address length must be explicitly specified.
  306. *
  307. * @param address A struct sockaddr. The size of the address is implied
  308. * from address->sa_family.
  309. */
  310. void setFromSockaddr(const struct sockaddr* address);
  311. /**
  312. * Initialize this SocketAddress from a struct sockaddr.
  313. *
  314. * Raises std::system_error on error.
  315. *
  316. * @param address A struct sockaddr.
  317. * @param addrlen The length of address data available. This must be long
  318. * enough for the full address type required by
  319. * address->sa_family.
  320. */
  321. void setFromSockaddr(const struct sockaddr* address, socklen_t addrlen);
  322. /**
  323. * Initialize this SocketAddress from a struct sockaddr_in.
  324. */
  325. void setFromSockaddr(const struct sockaddr_in* address);
  326. /**
  327. * Initialize this SocketAddress from a struct sockaddr_in6.
  328. */
  329. void setFromSockaddr(const struct sockaddr_in6* address);
  330. /**
  331. * Initialize this SocketAddress from a struct sockaddr_un.
  332. *
  333. * Note that the addrlen parameter is necessary to properly detect anonymous
  334. * addresses, which have 0 valid path bytes, and may not even have a NUL
  335. * character at the start of the path.
  336. *
  337. * @param address A struct sockaddr_un.
  338. * @param addrlen The length of address data. This should include all of
  339. * the valid bytes of sun_path, not including any NUL
  340. * terminator.
  341. */
  342. void setFromSockaddr(const struct sockaddr_un* address, socklen_t addrlen);
  343. /**
  344. * Fill in a given sockaddr_storage with the ip or unix address.
  345. *
  346. * Returns the actual size of the storage used.
  347. */
  348. socklen_t getAddress(sockaddr_storage* addr) const {
  349. if (!external_) {
  350. return storage_.addr.toSockaddrStorage(addr, htons(port_));
  351. } else {
  352. memcpy(addr, storage_.un.addr, sizeof(*storage_.un.addr));
  353. return storage_.un.len;
  354. }
  355. }
  356. const folly::IPAddress& getIPAddress() const;
  357. // Deprecated: getAddress() above returns the same size as getActualSize()
  358. socklen_t getActualSize() const;
  359. sa_family_t getFamily() const {
  360. DCHECK(external_ || AF_UNIX != storage_.addr.family());
  361. return external_ ? sa_family_t(AF_UNIX) : storage_.addr.family();
  362. }
  363. bool empty() const {
  364. return getFamily() == AF_UNSPEC;
  365. }
  366. /**
  367. * Get a string representation of the IPv4 or IPv6 address.
  368. *
  369. * Raises std::invalid_argument if an error occurs (for example, if
  370. * the address is not an IPv4 or IPv6 address).
  371. */
  372. std::string getAddressStr() const;
  373. /**
  374. * Get a string representation of the IPv4 or IPv6 address.
  375. *
  376. * Raises std::invalid_argument if an error occurs (for example, if
  377. * the address is not an IPv4 or IPv6 address).
  378. */
  379. void getAddressStr(char* buf, size_t buflen) const;
  380. /**
  381. * Return true if it is a valid IPv4 or IPv6 address.
  382. */
  383. bool isFamilyInet() const;
  384. /**
  385. * For v4 & v6 addresses, return the fully qualified address string
  386. */
  387. std::string getFullyQualified() const;
  388. /**
  389. * Get the IPv4 or IPv6 port for this address.
  390. *
  391. * Raises std::invalid_argument if this is not an IPv4 or IPv6 address.
  392. *
  393. * @return Returns the port, in host byte order.
  394. */
  395. uint16_t getPort() const;
  396. /**
  397. * Set the IPv4 or IPv6 port for this address.
  398. *
  399. * Raises std::invalid_argument if this is not an IPv4 or IPv6 address.
  400. */
  401. void setPort(uint16_t port);
  402. /**
  403. * Return true if this is an IPv4-mapped IPv6 address.
  404. */
  405. bool isIPv4Mapped() const {
  406. return (getFamily() == AF_INET6 && storage_.addr.isIPv4Mapped());
  407. }
  408. /**
  409. * Convert an IPv4-mapped IPv6 address to an IPv4 address.
  410. *
  411. * Raises std::invalid_argument if this is not an IPv4-mapped IPv6 address.
  412. */
  413. void convertToIPv4();
  414. /**
  415. * Try to convert an address to IPv4.
  416. *
  417. * This attempts to convert an address to an IPv4 address if possible.
  418. * If the address is an IPv4-mapped IPv6 address, it is converted to an IPv4
  419. * address and true is returned. Otherwise nothing is done, and false is
  420. * returned.
  421. */
  422. bool tryConvertToIPv4();
  423. /**
  424. * Convert an IPv4 address to IPv6 [::ffff:a.b.c.d]
  425. */
  426. bool mapToIPv6();
  427. /**
  428. * Get string representation of the host name (or IP address if the host name
  429. * cannot be resolved).
  430. *
  431. * Warning: Using this method is strongly discouraged. It performs a
  432. * DNS lookup, which may block for many seconds.
  433. *
  434. * Raises std::invalid_argument if an error occurs.
  435. */
  436. std::string getHostStr() const;
  437. /**
  438. * Get the path name for a Unix domain socket.
  439. *
  440. * Returns a std::string containing the path. For anonymous sockets, an
  441. * empty string is returned.
  442. *
  443. * For addresses in the abstract namespace (Linux-specific), a std::string
  444. * containing binary data is returned. In this case the first character will
  445. * always be a NUL character.
  446. *
  447. * Raises std::invalid_argument if called on a non-Unix domain socket.
  448. */
  449. std::string getPath() const;
  450. /**
  451. * Get human-readable string representation of the address.
  452. *
  453. * This prints a string representation of the address, for human consumption.
  454. * For IP addresses, the string is of the form "<IP>:<port>".
  455. */
  456. std::string describe() const;
  457. bool operator==(const SocketAddress& other) const;
  458. bool operator!=(const SocketAddress& other) const {
  459. return !(*this == other);
  460. }
  461. /**
  462. * Check whether the first N bits of this address match the first N
  463. * bits of another address.
  464. * @note returns false if the addresses are not from the same
  465. * address family or if the family is neither IPv4 nor IPv6
  466. */
  467. bool prefixMatch(const SocketAddress& other, unsigned prefixLength) const;
  468. /**
  469. * Use this operator for storing maps based on SocketAddress.
  470. */
  471. bool operator<(const SocketAddress& other) const;
  472. /**
  473. * Compuate a hash of a SocketAddress.
  474. */
  475. size_t hash() const;
  476. private:
  477. /**
  478. * Unix socket addresses require more storage than IPv4 and IPv6 addresses,
  479. * and are comparatively little-used.
  480. *
  481. * Therefore SocketAddress' internal storage_ member variable doesn't
  482. * contain room for a full unix address, to avoid wasting space in the common
  483. * case. When we do need to store a Unix socket address, we use this
  484. * ExternalUnixAddr structure to allocate a struct sockaddr_un separately on
  485. * the heap.
  486. */
  487. struct ExternalUnixAddr {
  488. struct sockaddr_un* addr;
  489. socklen_t len;
  490. socklen_t pathLength() const {
  491. return socklen_t(len - offsetof(struct sockaddr_un, sun_path));
  492. }
  493. void init() {
  494. addr = new struct sockaddr_un;
  495. addr->sun_family = AF_UNIX;
  496. len = 0;
  497. }
  498. void init(const ExternalUnixAddr& other) {
  499. addr = new struct sockaddr_un;
  500. len = other.len;
  501. memcpy(addr, other.addr, size_t(len));
  502. }
  503. void copy(const ExternalUnixAddr& other) {
  504. len = other.len;
  505. memcpy(addr, other.addr, size_t(len));
  506. }
  507. void free() {
  508. delete addr;
  509. }
  510. };
  511. struct addrinfo* getAddrInfo(const char* host, uint16_t port, int flags);
  512. struct addrinfo* getAddrInfo(const char* host, const char* port, int flags);
  513. void setFromAddrInfo(const struct addrinfo* results);
  514. void setFromLocalAddr(const struct addrinfo* results);
  515. void setFromSocket(int socket, int (*fn)(int, struct sockaddr*, socklen_t*));
  516. std::string getIpString(int flags) const;
  517. void getIpString(char* buf, size_t buflen, int flags) const;
  518. void updateUnixAddressLength(socklen_t addrlen);
  519. /*
  520. * storage_ contains room for a full IPv4 or IPv6 address, so they can be
  521. * stored inline without a separate allocation on the heap.
  522. *
  523. * If we need to store a Unix socket address, ExternalUnixAddr is a shim to
  524. * track a struct sockaddr_un allocated separately on the heap.
  525. */
  526. union AddrStorage {
  527. folly::IPAddress addr;
  528. ExternalUnixAddr un;
  529. AddrStorage() : addr() {}
  530. } storage_{};
  531. // IPAddress class does nto save zone or port, and must be saved here
  532. uint16_t port_;
  533. bool external_{false};
  534. };
  535. /**
  536. * Hash a SocketAddress object.
  537. *
  538. * boost::hash uses hash_value(), so this allows boost::hash to automatically
  539. * work for SocketAddress.
  540. */
  541. size_t hash_value(const SocketAddress& address);
  542. std::ostream& operator<<(std::ostream& os, const SocketAddress& addr);
  543. } // namespace folly
  544. namespace std {
  545. // Provide an implementation for std::hash<SocketAddress>
  546. template <>
  547. struct hash<folly::SocketAddress> {
  548. size_t operator()(const folly::SocketAddress& addr) const {
  549. return addr.hash();
  550. }
  551. };
  552. } // namespace std