1
#pragma once
2

            
3
#include "envoy/config/bootstrap/v3/bootstrap.pb.h"
4
#include "envoy/config/cluster/v3/cluster.pb.h"
5
#include "envoy/extensions/common/dynamic_forward_proxy/v3/dns_cache.pb.h"
6
#include "envoy/extensions/filters/udp/dns_filter/v3/dns_filter.pb.h"
7
#include "envoy/extensions/network/dns_resolver/apple/v3/apple_dns_resolver.pb.h"
8
#include "envoy/extensions/network/dns_resolver/cares/v3/cares_dns_resolver.pb.h"
9
#include "envoy/network/dns_resolver.h"
10

            
11
#include "source/common/runtime/runtime_features.h"
12

            
13
namespace Envoy {
14
namespace Network {
15

            
16
// Create a default c-ares DNS resolver typed config.
17
void makeDefaultCaresDnsResolverConfig(
18
    envoy::config::core::v3::TypedExtensionConfig& typed_dns_resolver_config);
19

            
20
// Create a default apple DNS resolver typed config.
21
void makeDefaultAppleDnsResolverConfig(
22
    envoy::config::core::v3::TypedExtensionConfig& typed_dns_resolver_config);
23

            
24
// Create a default DNS resolver typed config based on build system and configuration.
25
void makeDefaultDnsResolverConfig(
26
    envoy::config::core::v3::TypedExtensionConfig& typed_dns_resolver_config);
27

            
28
// If it is MacOS and it's compiled it, create an AppleDnsResolverConfig typed config.
29
bool tryUseAppleApiForDnsLookups(
30
    envoy::config::core::v3::TypedExtensionConfig& typed_dns_resolver_config);
31

            
32
// If the config has typed_dns_resolver_config, copy it over.
33
template <class ConfigType>
34
bool checkTypedDnsResolverConfigExist(
35
    const ConfigType& config,
36
329
    envoy::config::core::v3::TypedExtensionConfig& typed_dns_resolver_config) {
37
329
  if (config.has_typed_dns_resolver_config()) {
38
180
    typed_dns_resolver_config.MergeFrom(config.typed_dns_resolver_config());
39
180
    return true;
40
180
  }
41
149
  return false;
42
329
}
43

            
44
// If the config has dns_resolution_config, create a CaresDnsResolverConfig typed config based on
45
// it.
46
template <class ConfigType>
47
bool checkDnsResolutionConfigExist(
48
    const ConfigType& config,
49
150
    envoy::config::core::v3::TypedExtensionConfig& typed_dns_resolver_config) {
50
150
  if (config.has_dns_resolution_config()) {
51
24
    envoy::extensions::network::dns_resolver::cares::v3::CaresDnsResolverConfig cares;
52
24
    if (!config.dns_resolution_config().resolvers().empty()) {
53
22
      cares.mutable_resolvers()->MergeFrom(config.dns_resolution_config().resolvers());
54
22
    }
55
24
    cares.mutable_dns_resolver_options()->MergeFrom(
56
24
        config.dns_resolution_config().dns_resolver_options());
57
24
    typed_dns_resolver_config.mutable_typed_config()->PackFrom(cares);
58
24
    typed_dns_resolver_config.set_name(std::string(CaresDnsResolver));
59
24
    return true;
60
24
  }
61
126
  return false;
62
150
}
63

            
64
// For backward compatibility, copy over use_tcp_for_dns_lookups from config, and create
65
// a CaresDnsResolverConfig typed config. This logic fit for bootstrap, and dns_cache config types.
66
template <class ConfigType>
67
void handleLegacyDnsResolverData(
68
    const ConfigType& config,
69
122
    envoy::config::core::v3::TypedExtensionConfig& typed_dns_resolver_config) {
70
122
  envoy::extensions::network::dns_resolver::cares::v3::CaresDnsResolverConfig cares;
71
122
  cares.mutable_dns_resolver_options()->set_use_tcp_for_dns_lookups(
72
122
      config.use_tcp_for_dns_lookups());
73
122
  typed_dns_resolver_config.mutable_typed_config()->PackFrom(cares);
74
122
  typed_dns_resolver_config.set_name(std::string(CaresDnsResolver));
75
122
}
76

            
77
// Overloading the template function for DnsFilterConfig type, which doesn't need to copy anything.
78
void handleLegacyDnsResolverData(
79
    const envoy::extensions::filters::udp::dns_filter::v3::DnsFilterConfig::ClientContextConfig&,
80
    envoy::config::core::v3::TypedExtensionConfig& typed_dns_resolver_config);
81

            
82
// Overloading the template function for Cluster config type, which need to copy
83
// both use_tcp_for_dns_lookups and dns_resolvers.
84
void handleLegacyDnsResolverData(
85
    const envoy::config::cluster::v3::Cluster& config,
86
    envoy::config::core::v3::TypedExtensionConfig& typed_dns_resolver_config);
87

            
88
// Make typed_dns_resolver_config from the passed @param config.
89
template <class ConfigType>
90
327
envoy::config::core::v3::TypedExtensionConfig makeDnsResolverConfig(const ConfigType& config) {
91
327
  envoy::config::core::v3::TypedExtensionConfig typed_dns_resolver_config;
92

            
93
  // typed_dns_resolver_config takes precedence
94
327
  if (checkTypedDnsResolverConfigExist(config, typed_dns_resolver_config)) {
95
178
    return typed_dns_resolver_config;
96
178
  }
97

            
98
  // If use apple API for DNS lookups, create an AppleDnsResolverConfig typed config.
99
149
  if (tryUseAppleApiForDnsLookups(typed_dns_resolver_config)) {
100
    return typed_dns_resolver_config;
101
  }
102

            
103
  // If dns_resolution_config exits, create a CaresDnsResolverConfig typed config based on it.
104
149
  if (checkDnsResolutionConfigExist(config, typed_dns_resolver_config)) {
105
23
    return typed_dns_resolver_config;
106
23
  }
107

            
108
  // Handle legacy DNS resolver fields for backward compatibility.
109
  // Different config type has different fields to copy.
110
126
  handleLegacyDnsResolverData(config, typed_dns_resolver_config);
111
126
  return typed_dns_resolver_config;
112
149
}
113

            
114
// Create the DNS resolver factory from the typed config. This is the underline
115
// function which performs the registry lookup based on typed config.
116
Network::DnsResolverFactory& createDnsResolverFactoryFromTypedConfig(
117
    const envoy::config::core::v3::TypedExtensionConfig& typed_dns_resolver_config);
118

            
119
// Create the default DNS resolver factory. apple for MacOS or c-ares for all others.
120
// The default registry lookup will always succeed, thus no exception throwing.
121
// This function can be called in main or worker threads.
122
Network::DnsResolverFactory& createDefaultDnsResolverFactory(
123
    envoy::config::core::v3::TypedExtensionConfig& typed_dns_resolver_config);
124

            
125
// Create the DNS resolver factory from the proto config.
126
// The passed in config parameter may contain invalid typed_dns_resolver_config.
127
// In that case, the underline registry lookup will throw an exception.
128
// This function has to be called in main thread.
129
template <class ConfigType>
130
Network::DnsResolverFactory& createDnsResolverFactoryFromProto(
131
    const ConfigType& config,
132
326
    envoy::config::core::v3::TypedExtensionConfig& typed_dns_resolver_config) {
133
326
  ASSERT_IS_MAIN_OR_TEST_THREAD();
134
326
  typed_dns_resolver_config = makeDnsResolverConfig(config);
135
326
  return createDnsResolverFactoryFromTypedConfig(typed_dns_resolver_config);
136
326
}
137

            
138
} // namespace Network
139
} // namespace Envoy