diff --git a/include/fluent-bit/flb_config.h b/include/fluent-bit/flb_config.h index af699c44a6c..84bbc5ff1c3 100644 --- a/include/fluent-bit/flb_config.h +++ b/include/fluent-bit/flb_config.h @@ -174,6 +174,9 @@ struct flb_config { */ char *no_proxy; + /* DNS */ + char *dns_mode; + /* Chunk I/O Buffering */ void *cio; char *storage_path; @@ -273,6 +276,9 @@ enum conf_type { #define FLB_CONF_STR_HC_PERIOD "HC_Period" #endif /* !FLB_HAVE_HTTP_SERVER */ +/* DNS */ +#define FLB_CONF_DNS_MODE "dns.mode" + /* Storage / Chunk I/O */ #define FLB_CONF_STORAGE_PATH "storage.path" #define FLB_CONF_STORAGE_SYNC "storage.sync" diff --git a/include/fluent-bit/flb_network.h b/include/fluent-bit/flb_network.h index ab79a01ce5b..b751b887f65 100644 --- a/include/fluent-bit/flb_network.h +++ b/include/fluent-bit/flb_network.h @@ -43,6 +43,9 @@ struct flb_net_setup { /* maximum of times a keepalive connection can be used */ int keepalive_max_recycle; + + /* dns mode : FLB_DNS_USE_TCP, FLB_DNS_USE_UDP */ + char *dns_mode; }; /* Defines a host service and it properties */ @@ -76,6 +79,9 @@ struct flb_dns_lookup_context { /* result is a synthetized result, don't call freeaddrinfo on it */ }; +#define FLB_DNS_USE_TCP 'T' +#define FLB_DNS_USE_UDP 'U' + #ifndef TCP_FASTOPEN #define TCP_FASTOPEN 23 #endif diff --git a/src/flb_config.c b/src/flb_config.c index 13da8befd9c..0bf5e49c793 100644 --- a/src/flb_config.c +++ b/src/flb_config.c @@ -106,6 +106,10 @@ struct flb_service_config service_configs[] = { offsetof(struct flb_config, health_check_period)}, #endif + /* DNS*/ + {FLB_CONF_DNS_MODE, + FLB_CONF_TYPE_STR, + offsetof(struct flb_config, dns_mode)}, /* Storage */ {FLB_CONF_STORAGE_PATH, diff --git a/src/flb_network.c b/src/flb_network.c index 849183af5c7..a10ccdeb18b 100644 --- a/src/flb_network.c +++ b/src/flb_network.c @@ -67,6 +67,7 @@ void flb_net_init() void flb_net_setup_init(struct flb_net_setup *net) { + net->dns_mode = NULL; net->keepalive = FLB_TRUE; net->keepalive_idle_timeout = 30; net->keepalive_max_recycle = 0; @@ -602,7 +603,8 @@ static int flb_net_ares_sock_create_callback(ares_socket_t socket_fd, } struct flb_dns_lookup_context *flb_net_dns_lookup_context_create(struct mk_event_loop *evl, - struct flb_coro *coroutine) + struct flb_coro *coroutine, + char dns_mode) { int result; int optmask = 0; @@ -620,9 +622,12 @@ struct flb_dns_lookup_context *flb_net_dns_lookup_context_create(struct mk_event /* c-ares options: make sure it uses TCP and limit number of tries to 2 */ optmask = ARES_OPT_FLAGS; - opts.flags = ARES_FLAG_USEVC; opts.tries = 2; + if (dns_mode == FLB_DNS_USE_TCP) { + opts.flags = ARES_FLAG_USEVC; + } + result = ares_init_options((ares_channel *) &context->ares_channel, &opts, optmask); @@ -651,18 +656,26 @@ void flb_net_dns_lookup_context_destroy(struct flb_dns_lookup_context *context) int flb_net_getaddrinfo(const char *node, const char *service, struct addrinfo *hints, - struct addrinfo **res) + struct addrinfo **res, char *dns_mode_textual) { struct flb_dns_lookup_context *lookup_context; struct ares_addrinfo_hints ares_hints; struct mk_event_loop *event_loop; struct flb_coro *coroutine; + char dns_mode; int result; + dns_mode = FLB_DNS_USE_UDP; + + if (dns_mode_textual != NULL && + strncasecmp(dns_mode_textual, "TCP", 3) == 0) { + dns_mode = FLB_DNS_USE_TCP; + } + event_loop = flb_engine_evl_get(); coroutine = flb_coro_get(); - lookup_context = flb_net_dns_lookup_context_create(event_loop, coroutine); + lookup_context = flb_net_dns_lookup_context_create(event_loop, coroutine, dns_mode); if (!lookup_context) { return EAI_AGAIN; @@ -774,7 +787,7 @@ flb_sockfd_t flb_net_tcp_connect(const char *host, unsigned long port, /* retrieve DNS info */ if (is_async) { - ret = flb_net_getaddrinfo(host, _port, &hints, &res); + ret = flb_net_getaddrinfo(host, _port, &hints, &res, u_conn->u->net.dns_mode); } else { ret = getaddrinfo(host, _port, &hints, &res); diff --git a/src/flb_upstream.c b/src/flb_upstream.c index 9ae0b796e98..e734161cf21 100644 --- a/src/flb_upstream.c +++ b/src/flb_upstream.c @@ -34,6 +34,12 @@ FLB_TLS_DEFINE(struct mk_list, flb_upstream_list_key); /* Config map for Upstream networking setup */ struct flb_config_map upstream_net[] = { + { + FLB_CONFIG_MAP_STR, "net.dns_mode", NULL, + 0, FLB_TRUE, offsetof(struct flb_net_setup, dns_mode), + "Select the primary DNS connection type (TCP or UDP)" + }, + { FLB_CONFIG_MAP_BOOL, "net.keepalive", "true", 0, FLB_TRUE, offsetof(struct flb_net_setup, keepalive), @@ -90,9 +96,28 @@ void flb_upstream_thread_safe(struct flb_upstream *u) struct mk_list *flb_upstream_get_config_map(struct flb_config *config) { + size_t config_index; struct mk_list *config_map; + /* If a global dns mode was provided in the SERVICE category then we set it as + * the default value for net.dns_mode, that way the user can set a global value and + * override it on a per plugin basis, however, it's not because of this flexibility + * that it was done but because in order to be able to save the value in the + * flb_net_setup structure (and not lose it when flb_output_upstream_set overwrites + * the structure) we need to do it this way (or at least that's what I think) + */ + if (config->dns_mode != NULL) { + + for (config_index = 0 ; upstream_net[config_index].name != NULL ; config_index++) { + if(strcmp(upstream_net[config_index].name, "net.dns_mode") == 0) + { + upstream_net[config_index].def_value = config->dns_mode; + } + } + } + config_map = flb_config_map_create(config, upstream_net); + return config_map; } @@ -238,6 +263,7 @@ struct flb_upstream *flb_upstream_create(struct flb_config *config, #endif mk_list_add(&u->_head, &config->upstreams); + return u; }