ipv6_address.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442
  1. #include "ipv6_address.h"
  2. #include "ipv6_address_p.h"
  3. #ifdef _unix_
  4. #include <netinet/in.h>
  5. #endif
  6. #include <util/network/address.h>
  7. #include <util/network/init.h>
  8. #include <util/string/cast.h>
  9. #include <util/string/split.h>
  10. #include <util/system/byteorder.h>
  11. #include <util/ysaveload.h>
  12. #include <array>
  13. namespace {
  14. // reinterpret_cast from memory, where most significant bit is first
  15. inline ui128 FromMemMSF(const char* memPtr) {
  16. Y_ABORT_UNLESS(memPtr, " ");
  17. return ui128{
  18. *reinterpret_cast<const ui64*>(memPtr),
  19. *(reinterpret_cast<const ui64*>(memPtr) + 1)
  20. };
  21. }
  22. // zero-terminated copy of address string
  23. template <size_t N>
  24. inline auto AddrBuf(TStringBuf str) noexcept {
  25. std::array<char, N+1> res;
  26. auto len = Min(str.size(), N);
  27. CopyN(str.begin(), len, res.begin());
  28. res[len] = '\0';
  29. return res;
  30. }
  31. }
  32. void TIpv6Address::InitFrom(const in6_addr& addr) {
  33. const ui64* const ui64Ptr = reinterpret_cast<const ui64*>(&addr);
  34. const ui64 raw[2] = {SwapBytes(*ui64Ptr), SwapBytes(*(ui64Ptr + 1))};
  35. Ip = FromMemMSF(reinterpret_cast<const char*>(raw));
  36. Type_ = Ipv6;
  37. }
  38. void TIpv6Address::InitFrom(const in_addr& addr) {
  39. unsigned long swapped = SwapBytes(addr.s_addr);
  40. Ip = ui128{0, swapped};
  41. Type_ = Ipv4;
  42. }
  43. void TIpv6Address::InitFrom(const sockaddr_in6& Addr) {
  44. InitFrom(Addr.sin6_addr);
  45. ScopeId_ = Addr.sin6_scope_id;
  46. }
  47. void TIpv6Address::InitFrom(const sockaddr_in& Addr) {
  48. InitFrom(Addr.sin_addr);
  49. }
  50. TIpv6Address::TIpv6Address(const NAddr::IRemoteAddr& addr) {
  51. if (addr.Addr()->sa_family == AF_INET) { // IPv4
  52. const sockaddr_in* Tmp = reinterpret_cast<const sockaddr_in*>(addr.Addr());
  53. InitFrom(*Tmp);
  54. } else { // IPv6
  55. const sockaddr_in6* Tmp = reinterpret_cast<const sockaddr_in6*>(addr.Addr());
  56. InitFrom(*Tmp);
  57. }
  58. }
  59. TIpv6Address::TIpv6Address(const sockaddr_in6& Addr) {
  60. InitFrom(Addr);
  61. }
  62. TIpv6Address::TIpv6Address(const sockaddr_in& Addr) {
  63. InitFrom(Addr);
  64. }
  65. TIpv6Address::TIpv6Address(const in6_addr& addr, ui32 Scope) {
  66. InitFrom(addr);
  67. ScopeId_ = Scope;
  68. }
  69. TIpv6Address::TIpv6Address(const in_addr& addr) {
  70. InitFrom(addr);
  71. }
  72. TIpv6Address TIpv6Address::FromString(TStringBuf str, bool& ok) noexcept {
  73. const TIpType ipType = FigureOutType(str);
  74. if (ipType == Ipv6) {
  75. ui32 scopeId = 0;
  76. if (size_t pos = str.find('%'); pos != TStringBuf::npos) {
  77. ::TryFromString(str.substr(pos + 1), scopeId);
  78. str.Trunc(pos);
  79. }
  80. const auto buf = AddrBuf<INET6_ADDRSTRLEN>(str);
  81. in6_addr addr;
  82. if (inet_pton(AF_INET6, buf.data(), &addr) != 1) {
  83. ok = false;
  84. return TIpv6Address();
  85. }
  86. ok = true;
  87. return TIpv6Address(addr, scopeId);
  88. } else { // if (ipType == Ipv4) {
  89. const auto buf = AddrBuf<INET_ADDRSTRLEN>(str);
  90. in_addr addr;
  91. if (inet_pton(AF_INET, buf.data(), &addr) != 1) {
  92. ok = false;
  93. return TIpv6Address();
  94. }
  95. ok = true;
  96. return TIpv6Address(addr);
  97. }
  98. }
  99. TIpv6Address TIpv6Address::FromString(TStringBuf str) noexcept {
  100. bool ok = false;
  101. return TIpv6Address::FromString(str, ok);
  102. }
  103. TString TIpv6Address::ToString(bool* ok) const noexcept {
  104. return ToString(true, ok);
  105. }
  106. TString TIpv6Address::ToString(bool PrintScopeId, bool* ok) const noexcept {
  107. TString result;
  108. bool isOk = true;
  109. if (Type_ == TIpv6Address::Ipv4) {
  110. result.resize(INET_ADDRSTRLEN + 2);
  111. in_addr addr;
  112. ToInAddr(addr);
  113. isOk = inet_ntop(AF_INET, &addr, result.begin(), INET_ADDRSTRLEN);
  114. result.resize(result.find('\0'));
  115. } else if (Type_ == TIpv6Address::Ipv6) {
  116. result.resize(INET6_ADDRSTRLEN + 2);
  117. in6_addr addr;
  118. ToIn6Addr(addr);
  119. isOk = inet_ntop(AF_INET6, &addr, result.begin(), INET6_ADDRSTRLEN);
  120. result.resize(result.find('\0'));
  121. if (PrintScopeId)
  122. result += "%" + ::ToString(ScopeId_);
  123. } else {
  124. result = "null";
  125. isOk = true;
  126. }
  127. if (ok) {
  128. *ok = isOk;
  129. }
  130. return result;
  131. }
  132. void TIpv6Address::ToSockaddrAndSocklen(sockaddr_in& sockAddrIPv4,
  133. sockaddr_in6& sockAddrIPv6, // in
  134. const sockaddr*& sockAddrPtr,
  135. socklen_t& sockAddrSize,
  136. ui16 Port) const { // out
  137. if (Type_ == Ipv4) {
  138. memset(&sockAddrIPv4, 0, sizeof(sockAddrIPv4));
  139. sockAddrIPv4.sin_family = AF_INET;
  140. sockAddrIPv4.sin_port = htons(Port);
  141. ToInAddr(sockAddrIPv4.sin_addr);
  142. sockAddrSize = sizeof(sockAddrIPv4);
  143. sockAddrPtr = reinterpret_cast<sockaddr*>(&sockAddrIPv4);
  144. } else if (Type_ == Ipv6) {
  145. memset(&sockAddrIPv6, 0, sizeof(sockAddrIPv6));
  146. sockAddrIPv6.sin6_family = AF_INET6;
  147. sockAddrIPv6.sin6_port = htons(Port);
  148. ToIn6Addr(sockAddrIPv6.sin6_addr);
  149. sockAddrIPv6.sin6_scope_id = ScopeId_;
  150. sockAddrIPv6.sin6_flowinfo = 0;
  151. sockAddrSize = sizeof(sockAddrIPv6);
  152. sockAddrPtr = reinterpret_cast<sockaddr*>(&sockAddrIPv6);
  153. } else
  154. Y_ABORT_UNLESS(false);
  155. }
  156. void TIpv6Address::ToInAddr(in_addr& Addr4) const {
  157. Y_ABORT_UNLESS(Type_ == TIpv6Address::Ipv4);
  158. Zero(Addr4);
  159. ui32 Value = GetLow(Ip);
  160. Y_ABORT_UNLESS(Value == GetLow(Ip), " ");
  161. Y_ABORT_UNLESS(GetHigh(Ip) == 0, " ");
  162. Addr4.s_addr = SwapBytes(Value);
  163. }
  164. void TIpv6Address::ToIn6Addr(in6_addr& Addr6) const {
  165. Y_ABORT_UNLESS(Type_ == TIpv6Address::Ipv6);
  166. Zero(Addr6);
  167. ui64 Raw[2] = {GetHigh(Ip), GetLow(Ip)};
  168. *Raw = SwapBytes(*Raw);
  169. Raw[1] = SwapBytes(1 [Raw]);
  170. memcpy(&Addr6, Raw, sizeof(Raw));
  171. }
  172. void TIpv6Address::Save(IOutputStream* out) const {
  173. ::Save(out, Ip);
  174. ::Save(out, static_cast<ui8>(Type_));
  175. ::Save(out, ScopeId_);
  176. }
  177. void TIpv6Address::Load(IInputStream* in) {
  178. ::Load(in, Ip);
  179. ui8 num;
  180. ::Load(in, num);
  181. Type_ = static_cast<TIpType>(num);
  182. ::Load(in, ScopeId_);
  183. }
  184. bool TIpv6Address::Isv4MappedTov6() const noexcept {
  185. /// http://en.wikipedia.org/wiki/IPv6
  186. /// Hybrid dual-stack IPv6/IPv4 implementations recognize a special class of addresses,
  187. /// the IPv4-mapped IPv6 addresses. In these addresses, the first 80 bits are zero, the next 16 bits are one,
  188. /// and the remaining 32 bits are the IPv4 address.
  189. if (Type_ != Ipv6)
  190. return false;
  191. if (GetHigh(Ip) != 0)
  192. return false; // First 64 bit are not zero -> it is not ipv4-mapped-ipv6 address
  193. const ui64 Low = GetLow(Ip) >> 32;
  194. if (Low != 0x0000ffff)
  195. return false;
  196. return true;
  197. }
  198. TIpv6Address TIpv6Address::TryToExtractIpv4From6() const noexcept {
  199. if (Isv4MappedTov6() == false)
  200. return TIpv6Address();
  201. const ui64 NewLow = GetLow(Ip) & 0x00000000ffffffff;
  202. TIpv6Address Result(ui128(0, NewLow), Ipv4);
  203. return Result;
  204. }
  205. TIpv6Address TIpv6Address::Normalized() const noexcept {
  206. if (Isv4MappedTov6() == false)
  207. return *this;
  208. TIpv6Address Result = TryToExtractIpv4From6();
  209. Y_ABORT_UNLESS(Result.IsNull() == false);
  210. return Result;
  211. }
  212. IOutputStream& operator<<(IOutputStream& Out, const TIpv6Address::TIpType Type) noexcept {
  213. switch (Type) {
  214. case TIpv6Address::Ipv4:
  215. Out << "Ipv4";
  216. return Out;
  217. case TIpv6Address::Ipv6:
  218. Out << "Ipv6";
  219. return Out;
  220. default:
  221. Out << "UnknownType";
  222. return Out;
  223. }
  224. }
  225. IOutputStream& operator<<(IOutputStream& out, const TIpv6Address& ipv6Address) noexcept {
  226. bool ok;
  227. const TString& strIp = ipv6Address.ToString(&ok);
  228. if (!ok) {
  229. return out << "Can not convert ip to string";
  230. } else {
  231. return out << strIp;
  232. }
  233. }
  234. TString THostAddressAndPort::ToString() const noexcept {
  235. TStringStream Str;
  236. Str << *this;
  237. return Str.Str();
  238. }
  239. IOutputStream& operator<<(IOutputStream& Out, const THostAddressAndPort& HostAddressAndPort) noexcept {
  240. Out << HostAddressAndPort.Ip << ":" << HostAddressAndPort.Port;
  241. return Out;
  242. }
  243. namespace {
  244. class TRemoteAddr: public NAddr::IRemoteAddr {
  245. public:
  246. TRemoteAddr(const TIpv6Address& Address, TIpPort Port);
  247. const sockaddr* Addr() const override;
  248. socklen_t Len() const override;
  249. private:
  250. sockaddr_in SockAddrIPv4;
  251. sockaddr_in6 SockAddrIPv6;
  252. const sockaddr* SockAddrPtr = nullptr;
  253. socklen_t SockAddrSize = 0;
  254. };
  255. TRemoteAddr::TRemoteAddr(const TIpv6Address& Address, TIpPort Port) {
  256. Address.ToSockaddrAndSocklen(SockAddrIPv4, SockAddrIPv6, SockAddrPtr, SockAddrSize, Port);
  257. }
  258. const sockaddr* TRemoteAddr::Addr() const {
  259. return SockAddrPtr;
  260. }
  261. socklen_t TRemoteAddr::Len() const {
  262. return SockAddrSize;
  263. }
  264. }
  265. NAddr::IRemoteAddr* ToIRemoteAddr(const TIpv6Address& Address, TIpPort Port) {
  266. return new TRemoteAddr(Address, Port);
  267. }
  268. std::tuple<THostAddressAndPort, TString, TIpPort> ParseHostAndMayBePortFromString(const TString& RawStr,
  269. TIpPort DefaultPort,
  270. bool& Ok) noexcept {
  271. // Cout << "ParseHostAndMayBePortFromString: " << RawStr << ", Port: " << DefaultPort << Endl;
  272. using TRes = std::tuple<THostAddressAndPort, TString, TIpPort>;
  273. // ---------------------------------------------------------------------
  274. const size_t BracketColPos = RawStr.find("]:");
  275. if (BracketColPos != TString::npos) {
  276. // [ipv6]:port
  277. if (!RawStr.StartsWith('[')) {
  278. Ok = false;
  279. return {};
  280. }
  281. const TStringBuf StrIpv6(RawStr.begin() + 1, RawStr.begin() + BracketColPos);
  282. const TStringBuf StrPort(RawStr.begin() + BracketColPos + 2, RawStr.end());
  283. bool IpConverted;
  284. const TIpv6Address Ip = TIpv6Address::FromString(StrIpv6, IpConverted);
  285. if (!IpConverted) {
  286. Ok = false;
  287. return {};
  288. }
  289. if (Ip.Type() != TIpv6Address::Ipv6) {
  290. Ok = false;
  291. return {};
  292. }
  293. TIpPort Port {};
  294. if (!::TryFromString(StrPort, Port)) {
  295. Ok = false;
  296. return {};
  297. }
  298. Ok = true;
  299. TRes Res{{Ip, Port}, {}, {}};
  300. return Res;
  301. }
  302. // ---------------------------------------------------------------------
  303. if (RawStr.StartsWith('[')) {
  304. // [ipv6]
  305. if (!RawStr.EndsWith(']')) {
  306. Ok = false;
  307. return {};
  308. }
  309. const TStringBuf StrIpv6(RawStr.begin() + 1, RawStr.end() - 1);
  310. bool IpConverted;
  311. const TIpv6Address Ip = TIpv6Address::FromString(StrIpv6, IpConverted);
  312. if (!IpConverted || Ip.Type() != TIpv6Address::Ipv6) {
  313. Ok = false;
  314. return {};
  315. }
  316. Ok = true;
  317. TRes Res{{Ip, DefaultPort}, {}, {}};
  318. return Res;
  319. }
  320. // ---------------------------------------------------------------------
  321. const size_t ColPos = RawStr.find(':');
  322. if (ColPos != TString::npos) {
  323. // host:port
  324. // ipv4:port
  325. // ipv6
  326. {
  327. bool IpConverted;
  328. const TIpv6Address Ipv6 = TIpv6Address::FromString(RawStr, IpConverted);
  329. if (IpConverted && Ipv6.Type() == TIpv6Address::Ipv6) {
  330. // ipv6
  331. Ok = true;
  332. TRes Res{{Ipv6, DefaultPort}, {}, {}};
  333. return Res;
  334. }
  335. }
  336. const TStringBuf StrPort(RawStr.begin() + ColPos + 1, RawStr.end());
  337. TIpPort Port {};
  338. if (!::TryFromString(StrPort, Port)) {
  339. Ok = false;
  340. return {};
  341. }
  342. const TStringBuf StrIpv4OrHost(RawStr.begin(), RawStr.begin() + ColPos);
  343. {
  344. bool IpConverted;
  345. const TIpv6Address Ipv4 = TIpv6Address::FromString(StrIpv4OrHost, IpConverted);
  346. if (IpConverted && Ipv4.Type() == TIpv6Address::Ipv4) {
  347. // ipv4:port
  348. Ok = true;
  349. TRes Res{{Ipv4, Port}, {}, {}};
  350. return Res;
  351. }
  352. }
  353. {
  354. // host:port
  355. Ok = true;
  356. TRes Res{THostAddressAndPort{}, TString(StrIpv4OrHost), Port};
  357. return Res;
  358. }
  359. }
  360. // ---------------------------------------------------------------------
  361. {
  362. // ipv4
  363. bool IpConverted;
  364. const TIpv6Address Ipv4 = TIpv6Address::FromString(RawStr, IpConverted);
  365. if (IpConverted && Ipv4.Type() == TIpv6Address::Ipv4) {
  366. Ok = true;
  367. TRes Res{{Ipv4, DefaultPort}, {}, {}};
  368. return Res;
  369. }
  370. }
  371. // ---------------------------------------------------------------------
  372. {
  373. // host
  374. Ok = true;
  375. TRes Res{THostAddressAndPort{}, TString(RawStr), DefaultPort};
  376. return Res;
  377. }
  378. }