diff --git a/ydb/core/driver_lib/run/kikimr_services_initializers.cpp b/ydb/core/driver_lib/run/kikimr_services_initializers.cpp index 8ac8c7fdbcc5..c9c2f36b07e8 100644 --- a/ydb/core/driver_lib/run/kikimr_services_initializers.cpp +++ b/ydb/core/driver_lib/run/kikimr_services_initializers.cpp @@ -565,6 +565,7 @@ void TBasicServicesInitializer::InitializeServices(NActors::TActorSystemSetup* s resolverOptions.Type = NDnsResolver::EDnsResolverType::Libc; break; } + resolverOptions.AddTrailingDot = nsConfig.GetAddTrailingDot(); IActor *resolver = NDnsResolver::CreateOnDemandDnsResolver(resolverOptions); setup->LocalServices.emplace_back( diff --git a/ydb/core/protos/config.proto b/ydb/core/protos/config.proto index 0778bc29f56e..43017fcefb93 100644 --- a/ydb/core/protos/config.proto +++ b/ydb/core/protos/config.proto @@ -183,6 +183,7 @@ message TStaticNameserviceConfig { optional bool KeepSocket = 6 [default = true]; optional bool ForceTcp = 7 [default = false]; optional EDnsResolverType DnsResolverType = 8 [default = ARES]; + optional bool AddTrailingDot = 9 [default = false]; } message TDynamicNameserviceConfig { diff --git a/ydb/library/actors/dnsresolver/dnsresolver.cpp b/ydb/library/actors/dnsresolver/dnsresolver.cpp index 17f212691ab1..af4a6109e317 100644 --- a/ydb/library/actors/dnsresolver/dnsresolver.cpp +++ b/ydb/library/actors/dnsresolver/dnsresolver.cpp @@ -130,6 +130,13 @@ namespace NDnsResolver { std::atomic Activations{ 0 }; }; + static TString AddTrailingDot(TString&& name, bool addTrailingDot) noexcept { + if (addTrailingDot && !name.empty() && name.back() != '.') { + name += "."; + } + return name; + } + class TAresDnsResolver : public TActor , private TAresLibraryInitBase @@ -290,6 +297,7 @@ namespace NDnsResolver { memset(&hints, 0, sizeof(hints)); hints.ai_flags = ARES_AI_NOSORT; hints.ai_family = family; + name = AddTrailingDot(std::move(name), reqCtx->Self->Options.AddTrailingDot); ares_getaddrinfo(AresChannel, name.c_str(), nullptr, &hints, &TThis::GetAddrInfoAresCallback, reqCtx.Get()); } @@ -533,6 +541,7 @@ namespace NDnsResolver { private: std::unique_ptr GetHostByName(TString name, int family) { + name = AddTrailingDot(std::move(name), Options.AddTrailingDot); auto result = std::make_unique(); struct addrinfo hints, *res; diff --git a/ydb/library/actors/dnsresolver/dnsresolver.h b/ydb/library/actors/dnsresolver/dnsresolver.h index 9ef373dd053a..73ac336992b6 100644 --- a/ydb/library/actors/dnsresolver/dnsresolver.h +++ b/ydb/library/actors/dnsresolver/dnsresolver.h @@ -100,6 +100,8 @@ namespace NDnsResolver { bool KeepSocket = true; // Force tcp to perform dns requests bool ForceTcp = false; + // Add trailing dot to hostname + bool AddTrailingDot = false; }; IActor* CreateSimpleDnsResolver(TSimpleDnsResolverOptions options = TSimpleDnsResolverOptions()); diff --git a/ydb/library/actors/dnsresolver/dnsresolver_ut.cpp b/ydb/library/actors/dnsresolver/dnsresolver_ut.cpp index c62ca6ef5803..021de04cb46d 100644 --- a/ydb/library/actors/dnsresolver/dnsresolver_ut.cpp +++ b/ydb/library/actors/dnsresolver/dnsresolver_ut.cpp @@ -29,50 +29,56 @@ Y_UNIT_TEST_SUITE(DnsResolver) { }; Y_UNIT_TEST(ResolveLocalHost) { - for (auto type : { EDnsResolverType::Ares, EDnsResolverType::Libc }) { - TSimpleDnsResolverOptions options { .Type = type }; - TTestActorRuntimeBase runtime; - runtime.Initialize(); - auto sender = runtime.AllocateEdgeActor(); - auto resolver = runtime.Register(CreateSimpleDnsResolver(options)); - runtime.Send(new IEventHandle(resolver, sender, new TEvDns::TEvGetHostByName("localhost", AF_UNSPEC)), - 0, true); - auto ev = runtime.GrabEdgeEventRethrow(sender); - UNIT_ASSERT_VALUES_EQUAL_C(ev->Get()->Status, 0, ev->Get()->ErrorText); - size_t addrs = ev->Get()->AddrsV4.size() + ev->Get()->AddrsV6.size(); - UNIT_ASSERT_C(addrs > 0, "Got " << addrs << " addresses"); + for (auto addTrailingDot : { true, false }) { + for (auto type : { EDnsResolverType::Ares, EDnsResolverType::Libc }) { + TSimpleDnsResolverOptions options { .Type = type, .AddTrailingDot = addTrailingDot }; + TTestActorRuntimeBase runtime; + runtime.Initialize(); + auto sender = runtime.AllocateEdgeActor(); + auto resolver = runtime.Register(CreateSimpleDnsResolver(options)); + runtime.Send(new IEventHandle(resolver, sender, new TEvDns::TEvGetHostByName("localhost", AF_UNSPEC)), + 0, true); + auto ev = runtime.GrabEdgeEventRethrow(sender); + UNIT_ASSERT_VALUES_EQUAL_C(ev->Get()->Status, 0, ev->Get()->ErrorText); + size_t addrs = ev->Get()->AddrsV4.size() + ev->Get()->AddrsV6.size(); + UNIT_ASSERT_C(addrs > 0, "Got " << addrs << " addresses"); + } } } Y_UNIT_TEST(ResolveYandexRu) { - for (auto type : { EDnsResolverType::Ares, EDnsResolverType::Libc }) { - TSimpleDnsResolverOptions options { .Type = type }; - TTestActorRuntimeBase runtime; - runtime.Initialize(); - auto sender = runtime.AllocateEdgeActor(); - auto resolver = runtime.Register(CreateSimpleDnsResolver(options)); - runtime.Send(new IEventHandle(resolver, sender, new TEvDns::TEvGetHostByName("yandex.ru", AF_UNSPEC)), - 0, true); - auto ev = runtime.GrabEdgeEventRethrow(sender); - UNIT_ASSERT_VALUES_EQUAL_C(ev->Get()->Status, 0, ev->Get()->ErrorText); - size_t addrs = ev->Get()->AddrsV4.size() + ev->Get()->AddrsV6.size(); - UNIT_ASSERT_C(addrs > 0, "Got " << addrs << " addresses"); + for (auto addTrailingDot : { true, false }) { + for (auto type : { EDnsResolverType::Ares, EDnsResolverType::Libc }) { + TSimpleDnsResolverOptions options { .Type = type, .AddTrailingDot = addTrailingDot }; + TTestActorRuntimeBase runtime; + runtime.Initialize(); + auto sender = runtime.AllocateEdgeActor(); + auto resolver = runtime.Register(CreateSimpleDnsResolver(options)); + runtime.Send(new IEventHandle(resolver, sender, new TEvDns::TEvGetHostByName("yandex.ru", AF_UNSPEC)), + 0, true); + auto ev = runtime.GrabEdgeEventRethrow(sender); + UNIT_ASSERT_VALUES_EQUAL_C(ev->Get()->Status, 0, ev->Get()->ErrorText); + size_t addrs = ev->Get()->AddrsV4.size() + ev->Get()->AddrsV6.size(); + UNIT_ASSERT_C(addrs > 0, "Got " << addrs << " addresses"); + } } } Y_UNIT_TEST(GetAddrYandexRu) { - for (auto type : { EDnsResolverType::Ares, EDnsResolverType::Libc }) { - TSimpleDnsResolverOptions options { .Type = type }; - TTestActorRuntimeBase runtime; - runtime.Initialize(); - auto sender = runtime.AllocateEdgeActor(); - auto resolver = runtime.Register(CreateSimpleDnsResolver(options)); + for (auto addTrailingDot : { true, false }) { + for (auto type : { EDnsResolverType::Ares, EDnsResolverType::Libc }) { + TSimpleDnsResolverOptions options { .Type = type, .AddTrailingDot = addTrailingDot }; + TTestActorRuntimeBase runtime; + runtime.Initialize(); + auto sender = runtime.AllocateEdgeActor(); + auto resolver = runtime.Register(CreateSimpleDnsResolver(options)); - runtime.Send(new IEventHandle(resolver, sender, new TEvDns::TEvGetAddr("yandex.ru", AF_UNSPEC)), - 0, true); - auto ev = runtime.GrabEdgeEventRethrow(sender); - UNIT_ASSERT_VALUES_EQUAL_C(ev->Get()->Status, 0, ev->Get()->ErrorText); - UNIT_ASSERT_C(ev->Get()->IsV4() || ev->Get()->IsV6(), "Expect v4 or v6 address"); + runtime.Send(new IEventHandle(resolver, sender, new TEvDns::TEvGetAddr("yandex.ru", AF_UNSPEC)), + 0, true); + auto ev = runtime.GrabEdgeEventRethrow(sender); + UNIT_ASSERT_VALUES_EQUAL_C(ev->Get()->Status, 0, ev->Get()->ErrorText); + UNIT_ASSERT_C(ev->Get()->IsV4() || ev->Get()->IsV6(), "Expect v4 or v6 address"); + } } }