📄 resolve.c
字号:
/************************************************************************************************** $Id: resolve.c,v 1.59 2006/01/18 20:46:47 bboy Exp $ Copyright (C) 2002-2005 Don Moore <bboy@bboy.net> This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at Your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA**************************************************************************************************/#include "named.h"/* Make this nonzero to enable debugging for this source file */#define DEBUG_RESOLVE 1#if DEBUG_ENABLED && DEBUG_RESOLVE/* Strings describing the datasections */char *resolve_datasection_str[] = { "QUESTION", "ANSWER", "AUTHORITY", "ADDITIONAL" };#endif#if STATUS_ENABLEDextern int remote_status(TASK *t);#endif/************************************************************************************************** RESOLVE_SOA Adds SOA record to the specified section. If that section is ANSWER, assume this is a SOA query. Returns number of records inserted, or -1 if an error occurred.**************************************************************************************************/static intresolve_soa(TASK *t, datasection_t section, char *fqdn){ MYDNS_SOA *soa = find_soa(t, fqdn, NULL); if (soa) { t->zone = soa->id; t->minimum_ttl = soa->minimum; /* Don't cache replies for SOA with a 0 second TTL */ if (!soa->minimum && !soa->ttl) t->reply_cache_ok = 0; /* This is a SOA request - handle things a tiny bit differently */ if (t->qtype == DNS_QTYPE_SOA && section == ANSWER) { /* If the fqdn does not exactly match, put the SOA in AUTHORITY instead of ANSWER */ if (strcmp(fqdn, soa->origin)) { rrlist_add(t, AUTHORITY, DNS_RRTYPE_SOA, (void *)soa, soa->origin); t->sort_level++; } else { /* SOA in ANSWER - also add authoritative nameservers */ rrlist_add(t, section, DNS_RRTYPE_SOA, (void *)soa, soa->origin); t->sort_level++; (void)resolve(t, AUTHORITY, DNS_QTYPE_NS, soa->origin, 0); } } else { rrlist_add(t, section, DNS_RRTYPE_SOA, (void *)soa, soa->origin); t->sort_level++; } mydns_soa_free(soa); if (section == ANSWER) /* We are authoritative; Set `aa' flag */ t->hdr.aa = 1; return (1); } return (section == ANSWER ? dnserror(t, DNS_RCODE_REFUSED, ERR_ZONE_NOT_FOUND) : 0);}/*--- resolve_soa() -----------------------------------------------------------------------------*//************************************************************************************************** CNAME_RECURSE If task has a dominant matching CNAME record, recurse into it. Returns the number of records added.**************************************************************************************************/static intcname_recurse(TASK *t, datasection_t section, dns_qtype_t qtype, char *fqdn, MYDNS_SOA *soa, char *label, MYDNS_RR *cname, int level){ register int n; if (level >= MAX_CNAME_LEVEL) return (1); /* Add the CNAME record to the answer section */ if (section == ANSWER && level) rrlist_add(t, ADDITIONAL, DNS_RRTYPE_RR, (void *)cname, fqdn); else rrlist_add(t, section, DNS_RRTYPE_RR, (void *)cname, fqdn); t->sort_level++; /* If the request was for CNAME records, this is the answer; we are done. */ if (t->qtype == DNS_QTYPE_CNAME) return (1); /* Check `Cnames' list; if we are looping, stop. Otherwise add this to the array. */ for (n = 0; n < level; n++) if (t->Cnames[n] == cname->id) { /* CNAME loop: Send what we have so far and consider the resolution complete */ Verbose("%s: %s: %s %s %s (depth %d)", desctask(t), _("CNAME loop detected"), cname->name, mydns_qtype_str(cname->type), cname->data, level); return (1); } t->Cnames[level] = cname->id;#if DEBUG_ENABLED && DEBUG_RESOLVE Debug("%s: CNAME -> `%s'", desctask(t), cname->data);#endif /* Resolve with this new CNAME record as the FQDN */ return resolve(t, section, qtype, cname->data, level+1);}/*--- cname_recurse() ---------------------------------------------------------------------------*//************************************************************************************************** PROCESS_RR Process the resource record list. Returns number of records added.**************************************************************************************************/static intprocess_rr(TASK *t, datasection_t section, dns_qtype_t qtype, char *fqdn, MYDNS_SOA *soa, char *label, MYDNS_RR *rr, int level){ register MYDNS_RR *r; register int rv = 0; register int add_ns = (section == ANSWER && !t->ns.size && qtype != DNS_QTYPE_NS && qtype != DNS_QTYPE_ANY); t->name_ok = 1;#if DEBUG_ENABLED && DEBUG_RESOLVE Debug("%s: process_rr(%s, %s, \"%s\", (%s), \"%s\", %d)", desctask(t), resolve_datasection_str[section], mydns_qtype_str(qtype), fqdn, soa->origin, label, level); Debug("%s: matched `%s%s%s'", desctask(t), label, *label ? "." : "", soa->origin);#endif /* If the data section calls for a FQDN, and we just get a hostname, append the origin */ for (r = rr; r; r = r->next) if (r->type == DNS_QTYPE_NS || r->type == DNS_QTYPE_CNAME || r->type == DNS_QTYPE_MX) { register int len = strlen(r->data); if (r->data[len-1] == '.') continue;#if DEBUG_ENABLED && DEBUG_RESOLVE Debug("Appending origin (%s) to data section (%s)", soa->origin, r->data);#endif if (len + strlen(soa->origin) + 1 <= DNS_MAXNAMELEN) { r->data[len] = '.'; strcpy(r->data + len + 1, soa->origin); } } /* If the RR list returned contains a CNAME record, follow the CNAME. */ for (r = rr; r; r = r->next) if (r->type == DNS_QTYPE_CNAME) return cname_recurse(t, section, qtype, fqdn, soa, label, r, level); /* Find RRs matching QTYPE */ for (r = rr; r; r = r->next) if (r->type == qtype || qtype == DNS_QTYPE_ANY) {#if ALIAS_ENABLED /* If the RR is an ALIAS then follow it, otherwise just add it. */ if (r->alias) rv += alias_recurse(t, section, fqdn, soa, label, r); else { rrlist_add(t, section, DNS_RRTYPE_RR, (void *)r, fqdn); rv++; }#else rrlist_add(t, section, DNS_RRTYPE_RR, (void *)r, fqdn); rv++;#endif } t->sort_level++; /* If we found no matching RR's but there are NS records, and the name isn't empty or '*' (which I think is probably wrong, but...) treat as delegation -- set 'rv' to make the caller return, then set 'add_ns' to fill the AUTHORITY */ if (!rv && *label && *label != '*') for (r = rr; !rv && r; r = r->next) if (r->type == DNS_QTYPE_NS) rv = add_ns = 1; /* If we found some results, go ahead and put nameserver records into AUTHORITY */ for (r = rr; rv && r; r = r->next) if (r->type == DNS_QTYPE_NS && add_ns) { char ns[DNS_MAXNAMELEN+1]; /* If the rr is for something like "*.bboy.net.", show the labelized name */ if (r->name[0] == '*' && r->name[1] == '.' && r->name[2]) snprintf(ns, sizeof(ns), "%s.%s", r->name+2, soa->origin); else if (r->name[0] && r->name[0] != '*') snprintf(ns, sizeof(ns), "%s.%s", r->name, soa->origin); else strncpy(ns, soa->origin, sizeof(ns)-1);#if DEBUG_ENABLED && DEBUG_RESOLVE Debug("%s: Adding AUTHORITY for NS \"%s\"", desctask(t), ns);#endif rrlist_add(t, AUTHORITY, DNS_RRTYPE_RR, (void *)r, ns); /* If the NS data is a FQDN, look in THIS zone for an A record. That way glue records can be stored out of bailiwick a la BIND */ if (LASTCHAR(r->data) == '.') { MYDNS_RR *A = find_rr(t, soa, DNS_QTYPE_A, r->data); if (A) { register MYDNS_RR *a; for (a = A; a; a = a->next) rrlist_add(t, ADDITIONAL, DNS_RRTYPE_RR, (void *)a, r->data); mydns_rr_free(A); } } rv++; } t->sort_level++; /* We DID find matches for this label; thus, reply success but with no records in the ANSWER section. */ if (!rv && section == ANSWER) {#if DEBUG_ENABLED && DEBUG_RESOLVE Debug("%s: no RRs match", desctask(t));#endif if (!t->ns.size) rrlist_add(t, AUTHORITY, DNS_RRTYPE_SOA, (void *)soa, soa->origin); rv++; t->sort_level++; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -