diff -ru src.orig/cf.data.pre src/cf.data.pre --- src.orig/cf.data.pre Wed Apr 4 00:01:12 2001 +++ src/cf.data.pre Thu Aug 30 11:59:24 2001 @@ -1017,16 +1017,14 @@ 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 + Squid to handle single-component names, enable this option. DOC_END diff -ru src.orig/dns_internal.c src/dns_internal.c --- src.orig/dns_internal.c Thu Jan 11 16:51:47 2001 +++ src/dns_internal.c Thu Aug 30 14:55:27 2001 @@ -49,9 +49,11 @@ typedef struct _idns_query idns_query; typedef struct _ns ns; +typedef struct _sp sp; struct _idns_query { char buf[512]; + char name[512]; size_t sz; unsigned short id; int nsends; @@ -61,6 +63,8 @@ IDNSCB *callback; void *callback_data; int attempt; + unsigned short domain; + unsigned short dots; }; struct _ns { @@ -70,15 +74,26 @@ int large_pkts; }; +struct _sp { + char domain[64]; + int queries; +}; + 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 dlink_list lru_list; static int event_queued = 0; +static int have_path = 0; 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); static void idnsParseResolvConf(void); static void idnsSendQuery(idns_query * q); @@ -121,6 +136,35 @@ } static void +idnsAddPathComponent(const char *buf) +{ + /* TODO: Add here some other tests, not just length */ + /* For example, it shouldn't begin with a dot */ + /* But libc will be unhappy anyway about leading dots, so... */ + if (strlen(buf) > 63) { + debug(78, 0) ("WARNING: rejecting '%s' as a domain, because it is longer than 63 chars\n", buf); + return; + } + if (npc == npc_alloc) { + int oldalloc = npc_alloc; + sp *oldptr = searchpath; + if (npc_alloc == 0) + npc_alloc = 2; + else + npc_alloc <<= 1; + searchpath = xcalloc(npc_alloc, sizeof(struct _sp)); + if (oldptr && oldalloc) + xmemcpy(searchpath, oldptr, oldalloc * sizeof(struct _sp)); + 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]); + npc++; +} + +static void idnsFreeNameservers(void) { safe_free(nameservers); @@ -128,6 +172,13 @@ } static void +idnsFreeSearchpath(void) +{ + safe_free(searchpath); + npc = npc_alloc = 0; +} + +static void idnsParseNameservers(void) { wordlist *w; @@ -155,6 +206,11 @@ t = strtok(buf, w_space); if (NULL == t) continue; + /* the last directive wins ("man resolv.conf") */ + if (!strcasecmp(t, "search")) + have_path = 1; + if (!strcasecmp(t, "domain")) + have_path = 2; if (strcasecmp(t, "nameserver")) continue; t = strtok(NULL, w_space); @@ -163,6 +219,26 @@ debug(78, 1) ("Adding nameserver %s from %s\n", t, _PATH_RESOLV_CONF); idnsAddNameserver(t); } + if (have_path) { + fseek(fp, 0, SEEK_SET); + while (fgets(buf, 512, fp)) { + /* TODO: replace all tabs in buf with whitespace here! */ + t = strtok(buf, w_space); + if (NULL == t) + continue; + if ((have_path == 1) && strcasecmp(t, "search")) + continue; + if ((have_path == 2) && strcasecmp(t, "domain")) + continue; + while (t != NULL) { + t = strtok(NULL, w_space); + if (t == NULL) + continue; + debug(78, 1) ("Adding domain %s from %s\n", t, _PATH_RESOLV_CONF); + idnsAddPathComponent(t); + } + } + } fclose(fp); } @@ -321,6 +397,21 @@ idnsSendQuery(q); return; } + if (-3 == n && ++q->domain < npc && !q->dots && + Config.onoff.res_defnames && have_path != 0) { + /* + * I assume here that RCODE 3 means there's no such host + * Therefore, rebuild the query and resend it + */ + assert(NULL == answers); + strtok(q->name, "."); + strcat(q->name, "."); + strcat(q->name, searchpath[q->domain].domain); + q->start_t = current_time; + q->id = rfc1035BuildAQuery(q->name, q->buf, &q->sz); + idnsSendQuery(q); + return; + } } valid = cbdataValid(q->callback_data); cbdataUnlock(q->callback_data); @@ -495,6 +586,7 @@ comm_close(DnsSocket); DnsSocket = -1; idnsFreeNameservers(); + idnsFreeSearchpath(); } void @@ -502,7 +594,22 @@ { idns_query *q = memAllocate(MEM_IDNS_QUERY); q->sz = sizeof(q->buf); - q->id = rfc1035BuildAQuery(name, q->buf, &q->sz); + if (NULL != strstr(name, ".")) { + q->dots = 1; + } else { + q->dots = 0; + } + if (Config.onoff.res_defnames && !q->dots && have_path != 0) { + /* Is there any length check on "name"? */ + /* it should be no bigger than 64 chars or something... */ + strcpy(q->name, name); + strcat(q->name, "."); + q->domain = 0; + strcat(q->name, searchpath[q->domain].domain); + q->id = rfc1035BuildAQuery(q->name, q->buf, &q->sz); + } else { + q->id = rfc1035BuildAQuery(name, q->buf, &q->sz); + } if (0 == q->id) { /* problem with query data -- query not sent */ callback(data, NULL, 0); diff -ru src.orig/structs.h src/structs.h --- src.orig/structs.h Wed Apr 4 00:01:12 2001 +++ src/structs.h Wed Aug 29 14:45:52 2001 @@ -395,9 +395,7 @@ } Netdb; struct { int log_udp; -#if USE_DNSSERVERS int res_defnames; -#endif int anonymizer; int client_db; int query_icmp;