6 static RR* doextquery(DNSmsg*, Request*, int);
7 static void hint(RR**, RR*);
10 int norecursion; /* don't allow recursive requests */
13 * answer a dns request
16 dnserver(DNSmsg *reqp, DNSmsg *repp, Request *req, uchar *srcip, int rcode)
25 recursionflag = norecursion? 0: Fcanrec;
26 memset(repp, 0, sizeof(*repp));
28 repp->flags = Fresp | recursionflag | Oquery;
30 /* move one question from reqp to repp */
38 if (rcode >= 0 && rcode < nrname)
39 errmsg = rname[rcode];
40 dnslog("server: response code 0%o (%s), req from %I",
41 rcode, errmsg, srcip);
42 /* provide feedback to clients who send us trash */
43 repp->flags = (rcode&Rmask) | Fresp | Fcanrec | Oquery;
46 if(!rrsupported(repp->qd->type)){
47 dnslog("server: unsupported request %s from %I",
48 rrname(repp->qd->type, tname, sizeof tname), srcip);
49 repp->flags = Runimplimented | Fresp | Fcanrec | Oquery;
53 if(repp->qd->owner->class != Cin){
54 dnslog("server: unsupported class %d from %I",
55 repp->qd->owner->class, srcip);
56 repp->flags = Runimplimented | Fresp | Fcanrec | Oquery;
60 myarea = inmyarea(repp->qd->owner->name);
62 if(repp->qd->type == Tixfr || repp->qd->type == Taxfr){
63 dnslog("server: unsupported xfr request %s for %s from %I",
64 rrname(repp->qd->type, tname, sizeof tname),
65 repp->qd->owner->name, srcip);
66 repp->flags = Runimplimented | Fresp | recursionflag |
71 if(myarea == nil && norecursion) {
72 /* we don't recurse and we're not authoritative */
73 repp->flags = Rok | Fresp | Oquery;
77 * get the answer if we can, in *repp
79 if(reqp->flags & Frecurse)
80 neg = doextquery(repp, req, Recurse);
82 neg = doextquery(repp, req, Dontrecurse);
84 /* authority is transitive */
85 if(myarea != nil || (repp->an && repp->an->auth))
88 /* pass on error codes */
90 dp = dnlookup(repp->qd->owner->name, repp->qd->owner->class, 0);
92 if(reqp->flags & Frecurse)
93 repp->flags |= dp->respcode | Fauth;
99 * add name server if we know
101 for(cp = repp->qd->owner->name; cp; cp = walkup(cp)){
102 nsdp = dnlookup(cp, repp->qd->owner->class, 0);
106 repp->ns = rrlookup(nsdp, Tns, OKneg);
108 /* don't pass on anything we know is wrong */
109 if(repp->ns->negative){
117 if (strncmp(nsdp->name, "local#", 6) == 0)
118 dnslog("returning %s as nameserver", nsdp->name);
119 repp->ns = dblookup(cp, repp->qd->owner->class, Tns, 0, 0);
126 * add ip addresses as hints
128 if(repp->qd->type != Taxfr && repp->qd->type != Tixfr){
129 for(tp = repp->ns; tp; tp = tp->next)
131 for(tp = repp->an; tp; tp = tp->next)
136 * add an soa to the authority section to help client
137 * with negative caching
141 rrcopy(myarea->soarr, &tp);
142 rrcat(&repp->ns, tp);
143 } else if(neg != nil) {
144 if(neg->negsoaowner != nil) {
145 tp = rrlookup(neg->negsoaowner, Tsoa, NOneg);
146 rrcat(&repp->ns, tp);
148 repp->flags |= neg->negrcode;
153 * get rid of duplicates
163 * satisfy a recursive request. dnlookup will handle cnames.
166 doextquery(DNSmsg *mp, Request *req, int recurse)
172 name = mp->qd->owner->name;
174 rp = dnresolve(name, Cin, type, req, &mp->an, 0, recurse, 1, 0);
176 /* don't return soa hints as answers, it's wrong */
177 if(rp && rp->db && !rp->auth && rp->type == Tsoa) {
182 /* don't let negative cached entries escape */
190 hint(RR **last, RR *rp)
200 hp = rrlookup(rp->host, Ta, NOneg);
202 hp = dblookup(rp->host->name, Cin, Ta, 0, 0);
204 hp = rrlookup(rp->host, Taaaa, NOneg);
206 hp = dblookup(rp->host->name, Cin, Taaaa, 0, 0);
207 if (hp && strncmp(hp->owner->name, "local#", 6) == 0)
208 dnslog("returning %s as hint", hp->owner->name);