]> git.ipfire.org Git - thirdparty/squid.git/commitdiff
Bug #1326: Use DNS search path from /etc/resolv.conf
authorhno <>
Mon, 26 Sep 2005 02:25:55 +0000 (02:25 +0000)
committerhno <>
Mon, 26 Sep 2005 02:25:55 +0000 (02:25 +0000)
patch by Thien Vu with fixes by "Paul".

src/cf.data.pre
src/dns_internal.cc
src/structs.h

index 985b7df1fb25206366abac39f26e0ffe9f861974..a46f6500befd77e134a02c11a9fd0bd5f964e5a2 100644 (file)
@@ -1,6 +1,6 @@
 
 #
-# $Id: cf.data.pre,v 1.395 2005/09/07 19:24:49 wessels Exp $
+# $Id: cf.data.pre,v 1.396 2005/09/25 20:25:55 hno Exp $
 #
 #
 # SQUID Web Proxy Cache          http://www.squid-cache.org/
@@ -1569,17 +1569,14 @@ DOC_END
 
 NAME: dns_defnames
 COMMENT: on|off
-IFDEF: USE_DNSSERVERS
 TYPE: onoff
 DEFAULT: off
 LOC: Config.onoff.res_defnames
-IFDEF: USE_DNSSERVERS
 DOC_START
-       Normally the 'dnsserver' disables the RES_DEFNAMES resolver
-       option (see res_init(3)).  This prevents caches in a hierarchy
+       Normally the RES_DEFNAMES resolver option is disabled
+       (see res_init(3)).  This prevents caches in a hierarchy
        from interpreting single-component hostnames locally.  To allow
-       dnsserver to handle single-component names, enable this
-       option.
+       Squid to handle single-component names, enable this option.
 DOC_END
 
 NAME: dns_nameservers
index 8b859cc79a804f8c55345b41d4054c3e99dc57b8..4f27cbe98a6722e0d8cde93b5cd33625657ef01c 100644 (file)
@@ -1,6 +1,6 @@
 
 /*
- * $Id: dns_internal.cc,v 1.82 2005/09/17 05:50:08 wessels Exp $
+ * $Id: dns_internal.cc,v 1.83 2005/09/25 20:25:56 hno Exp $
  *
  * DEBUG: section 78    DNS lookups; interacts with lib/rfc1035.c
  * AUTHOR: Duane Wessels
 #include "comm.h"
 #include "MemBuf.h"
 
-/* MS VisualStudio Projects are monolitich, so we need the following
+#include "config.h"
+
+#if HAVE_ARPA_NAMESER_H
+#include <arpa/nameser.h>
+#endif
+#if HAVE_RESOLV_H
+#include <resolv.h>
+#endif
+
+/* MS VisualStudio Projects are monolithic, so we need the following
    #ifndef to exclude the internal DNS code from compile process when
    using external DNS process.
  */
 #ifdef _SQUID_WIN32_
 #include "squid_windows.h"
 #endif
-#ifndef _PATH_RESOLV_CONF
-#define _PATH_RESOLV_CONF "/etc/resolv.conf"
+#ifndef _PATH_RESCONF
+#define _PATH_RESCONF "/etc/resolv.conf"
+#endif
+#ifndef NS_DEFAULTPORT
+#define NS_DEFAULTPORT 53
+#endif
+
+#ifndef NS_MAXDNAME
+#define NS_MAXDNAME 1025
+#endif
+
+#ifndef MAXDNSRCH
+#define MAXDNSRCH 6
 #endif
-#ifndef DOMAIN_PORT
-#define DOMAIN_PORT 53
+
+/* The buffer size required to store the maximum allowed search path */
+#ifndef RESOLV_BUFSZ
+#define RESOLV_BUFSZ NS_MAXDNAME * MAXDNSRCH + sizeof("search ") + 1
 #endif
 
 #define IDNS_MAX_TRIES 20
@@ -62,13 +84,17 @@ typedef struct _idns_query idns_query;
 
 typedef struct _ns ns;
 
+typedef struct _sp sp;
+
 typedef struct _nsvc nsvc;
 
 struct _idns_query
 {
     hash_link hash;
     rfc1035_query query;
-    char buf[512];
+    char buf[RESOLV_BUFSZ];
+    char name[NS_MAXDNAME + 1];
+    char orig[NS_MAXDNAME + 1];
     size_t sz;
     unsigned short id;
     int nsends;
@@ -84,6 +110,8 @@ struct _idns_query
     const char *error;
     int rcode;
     idns_query *queue;
+    unsigned short domain;
+    unsigned short do_searchpath;
 };
 
 struct _nsvc
@@ -107,18 +135,30 @@ struct _ns
     nsvc *vc;
 };
 
