Blame


1 3e0d8fb3 2005-12-27 devnull #include <u.h>
2 3e0d8fb3 2005-12-27 devnull #include <libc.h>
3 3e0d8fb3 2005-12-27 devnull #include <ip.h>
4 3e0d8fb3 2005-12-27 devnull #include <bio.h>
5 3e0d8fb3 2005-12-27 devnull #include <ndb.h>
6 3e0d8fb3 2005-12-27 devnull #include "dns.h"
7 3e0d8fb3 2005-12-27 devnull
8 3e0d8fb3 2005-12-27 devnull static RR* doextquery(DNSmsg*, Request*, int);
9 3e0d8fb3 2005-12-27 devnull static void hint(RR**, RR*);
10 3e0d8fb3 2005-12-27 devnull
11 3e0d8fb3 2005-12-27 devnull extern char *logfile;
12 3e0d8fb3 2005-12-27 devnull
13 3e0d8fb3 2005-12-27 devnull /*
14 3e0d8fb3 2005-12-27 devnull * answer a dns request
15 3e0d8fb3 2005-12-27 devnull */
16 3e0d8fb3 2005-12-27 devnull void
17 3e0d8fb3 2005-12-27 devnull dnserver(DNSmsg *reqp, DNSmsg *repp, Request *req)
18 3e0d8fb3 2005-12-27 devnull {
19 3e0d8fb3 2005-12-27 devnull RR *tp, *neg;
20 3e0d8fb3 2005-12-27 devnull char *cp;
21 3e0d8fb3 2005-12-27 devnull DN *nsdp, *dp;
22 3e0d8fb3 2005-12-27 devnull Area *myarea;
23 3e0d8fb3 2005-12-27 devnull char tname[32];
24 3e0d8fb3 2005-12-27 devnull
25 3e0d8fb3 2005-12-27 devnull dncheck(nil, 1);
26 3e0d8fb3 2005-12-27 devnull
27 3e0d8fb3 2005-12-27 devnull memset(repp, 0, sizeof(*repp));
28 3e0d8fb3 2005-12-27 devnull repp->id = reqp->id;
29 3e0d8fb3 2005-12-27 devnull repp->flags = Fresp | Fcanrec | Oquery;
30 3e0d8fb3 2005-12-27 devnull
31 3e0d8fb3 2005-12-27 devnull /* move one question from reqp to repp */
32 3e0d8fb3 2005-12-27 devnull tp = reqp->qd;
33 3e0d8fb3 2005-12-27 devnull reqp->qd = tp->next;
34 3e0d8fb3 2005-12-27 devnull tp->next = 0;
35 3e0d8fb3 2005-12-27 devnull repp->qd = tp;
36 3e0d8fb3 2005-12-27 devnull
37 3e0d8fb3 2005-12-27 devnull if(!rrsupported(repp->qd->type)){
38 3e0d8fb3 2005-12-27 devnull syslog(0, logfile, "server: request %s", rrname(repp->qd->type, tname, sizeof tname));
39 3e0d8fb3 2005-12-27 devnull repp->flags = Runimplimented | Fresp | Fcanrec | Oquery;
40 3e0d8fb3 2005-12-27 devnull return;
41 3e0d8fb3 2005-12-27 devnull }
42 3e0d8fb3 2005-12-27 devnull
43 3e0d8fb3 2005-12-27 devnull if(repp->qd->owner->class != Cin){
44 3e0d8fb3 2005-12-27 devnull syslog(0, logfile, "server: class %d", repp->qd->owner->class);
45 3e0d8fb3 2005-12-27 devnull repp->flags = Runimplimented | Fresp | Fcanrec | Oquery;
46 3e0d8fb3 2005-12-27 devnull return;
47 3e0d8fb3 2005-12-27 devnull }
48 3e0d8fb3 2005-12-27 devnull
49 3e0d8fb3 2005-12-27 devnull myarea = inmyarea(repp->qd->owner->name);
50 3e0d8fb3 2005-12-27 devnull if(myarea != nil && (repp->qd->type == Tixfr || repp->qd->type == Taxfr)){
51 3e0d8fb3 2005-12-27 devnull syslog(0, logfile, "server: request %s", rrname(repp->qd->type, tname, sizeof tname));
52 3e0d8fb3 2005-12-27 devnull repp->flags = Runimplimented | Fresp | Fcanrec | Oquery;
53 3e0d8fb3 2005-12-27 devnull return;
54 3e0d8fb3 2005-12-27 devnull }
55 3e0d8fb3 2005-12-27 devnull
56 3e0d8fb3 2005-12-27 devnull /*
57 3e0d8fb3 2005-12-27 devnull * get the answer if we can
58 3e0d8fb3 2005-12-27 devnull */
59 3e0d8fb3 2005-12-27 devnull if(reqp->flags & Frecurse)
60 3e0d8fb3 2005-12-27 devnull neg = doextquery(repp, req, Recurse);
61 3e0d8fb3 2005-12-27 devnull else
62 3e0d8fb3 2005-12-27 devnull neg = doextquery(repp, req, Dontrecurse);
63 3e0d8fb3 2005-12-27 devnull
64 3e0d8fb3 2005-12-27 devnull /* authority is transitive */
65 3e0d8fb3 2005-12-27 devnull if(myarea != nil || (repp->an && repp->an->auth))
66 3e0d8fb3 2005-12-27 devnull repp->flags |= Fauth;
67 3e0d8fb3 2005-12-27 devnull
68 3e0d8fb3 2005-12-27 devnull /* pass on error codes */
69 3e0d8fb3 2005-12-27 devnull if(repp->an == 0){
70 3e0d8fb3 2005-12-27 devnull dp = dnlookup(repp->qd->owner->name, repp->qd->owner->class, 0);
71 3e0d8fb3 2005-12-27 devnull if(dp->rr == 0)
72 3e0d8fb3 2005-12-27 devnull if(reqp->flags & Frecurse)
73 3e0d8fb3 2005-12-27 devnull repp->flags |= dp->nonexistent|Fauth;
74 3e0d8fb3 2005-12-27 devnull }
75 3e0d8fb3 2005-12-27 devnull
76 3e0d8fb3 2005-12-27 devnull if(myarea == nil){
77 3e0d8fb3 2005-12-27 devnull /*
78 3e0d8fb3 2005-12-27 devnull * add name server if we know
79 3e0d8fb3 2005-12-27 devnull */
80 3e0d8fb3 2005-12-27 devnull for(cp = repp->qd->owner->name; cp; cp = walkup(cp)){
81 3e0d8fb3 2005-12-27 devnull nsdp = dnlookup(cp, repp->qd->owner->class, 0);
82 3e0d8fb3 2005-12-27 devnull if(nsdp == 0)
83 3e0d8fb3 2005-12-27 devnull continue;
84 3e0d8fb3 2005-12-27 devnull
85 3e0d8fb3 2005-12-27 devnull repp->ns = rrlookup(nsdp, Tns, OKneg);
86 3e0d8fb3 2005-12-27 devnull if(repp->ns){
87 3e0d8fb3 2005-12-27 devnull /* don't pass on anything we know is wrong */
88 3e0d8fb3 2005-12-27 devnull if(repp->ns->negative){
89 3e0d8fb3 2005-12-27 devnull rrfreelist(repp->ns);
90 3e0d8fb3 2005-12-27 devnull repp->ns = nil;
91 3e0d8fb3 2005-12-27 devnull }
92 3e0d8fb3 2005-12-27 devnull break;
93 3e0d8fb3 2005-12-27 devnull }
94 3e0d8fb3 2005-12-27 devnull
95 3e0d8fb3 2005-12-27 devnull repp->ns = dblookup(cp, repp->qd->owner->class, Tns, 0, 0);
96 3e0d8fb3 2005-12-27 devnull if(repp->ns)
97 3e0d8fb3 2005-12-27 devnull break;
98 3e0d8fb3 2005-12-27 devnull }
99 3e0d8fb3 2005-12-27 devnull }
100 3e0d8fb3 2005-12-27 devnull
101 3e0d8fb3 2005-12-27 devnull /*
102 3e0d8fb3 2005-12-27 devnull * add ip addresses as hints
103 3e0d8fb3 2005-12-27 devnull */
104 3e0d8fb3 2005-12-27 devnull if(repp->qd->type != Taxfr && repp->qd->type != Tixfr){
105 3e0d8fb3 2005-12-27 devnull for(tp = repp->ns; tp; tp = tp->next)
106 3e0d8fb3 2005-12-27 devnull hint(&repp->ar, tp);
107 3e0d8fb3 2005-12-27 devnull for(tp = repp->an; tp; tp = tp->next)
108 3e0d8fb3 2005-12-27 devnull hint(&repp->ar, tp);
109 3e0d8fb3 2005-12-27 devnull }
110 3e0d8fb3 2005-12-27 devnull
111 3e0d8fb3 2005-12-27 devnull /*
112 3e0d8fb3 2005-12-27 devnull * add an soa to the authority section to help client with negative caching
113 3e0d8fb3 2005-12-27 devnull */
114 3e0d8fb3 2005-12-27 devnull if(repp->an == nil){
115 3e0d8fb3 2005-12-27 devnull if(myarea != nil){
116 3e0d8fb3 2005-12-27 devnull rrcopy(myarea->soarr, &tp);
117 3e0d8fb3 2005-12-27 devnull rrcat(&repp->ns, tp);
118 3e0d8fb3 2005-12-27 devnull } else if(neg != nil) {
119 3e0d8fb3 2005-12-27 devnull if(neg->negsoaowner != nil)
120 3e0d8fb3 2005-12-27 devnull rrcat(&repp->ns, rrlookup(neg->negsoaowner, Tsoa, NOneg));
121 3e0d8fb3 2005-12-27 devnull repp->flags |= neg->negrcode;
122 3e0d8fb3 2005-12-27 devnull }
123 3e0d8fb3 2005-12-27 devnull }
124 3e0d8fb3 2005-12-27 devnull
125 3e0d8fb3 2005-12-27 devnull /*
126 3e0d8fb3 2005-12-27 devnull * get rid of duplicates
127 3e0d8fb3 2005-12-27 devnull */
128 3e0d8fb3 2005-12-27 devnull unique(repp->an);
129 3e0d8fb3 2005-12-27 devnull unique(repp->ns);
130 3e0d8fb3 2005-12-27 devnull unique(repp->ar);
131 3e0d8fb3 2005-12-27 devnull
132 3e0d8fb3 2005-12-27 devnull rrfreelist(neg);
133 3e0d8fb3 2005-12-27 devnull
134 3e0d8fb3 2005-12-27 devnull dncheck(nil, 1);
135 3e0d8fb3 2005-12-27 devnull }
136 3e0d8fb3 2005-12-27 devnull
137 3e0d8fb3 2005-12-27 devnull /*
138 3e0d8fb3 2005-12-27 devnull * satisfy a recursive request. dnlookup will handle cnames.
139 3e0d8fb3 2005-12-27 devnull */
140 3e0d8fb3 2005-12-27 devnull static RR*
141 3e0d8fb3 2005-12-27 devnull doextquery(DNSmsg *mp, Request *req, int recurse)
142 3e0d8fb3 2005-12-27 devnull {
143 3e0d8fb3 2005-12-27 devnull int type;
144 3e0d8fb3 2005-12-27 devnull char *name;
145 3e0d8fb3 2005-12-27 devnull RR *rp, *neg;
146 3e0d8fb3 2005-12-27 devnull
147 3e0d8fb3 2005-12-27 devnull name = mp->qd->owner->name;
148 3e0d8fb3 2005-12-27 devnull type = mp->qd->type;
149 3e0d8fb3 2005-12-27 devnull rp = dnresolve(name, Cin, type, req, &mp->an, 0, recurse, 1, 0);
150 3e0d8fb3 2005-12-27 devnull
151 3e0d8fb3 2005-12-27 devnull /* don't return soa hints as answers, it's wrong */
152 3e0d8fb3 2005-12-27 devnull if(rp && rp->db && !rp->auth && rp->type == Tsoa)
153 3e0d8fb3 2005-12-27 devnull rrfreelist(rp);
154 3e0d8fb3 2005-12-27 devnull
155 3e0d8fb3 2005-12-27 devnull /* don't let negative cached entries escape */
156 3e0d8fb3 2005-12-27 devnull neg = rrremneg(&rp);
157 3e0d8fb3 2005-12-27 devnull rrcat(&mp->an, rp);
158 3e0d8fb3 2005-12-27 devnull return neg;
159 3e0d8fb3 2005-12-27 devnull }
160 3e0d8fb3 2005-12-27 devnull
161 3e0d8fb3 2005-12-27 devnull static void
162 3e0d8fb3 2005-12-27 devnull hint(RR **last, RR *rp)
163 3e0d8fb3 2005-12-27 devnull {
164 3e0d8fb3 2005-12-27 devnull RR *hp;
165 3e0d8fb3 2005-12-27 devnull
166 3e0d8fb3 2005-12-27 devnull switch(rp->type){
167 3e0d8fb3 2005-12-27 devnull case Tns:
168 3e0d8fb3 2005-12-27 devnull case Tmx:
169 3e0d8fb3 2005-12-27 devnull case Tmb:
170 3e0d8fb3 2005-12-27 devnull case Tmf:
171 3e0d8fb3 2005-12-27 devnull case Tmd:
172 3e0d8fb3 2005-12-27 devnull hp = rrlookup(rp->host, Ta, NOneg);
173 3e0d8fb3 2005-12-27 devnull if(hp == nil)
174 3e0d8fb3 2005-12-27 devnull hp = dblookup(rp->host->name, Cin, Ta, 0, 0);
175 3e0d8fb3 2005-12-27 devnull rrcat(last, hp);
176 3e0d8fb3 2005-12-27 devnull break;
177 3e0d8fb3 2005-12-27 devnull }
178 3e0d8fb3 2005-12-27 devnull }