]> granicus.if.org Git - pgbouncer/commitdiff
Add resolv_conf option to set custom resolv.conf file
authorPeter Eisentraut <peter@eisentraut.org>
Fri, 27 Sep 2019 11:56:16 +0000 (13:56 +0200)
committerPeter Eisentraut <peter@eisentraut.org>
Fri, 27 Sep 2019 11:56:16 +0000 (13:56 +0200)
closes #379

doc/config.md
etc/pgbouncer.ini
include/bouncer.h
src/dnslookup.c
src/main.c

index f1c06b81deaa3179a2a4acfd6c702568e8f903c6..407fbb5c47a3d100131fc524e6a839a85813588b 100644 (file)
@@ -520,6 +520,20 @@ Works only with UDNS and c-ares backends (`--with-udns` or `--with-cares` to con
 
 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
 
index d72dedeebd97a748c77ac98719f735faf68d6dcc..867344b519b32d97761af4215fca19dd7159fcf6 100644 (file)
@@ -329,6 +329,10 @@ auth_file = /etc/pgbouncer/userlist.txt
 ;; DNS negative result caching time
 ;dns_nxdomain_ttl = 15
 
+;; Custom resolv.conf file, to set custom DNS servers or other options
+;; (default: empty = use OS settings)
+;resolv_conf = /etc/pgbouncer/resolv.conf
+
 ;;;
 ;;; Random stuff
 ;;;
index c1ead6a8f11c64e49aae3373a4202a9cf1d28258..e14cf34dff5aa0cfcd1587d92c43638ba6dc967b 100644 (file)
@@ -463,6 +463,7 @@ extern int cf_disable_pqexec;
 extern usec_t cf_dns_max_ttl;
 extern usec_t cf_dns_nxdomain_ttl;
 extern usec_t cf_dns_zone_check_period;
+extern char *cf_resolv_conf;
 
 extern int cf_auth_type;
 extern char *cf_auth_file;
index 6fefc71a848a0095d3e9cecc76af5ade24014d25..5519905b0baeaa5499b1684cfbbf8baade23af9d 100644 (file)
@@ -286,7 +286,14 @@ static void dns_signal(int f, short ev, void *arg)
 
 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);
@@ -367,12 +374,47 @@ const char *adns_get_backend(void)
        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;
 }
@@ -496,6 +538,11 @@ static bool impl_init(struct DNSContext *ctx)
        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);
@@ -907,6 +954,17 @@ static bool impl_init(struct DNSContext *ctx)
        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) {
index 3fe6e4a13380a02c48e5a7efc53cc1a94481f1bb..b96f14de234bd39ed3d12d62cae65e06ab4db5f5 100644 (file)
@@ -112,6 +112,7 @@ int cf_disable_pqexec;
 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;
@@ -260,6 +261,7 @@ CF_ABS("disable_pqexec", CF_INT, cf_disable_pqexec, CF_NO_RELOAD, "0"),
 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"),