+struct _sp
+{
+    char domain[NS_MAXDNAME];
+    int queries;
+};
+
 CBDATA_TYPE(nsvc);
 
 static ns *nameservers = NULL;
+static sp *searchpath = NULL;
 static int nns = 0;
 static int nns_alloc = 0;
+static int npc = 0;
+static int npc_alloc = 0;
+static int ndots = 1;
 static dlink_list lru_list;
 static int event_queued = 0;
 static hash_table *idns_lookup_hash = NULL;
 
 static OBJH idnsStats;
 static void idnsAddNameserver(const char *buf);
+static void idnsAddPathComponent(const char *buf);
 static void idnsFreeNameservers(void);
+static void idnsFreeSearchpath(void);
 static void idnsParseNameservers(void);
 #ifndef _SQUID_MSWIN_
 static void idnsParseResolvConf(void);
@@ -126,6 +166,7 @@ static void idnsParseResolvConf(void);
 #ifdef _SQUID_WIN32_
 static void idnsParseWIN32Registry(void);
 #endif
+static void idnsCacheQuery(idns_query * q);
 static void idnsSendQuery(idns_query * q);
 static IOCB idnsReadVCHeader;
 
@@ -174,13 +215,41 @@ idnsAddNameserver(const char *buf)
 
     assert(nns < nns_alloc);
     nameservers[nns].S.sin_family = AF_INET;
-    nameservers[nns].S.sin_port = htons(DOMAIN_PORT);
+    nameservers[nns].S.sin_port = htons(NS_DEFAULTPORT);
     nameservers[nns].S.sin_addr.s_addr = A.s_addr;
     debug(78, 3) ("idnsAddNameserver: Added nameserver #%d: %s\n",
                   nns, inet_ntoa(nameservers[nns].S.sin_addr));
     nns++;
 }
 
+static void
+idnsAddPathComponent(const char *buf)
+{
+    if (npc == npc_alloc) {
+        int oldalloc = npc_alloc;
+        sp *oldptr = searchpath;
+
+        if (0 == npc_alloc)
+            npc_alloc = 2;
+        else
+            npc_alloc <<= 1;
+
+        searchpath = (sp *)xcalloc(npc_alloc, sizeof(*searchpath));
+
+        if (oldptr && oldalloc)
+            xmemcpy(searchpath, oldptr, oldalloc * sizeof(*searchpath));
+
+        if (oldptr)
+            safe_free(oldptr);
+    }
+
+    assert(npc < npc_alloc);
+    strcpy(searchpath[npc].domain, buf);
+    debug(78, 3) ("idnsAddPathComponent: Added domain #%d: %s\n",
+                  npc, searchpath[npc].domain);
+    npc++;
+}
+
 static void
 idnsFreeNameservers(void)
 {
@@ -188,6 +257,15 @@ idnsFreeNameservers(void)
     nns = nns_alloc = 0;
 }
 
