Default: 0.0 (disabled)
+### resolv_conf
+
+The location of a custom `resolv.conf` file. This is to allow
+specifying custom DNS servers and perhaps other name resolution
+options, independent of the global operating system configuration.
+
+Requires evdns (>= 2.0.3) or c-ares (>= 1.15.0) backend.
+
+The parsing of the file is done by the DNS backend library, not
+PgBouncer, so see the library's documentation for details on allowed
+syntax and directives.
+
+Default: empty (use operating system defaults)
+
## TLS settings
static bool impl_init(struct DNSContext *ctx)
{
- struct GaiContext *gctx = calloc(1, sizeof(*gctx));
+ struct GaiContext *gctx;
+
+ if (cf_resolv_conf && cf_resolv_conf[0]) {
+ log_error("resolv_conf setting is not supported by libc adns");
+ return false;
+ }
+
+ gctx = calloc(1, sizeof(*gctx));
if (!gctx)
return false;
list_init(&gctx->gairq_list);
return "evdns2";
}
+/*
+ * Confusingly, this is not the same as evdns_err_to_string().
+ */
+static const char *_evdns_base_resolv_conf_parse_err_to_string(int err)
+{
+ switch (err) {
+ case 0: return "no error";
+ case 1: return "failed to open file";
+ case 2: return "failed to stat file";
+ case 3: return "file too large";
+ case 4: return "out of memory";
+ case 5: return "short read from file";
+ case 6: return "no nameservers listed in the file";
+ default: return "[Unknown error code]";
+ }
+}
+
static bool impl_init(struct DNSContext *ctx)
{
- ctx->edns = evdns_base_new(NULL, 1);
- if (!ctx->edns) {
- log_error("evdns_base_new failed");
- return false;
+ if (cf_resolv_conf && cf_resolv_conf[0]) {
+ int err;
+
+ ctx->edns = evdns_base_new(NULL, 0);
+ if (!ctx->edns) {
+ log_error("evdns_base_new failed");
+ return false;
+ }
+ err = evdns_base_resolv_conf_parse(ctx->edns, DNS_OPTIONS_ALL,
+ cf_resolv_conf);
+ if (err) {
+ log_error("evdns parsing of \"%s\" failed: %s",
+ cf_resolv_conf,
+ _evdns_base_resolv_conf_parse_err_to_string(err));
+ return false;
+ }
+ } else {
+ ctx->edns = evdns_base_new(NULL, 1);
+ if (!ctx->edns) {
+ log_error("evdns_base_new failed");
+ return false;
+ }
}
return true;
}
struct UdnsMeta *udns;
int err;
+ if (cf_resolv_conf && cf_resolv_conf[0]) {
+ log_error("resolv_conf setting is not supported by udns");
+ return false;
+ }
+
dns_init(NULL, 0);
dctx = dns_new(NULL);
opts.sock_state_cb = xares_state_cb;
opts.sock_state_cb_data = ctx;
mask = ARES_OPT_SOCK_STATE_CB;
+ if (cf_resolv_conf && cf_resolv_conf[0]) {
+#ifdef ARES_OPT_RESOLVCONF
+ opts.resolvconf_path = strdup(cf_resolv_conf);
+ if (!opts.resolvconf_path)
+ return false;
+ mask |= ARES_OPT_RESOLVCONF;
+#else
+ log_error("resolv_conf setting is not supported by this version of c-ares");
+ return false;
+#endif
+ }
err = ares_init_options(&meta->chan, &opts, mask);
if (err) {
usec_t cf_dns_max_ttl;
usec_t cf_dns_nxdomain_ttl;
usec_t cf_dns_zone_check_period;
+char *cf_resolv_conf;
unsigned int cf_max_packet_size;
char *cf_ignore_startup_params;
CF_ABS("dns_max_ttl", CF_TIME_USEC, cf_dns_max_ttl, 0, "15"),
CF_ABS("dns_nxdomain_ttl", CF_TIME_USEC, cf_dns_nxdomain_ttl, 0, "15"),
CF_ABS("dns_zone_check_period", CF_TIME_USEC, cf_dns_zone_check_period, 0, "0"),
+CF_ABS("resolv_conf", CF_STR, cf_resolv_conf, CF_NO_RELOAD, ""),
CF_ABS("max_packet_size", CF_UINT, cf_max_packet_size, 0, "2147483647"),
CF_ABS("pkt_buf", CF_INT, cf_sbuf_len, CF_NO_RELOAD, "4096"),