ip.h 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  1. #pragma once
  2. #include <util/digest/murmur.h>
  3. #include <util/network/ip.h>
  4. #include <util/str_stl.h>
  5. #include <util/generic/maybe.h>
  6. #include <util/generic/variant.h>
  7. #ifdef _unix_
  8. #include <sys/types.h>
  9. #include <sys/socket.h>
  10. #include <arpa/inet.h>
  11. #endif // _unix_
  12. #include <string.h>
  13. #ifndef INET6_ADDRSTRLEN
  14. #define INET6_ADDRSTRLEN 46
  15. #endif
  16. // Network (big-endian) byte order
  17. using TIp4 = TIpHost;
  18. // Network (big-endian) byte order
  19. struct TIp6 {
  20. char Data[16];
  21. bool operator==(const TIp6& rhs) const {
  22. return memcmp(Data, rhs.Data, sizeof(Data)) == 0;
  23. }
  24. bool operator<(const TIp6& rhs) const {
  25. return memcmp(Data, rhs.Data, sizeof(Data)) < 0;
  26. }
  27. };
  28. template <>
  29. struct THash<TIp6> {
  30. inline size_t operator()(const TIp6& ip) const {
  31. return MurmurHash<size_t>((const void*)ip.Data, 16);
  32. }
  33. };
  34. static inline TIp6 Ip6FromIp4(TIp4 addr) {
  35. TIp6 res;
  36. memset(res.Data, 0, sizeof(res.Data));
  37. res.Data[10] = '\xFF';
  38. res.Data[11] = '\xFF';
  39. memcpy(res.Data + 12, &addr, 4);
  40. return res;
  41. }
  42. static inline TIp6 Ip6FromString(const char* ipStr) {
  43. TIp6 res;
  44. if (inet_pton(AF_INET6, ipStr, &res.Data) == 0) {
  45. ythrow TSystemError() << "Failed to convert (" << ipStr << ") to ipv6 address";
  46. }
  47. return res;
  48. }
  49. static inline TMaybe<TIp6> TryParseIp6FromString(const char* ipStr) {
  50. TIp6 res;
  51. if (inet_pton(AF_INET6, ipStr, &res.Data) == 0) {
  52. return Nothing();
  53. }
  54. return res;
  55. }
  56. static inline char* Ip6ToString(const TIp6& ip, char* buf, size_t len) {
  57. if (!inet_ntop(AF_INET6, (void*)&ip.Data, buf, (socklen_t)len)) {
  58. ythrow TSystemError() << "Failed to get ipv6 address string";
  59. }
  60. return buf;
  61. }
  62. static inline TString Ip6ToString(const TIp6& ip) {
  63. char buf[INET6_ADDRSTRLEN];
  64. return TString(Ip6ToString(ip, buf, sizeof(buf)));
  65. }
  66. template <>
  67. inline void Out<TIp6>(IOutputStream& os, const TIp6& a) {
  68. os << Ip6ToString(a);
  69. }
  70. using TIp4Or6 = std::variant<TIp4, TIp6>;
  71. static inline TIp4Or6 Ip4Or6FromString(const char* ipStr) {
  72. const char* c = ipStr;
  73. for (; *c; ++c) {
  74. if (*c == '.') {
  75. return IpFromString(ipStr);
  76. }
  77. if (*c == ':') {
  78. return Ip6FromString(ipStr);
  79. }
  80. }
  81. ythrow TSystemError() << "Failed to convert (" << ipStr << ") to ipv4 or ipv6 address";
  82. }
  83. static inline TString Ip4Or6ToString(const TIp4Or6& ip) {
  84. if (std::holds_alternative<TIp6>(ip)) {
  85. return Ip6ToString(std::get<TIp6>(ip));
  86. } else {
  87. return IpToString(std::get<TIp4>(ip));
  88. }
  89. }
  90. // for TIp4 or TIp6, not TIp4Or6
  91. template <class TIp>
  92. struct TIpCompare {
  93. bool Less(const TIp& l, const TIp& r) const {
  94. return memcmp(&l, &r, sizeof(TIp)) < 0;
  95. }
  96. bool LessEqual(const TIp& l, const TIp& r) const {
  97. return memcmp(&l, &r, sizeof(TIp)) <= 0;
  98. }
  99. bool operator()(const TIp& l, const TIp& r) const {
  100. return Less(l, r);
  101. }
  102. };