+static void
+idnsFreeSearchpath(void)
+{
+    safe_free(searchpath);
+    npc = npc_alloc = 0;
+}
+
+
+
 static void
 idnsParseNameservers(void)
 {
@@ -204,12 +282,12 @@ static void
 idnsParseResolvConf(void)
 {
     FILE *fp;
-    char buf[512];
+    char buf[RESOLV_BUFSZ];
     char *t;
-    fp = fopen(_PATH_RESOLV_CONF, "r");
+    fp = fopen(_PATH_RESCONF, "r");
 
     if (fp == NULL) {
-        debug(78, 1) ("%s: %s\n", _PATH_RESOLV_CONF, xstrerror());
+        debug(78, 1) ("%s: %s\n", _PATH_RESCONF, xstrerror());
         return;
     }
 
@@ -218,23 +296,48 @@ idnsParseResolvConf(void)
 
 #endif
 
-    while (fgets(buf, 512, fp)) {
+    while (fgets(buf, RESOLV_BUFSZ, fp)) {
         t = strtok(buf, w_space);
 
-        if (NULL == t)
+        if (NULL == t) {
             continue;
+        } else if (strcasecmp(t, "nameserver") == 0) {
+            t = strtok(NULL, w_space);
 
-        if (strcasecmp(t, "nameserver"))
-            continue;
+            if (NULL == t)
+                continue;
 
-        t = strtok(NULL, w_space);
+            debug(78, 1) ("Adding nameserver %s from %s\n", t, _PATH_RESCONF);
 
-        if (t == NULL)
-            continue;
+            idnsAddNameserver(t);
+        } else if (strcasecmp(t, "search") == 0) {
+            while (NULL != t) {
+                t = strtok(NULL, w_space);
+
+                if (NULL == t)
+                    continue;
+
+                debug(78, 1) ("Adding domain %s from %s\n", t, _PATH_RESCONF);
+
+                idnsAddPathComponent(t);
+            }
+        } else if (strcasecmp(t, "options") == 0) {
+            while (NULL != t) {
+                t = strtok(NULL, w_space);
 
-        debug(78, 1) ("Adding nameserver %s from %s\n", t, _PATH_RESOLV_CONF);
+                if (NULL == t)
+                    continue;
 
-        idnsAddNameserver(t);
+                if (strncmp(t, "ndots:", 6) != 0) {
+                    ndots = atoi(t + 6);
+
+                    if (ndots < 1)
+                        ndots = 1;
+
+                    debug(78, 1) ("Adding ndots %d from %s\n", ndots, _PATH_RESCONF);
+                }
+            }
+        }
     }
 
     fclose(fp);
@@ -808,6 +911,32 @@ idnsGrokReply(const char *buf, size_t sz)
             idnsSendQuery(q);
             return;
         }
+
+        if (q->rcode == 3 && q->do_searchpath && q->attempt < MAX_ATTEMPT) {
+            assert(NULL == message->answer);
+            strcpy(q->name, q->orig);
+
+            if (q->domain < npc) {
+                strcat(q->name, ".");
+                strcat(q->name, searchpath[q->domain].domain);
+                debug(78, 3) ("idnsGrokReply: searchpath used for %s\n",
+                              q->name);
+                q->domain++;
+            } else {
+                q->attempt++;
+            }
+
+            rfc1035MessageDestroy(message);
+            q->start_t = current_time;
+            q->id = idnsQueryID();
+            rfc1035SetQueryID(q->buf, q->id);
+            q->sz = rfc1035BuildAQuery(q->name, q->buf, sizeof(q->buf), q->id,
+                                       &q->query);
+
+            idnsCacheQuery(q);
+            idnsSendQuery(q);
+            return;
+        }
     }
 
     idnsCallback(q, message->answer, n, q->error);
@@ -1090,6 +1219,8 @@ idnsShutdown(void)
     DnsSocket = -1;
 
     idnsFreeNameservers();
+
+    idnsFreeSearchpath();
 }
 
 static int
@@ -1125,6 +1256,8 @@ idnsCacheQuery(idns_query *q)
 void
 idnsALookup(const char *name, IDNSCB * callback, void *data)
 {
+    unsigned int i;
+    int nd = 0;
     idns_query *q;
 
     if (idnsCachedLookup(name, callback, data))
@@ -1134,7 +1267,29 @@ idnsALookup(const char *name, IDNSCB * callback, void *data)
 
     q->id = idnsQueryID();
 
-    q->sz = rfc1035BuildAQuery(name, q->buf, sizeof(q->buf), q->id, &q->query);
+    for (i = 0; i < strlen(name); i++)
+        if (name[i] == '.')
+            nd++;
+
+    if (Config.onoff.res_defnames && npc > 0 && name[strlen(name)-1] != '.') {
+        q->do_searchpath = 1;
+    } else {
+        q->do_searchpath = 0;
+    }
+
+    strcpy(q->orig, name);
+    strcpy(q->name, q->orig);
+
+    if (q->do_searchpath && nd < ndots) {
+        q->domain = 0;
+        strcat(q->name, ".");
+        strcat(q->name, searchpath[q->domain].domain);
+        debug(78, 3) ("idnsALookup: searchpath used for %s\n",
+                      q->name);
+    }
+
+    q->sz = rfc1035BuildAQuery(q->name, q->buf, sizeof(q->buf), q->id,
+                               &q->query);
 
     if (q->sz < 0) {
         /* problem with query data -- query not sent */
@@ -1144,7 +1299,7 @@ idnsALookup(const char *name, IDNSCB * callback, void *data)
     }
 
     debug(78, 3) ("idnsALookup: buf is %d bytes for %s, id = %#hx\n",
-                  (int) q->sz, name, q->id);
+                  (int) q->sz, q->name, q->id);
 
     q->callback = callback;
 
index bd206c85768ea51ef8cd1eb3421a605fc41525f7..a9d2b5dcf394c8fa8175e6ed6a2057e3bb0807c1 100644 (file)
@@ -1,6 +1,6 @@
 
 /*
- * $Id: structs.h,v 1.528 2005/09/17 04:53:44 wessels Exp $
+ * $Id: structs.h,v 1.529 2005/09/25 20:25:56 hno Exp $
  *
  *
  * SQUID Web Proxy Cache          http://www.squid-cache.org/
@@ -523,11 +523,7 @@ struct _SquidConfig
     struct
     {
         int log_udp;
-#if USE_DNSSERVERS
-
         int res_defnames;
-#endif
-
         int anonymizer;
         int client_db;
         int query_icmp;