Blame


1 27b457ae 2006-02-15 devnull #include <u.h>
2 27b457ae 2006-02-15 devnull #include <libc.h>
3 27b457ae 2006-02-15 devnull #include <ip.h>
4 27b457ae 2006-02-15 devnull #include <bio.h>
5 27b457ae 2006-02-15 devnull #include <ndb.h>
6 27b457ae 2006-02-15 devnull #include <thread.h>
7 27b457ae 2006-02-15 devnull #include "dns.h"
8 27b457ae 2006-02-15 devnull
9 27b457ae 2006-02-15 devnull static char adir[40];
10 27b457ae 2006-02-15 devnull
11 27b457ae 2006-02-15 devnull static int
12 27b457ae 2006-02-15 devnull readmsg(int fd, uchar *buf, int max)
13 27b457ae 2006-02-15 devnull {
14 27b457ae 2006-02-15 devnull int n;
15 27b457ae 2006-02-15 devnull uchar x[2];
16 27b457ae 2006-02-15 devnull
17 27b457ae 2006-02-15 devnull if(readn(fd, x, 2) != 2)
18 27b457ae 2006-02-15 devnull return -1;
19 27b457ae 2006-02-15 devnull n = (x[0]<<8) | x[1];
20 27b457ae 2006-02-15 devnull if(n > max)
21 27b457ae 2006-02-15 devnull return -1;
22 27b457ae 2006-02-15 devnull if(readn(fd, buf, n) != n)
23 27b457ae 2006-02-15 devnull return -1;
24 27b457ae 2006-02-15 devnull return n;
25 27b457ae 2006-02-15 devnull }
26 27b457ae 2006-02-15 devnull
27 27b457ae 2006-02-15 devnull static int
28 27b457ae 2006-02-15 devnull connreadmsg(int tfd, int *fd, uchar *buf, int max)
29 27b457ae 2006-02-15 devnull {
30 27b457ae 2006-02-15 devnull int n;
31 27b457ae 2006-02-15 devnull int lfd;
32 27b457ae 2006-02-15 devnull char ldir[40];
33 27b457ae 2006-02-15 devnull
34 27b457ae 2006-02-15 devnull lfd = listen(adir, ldir);
35 27b457ae 2006-02-15 devnull if (lfd < 0)
36 27b457ae 2006-02-15 devnull return -1;
37 27b457ae 2006-02-15 devnull *fd = accept(lfd, ldir);
38 19256e0d 2006-02-17 devnull if (*fd >= 0)
39 27b457ae 2006-02-15 devnull n = readmsg(*fd, buf, max);
40 19256e0d 2006-02-17 devnull else
41 19256e0d 2006-02-17 devnull n = -1;
42 27b457ae 2006-02-15 devnull close(lfd);
43 27b457ae 2006-02-15 devnull return n;
44 27b457ae 2006-02-15 devnull }
45 27b457ae 2006-02-15 devnull
46 27b457ae 2006-02-15 devnull static int
47 27b457ae 2006-02-15 devnull reply(int fd, DNSmsg *rep, Request *req, NetConnInfo *caller)
48 27b457ae 2006-02-15 devnull {
49 27b457ae 2006-02-15 devnull int len;
50 27b457ae 2006-02-15 devnull char tname[32];
51 27b457ae 2006-02-15 devnull uchar buf[4096];
52 27b457ae 2006-02-15 devnull RR *rp;
53 27b457ae 2006-02-15 devnull
54 27b457ae 2006-02-15 devnull if(debug){
55 27b457ae 2006-02-15 devnull syslog(0, logfile, "%d: reply (%s) %s %s %ux",
56 27b457ae 2006-02-15 devnull req->id, caller ? caller->raddr : "unk",
57 27b457ae 2006-02-15 devnull rep->qd->owner->name,
58 27b457ae 2006-02-15 devnull rrname(rep->qd->type, tname, sizeof tname),
59 27b457ae 2006-02-15 devnull rep->flags);
60 27b457ae 2006-02-15 devnull for(rp = rep->an; rp; rp = rp->next)
61 27b457ae 2006-02-15 devnull syslog(0, logfile, "an %R", rp);
62 27b457ae 2006-02-15 devnull for(rp = rep->ns; rp; rp = rp->next)
63 27b457ae 2006-02-15 devnull syslog(0, logfile, "ns %R", rp);
64 27b457ae 2006-02-15 devnull for(rp = rep->ar; rp; rp = rp->next)
65 27b457ae 2006-02-15 devnull syslog(0, logfile, "ar %R", rp);
66 27b457ae 2006-02-15 devnull }
67 27b457ae 2006-02-15 devnull
68 27b457ae 2006-02-15 devnull
69 27b457ae 2006-02-15 devnull len = convDNS2M(rep, buf+2, sizeof(buf) - 2);
70 27b457ae 2006-02-15 devnull if(len <= 0)
71 27b457ae 2006-02-15 devnull abort(); /* "dnserver: converting reply" */;
72 27b457ae 2006-02-15 devnull buf[0] = len>>8;
73 27b457ae 2006-02-15 devnull buf[1] = len;
74 27b457ae 2006-02-15 devnull if(write(fd, buf, len+2) < 0){
75 27b457ae 2006-02-15 devnull syslog(0, logfile, "sending reply: %r");
76 27b457ae 2006-02-15 devnull return -1;
77 27b457ae 2006-02-15 devnull }
78 27b457ae 2006-02-15 devnull return 0;
79 27b457ae 2006-02-15 devnull }
80 27b457ae 2006-02-15 devnull
81 27b457ae 2006-02-15 devnull /*
82 27b457ae 2006-02-15 devnull * Hash table for domain names. The hash is based only on the
83 27b457ae 2006-02-15 devnull * first element of the domain name.
84 27b457ae 2006-02-15 devnull */
85 27b457ae 2006-02-15 devnull extern DN *ht[HTLEN];
86 27b457ae 2006-02-15 devnull
87 27b457ae 2006-02-15 devnull static int
88 27b457ae 2006-02-15 devnull numelem(char *name)
89 27b457ae 2006-02-15 devnull {
90 27b457ae 2006-02-15 devnull int i;
91 27b457ae 2006-02-15 devnull
92 27b457ae 2006-02-15 devnull i = 1;
93 27b457ae 2006-02-15 devnull for(; *name; name++)
94 27b457ae 2006-02-15 devnull if(*name == '.')
95 27b457ae 2006-02-15 devnull i++;
96 27b457ae 2006-02-15 devnull return i;
97 27b457ae 2006-02-15 devnull }
98 27b457ae 2006-02-15 devnull
99 27b457ae 2006-02-15 devnull static int
100 27b457ae 2006-02-15 devnull inzone(DN *dp, char *name, int namelen, int depth)
101 27b457ae 2006-02-15 devnull {
102 27b457ae 2006-02-15 devnull int n;
103 27b457ae 2006-02-15 devnull
104 27b457ae 2006-02-15 devnull if(dp->name == 0)
105 27b457ae 2006-02-15 devnull return 0;
106 27b457ae 2006-02-15 devnull if(numelem(dp->name) != depth)
107 27b457ae 2006-02-15 devnull return 0;
108 27b457ae 2006-02-15 devnull n = strlen(dp->name);
109 27b457ae 2006-02-15 devnull if(n < namelen)
110 27b457ae 2006-02-15 devnull return 0;
111 27b457ae 2006-02-15 devnull if(strcmp(name, dp->name + n - namelen) != 0)
112 27b457ae 2006-02-15 devnull return 0;
113 27b457ae 2006-02-15 devnull if(n > namelen && dp->name[n - namelen - 1] != '.')
114 27b457ae 2006-02-15 devnull return 0;
115 27b457ae 2006-02-15 devnull return 1;
116 27b457ae 2006-02-15 devnull }
117 27b457ae 2006-02-15 devnull
118 27b457ae 2006-02-15 devnull static int
119 27b457ae 2006-02-15 devnull dnzone(DNSmsg *reqp, DNSmsg *repp, Request *req, int rfd, NetConnInfo *caller)
120 27b457ae 2006-02-15 devnull {
121 27b457ae 2006-02-15 devnull DN *dp, *ndp;
122 27b457ae 2006-02-15 devnull RR r, *rp;
123 27b457ae 2006-02-15 devnull int h, depth, found, nlen, rv;
124 27b457ae 2006-02-15 devnull
125 27b457ae 2006-02-15 devnull rv = 0;
126 27b457ae 2006-02-15 devnull memset(repp, 0, sizeof(*repp));
127 27b457ae 2006-02-15 devnull repp->id = reqp->id;
128 27b457ae 2006-02-15 devnull repp->flags = Fauth | Fresp | Fcanrec | Oquery;
129 27b457ae 2006-02-15 devnull repp->qd = reqp->qd;
130 27b457ae 2006-02-15 devnull reqp->qd = reqp->qd->next;
131 27b457ae 2006-02-15 devnull repp->qd->next = 0;
132 27b457ae 2006-02-15 devnull dp = repp->qd->owner;
133 27b457ae 2006-02-15 devnull
134 27b457ae 2006-02-15 devnull /* send the soa */
135 27b457ae 2006-02-15 devnull repp->an = rrlookup(dp, Tsoa, NOneg);
136 27b457ae 2006-02-15 devnull rv = reply(rfd, repp, req, caller);
137 27b457ae 2006-02-15 devnull if(repp->an == 0 || rv < 0)
138 27b457ae 2006-02-15 devnull goto out;
139 27b457ae 2006-02-15 devnull rrfreelist(repp->an);
140 27b457ae 2006-02-15 devnull
141 27b457ae 2006-02-15 devnull nlen = strlen(dp->name);
142 27b457ae 2006-02-15 devnull
143 27b457ae 2006-02-15 devnull /* construct a breadth first search of the name space (hard with a hash) */
144 27b457ae 2006-02-15 devnull repp->an = &r;
145 27b457ae 2006-02-15 devnull for(depth = numelem(dp->name); ; depth++){
146 27b457ae 2006-02-15 devnull found = 0;
147 27b457ae 2006-02-15 devnull for(h = 0; h < HTLEN; h++)
148 27b457ae 2006-02-15 devnull for(ndp = ht[h]; ndp; ndp = ndp->next)
149 27b457ae 2006-02-15 devnull if(inzone(ndp, dp->name, nlen, depth)){
150 27b457ae 2006-02-15 devnull for(rp = ndp->rr; rp; rp = rp->next){
151 27b457ae 2006-02-15 devnull /* there shouldn't be negatives, but just in case */
152 27b457ae 2006-02-15 devnull if(rp->negative)
153 27b457ae 2006-02-15 devnull continue;
154 27b457ae 2006-02-15 devnull
155 27b457ae 2006-02-15 devnull /* don't send an soa's, ns's are enough */
156 27b457ae 2006-02-15 devnull if(rp->type == Tsoa)
157 27b457ae 2006-02-15 devnull continue;
158 27b457ae 2006-02-15 devnull
159 27b457ae 2006-02-15 devnull r = *rp;
160 27b457ae 2006-02-15 devnull r.next = 0;
161 27b457ae 2006-02-15 devnull rv = reply(rfd, repp, req, caller);
162 27b457ae 2006-02-15 devnull if(rv < 0)
163 27b457ae 2006-02-15 devnull goto out;
164 27b457ae 2006-02-15 devnull }
165 27b457ae 2006-02-15 devnull found = 1;
166 27b457ae 2006-02-15 devnull }
167 27b457ae 2006-02-15 devnull if(!found)
168 27b457ae 2006-02-15 devnull break;
169 27b457ae 2006-02-15 devnull }
170 27b457ae 2006-02-15 devnull
171 27b457ae 2006-02-15 devnull /* resend the soa */
172 27b457ae 2006-02-15 devnull repp->an = rrlookup(dp, Tsoa, NOneg);
173 27b457ae 2006-02-15 devnull rv = reply(rfd, repp, req, caller);
174 27b457ae 2006-02-15 devnull out:
175 27b457ae 2006-02-15 devnull if (repp->an)
176 27b457ae 2006-02-15 devnull rrfreelist(repp->an);
177 27b457ae 2006-02-15 devnull rrfree(repp->qd);
178 27b457ae 2006-02-15 devnull return rv;
179 27b457ae 2006-02-15 devnull }
180 27b457ae 2006-02-15 devnull
181 27b457ae 2006-02-15 devnull void
182 27b457ae 2006-02-15 devnull tcpproc(void *v)
183 27b457ae 2006-02-15 devnull {
184 19256e0d 2006-02-17 devnull int len, rv;
185 27b457ae 2006-02-15 devnull Request req;
186 27b457ae 2006-02-15 devnull DNSmsg reqmsg, repmsg;
187 27b457ae 2006-02-15 devnull char *err;
188 27b457ae 2006-02-15 devnull uchar buf[512];
189 27b457ae 2006-02-15 devnull char tname[32];
190 27b457ae 2006-02-15 devnull int fd, rfd;
191 27b457ae 2006-02-15 devnull NetConnInfo *caller;
192 27b457ae 2006-02-15 devnull
193 27b457ae 2006-02-15 devnull rfd = -1;
194 19256e0d 2006-02-17 devnull fd = (uintptr)v;
195 27b457ae 2006-02-15 devnull caller = 0;
196 27b457ae 2006-02-15 devnull /* loop on requests */
197 27b457ae 2006-02-15 devnull for(;; putactivity()){
198 27b457ae 2006-02-15 devnull if (rfd == 1)
199 27b457ae 2006-02-15 devnull return;
200 27b457ae 2006-02-15 devnull close(rfd);
201 27b457ae 2006-02-15 devnull now = time(0);
202 27b457ae 2006-02-15 devnull memset(&repmsg, 0, sizeof(repmsg));
203 27b457ae 2006-02-15 devnull if (fd == 0) {
204 27b457ae 2006-02-15 devnull len = readmsg(fd, buf, sizeof buf);
205 27b457ae 2006-02-15 devnull rfd = 1;
206 27b457ae 2006-02-15 devnull } else {
207 27b457ae 2006-02-15 devnull len = connreadmsg(fd, &rfd, buf, sizeof buf);
208 27b457ae 2006-02-15 devnull }
209 27b457ae 2006-02-15 devnull if(len <= 0)
210 27b457ae 2006-02-15 devnull continue;
211 b7f150b0 2006-02-24 devnull freenetconninfo(caller);
212 b7f150b0 2006-02-24 devnull caller = getnetconninfo(0, fd);
213 27b457ae 2006-02-15 devnull getactivity(&req);
214 27b457ae 2006-02-15 devnull req.aborttime = now + 15*Min;
215 27b457ae 2006-02-15 devnull err = convM2DNS(buf, len, &reqmsg);
216 27b457ae 2006-02-15 devnull if(err){
217 27b457ae 2006-02-15 devnull syslog(0, logfile, "server: input error: %s from %I", err, buf);
218 27b457ae 2006-02-15 devnull continue;
219 27b457ae 2006-02-15 devnull }
220 27b457ae 2006-02-15 devnull if(reqmsg.qdcount < 1){
221 27b457ae 2006-02-15 devnull syslog(0, logfile, "server: no questions from %I", buf);
222 27b457ae 2006-02-15 devnull continue;
223 27b457ae 2006-02-15 devnull }
224 27b457ae 2006-02-15 devnull if(reqmsg.flags & Fresp){
225 27b457ae 2006-02-15 devnull syslog(0, logfile, "server: reply not request from %I", buf);
226 27b457ae 2006-02-15 devnull continue;
227 27b457ae 2006-02-15 devnull }
228 27b457ae 2006-02-15 devnull if((reqmsg.flags & Omask) != Oquery){
229 27b457ae 2006-02-15 devnull syslog(0, logfile, "server: op %d from %I", reqmsg.flags & Omask, buf);
230 27b457ae 2006-02-15 devnull continue;
231 27b457ae 2006-02-15 devnull }
232 27b457ae 2006-02-15 devnull
233 27b457ae 2006-02-15 devnull if(debug)
234 27b457ae 2006-02-15 devnull syslog(0, logfile, "%d: serve (%s) %d %s %s",
235 27b457ae 2006-02-15 devnull req.id, caller ? caller->raddr : 0,
236 27b457ae 2006-02-15 devnull reqmsg.id,
237 27b457ae 2006-02-15 devnull reqmsg.qd->owner->name,
238 27b457ae 2006-02-15 devnull rrname(reqmsg.qd->type, tname, sizeof tname));
239 27b457ae 2006-02-15 devnull
240 27b457ae 2006-02-15 devnull /* loop through each question */
241 27b457ae 2006-02-15 devnull while(reqmsg.qd){
242 27b457ae 2006-02-15 devnull if(reqmsg.qd->type == Taxfr){
243 27b457ae 2006-02-15 devnull if(dnzone(&reqmsg, &repmsg, &req, rfd, caller) < 0)
244 27b457ae 2006-02-15 devnull break;
245 27b457ae 2006-02-15 devnull } else {
246 27b457ae 2006-02-15 devnull dnserver(&reqmsg, &repmsg, &req);
247 19256e0d 2006-02-17 devnull rv = reply(rfd, &repmsg, &req, caller);
248 27b457ae 2006-02-15 devnull rrfreelist(repmsg.qd);
249 27b457ae 2006-02-15 devnull rrfreelist(repmsg.an);
250 27b457ae 2006-02-15 devnull rrfreelist(repmsg.ns);
251 27b457ae 2006-02-15 devnull rrfreelist(repmsg.ar);
252 19256e0d 2006-02-17 devnull if(rv < 0)
253 19256e0d 2006-02-17 devnull break;
254 27b457ae 2006-02-15 devnull }
255 27b457ae 2006-02-15 devnull }
256 27b457ae 2006-02-15 devnull
257 27b457ae 2006-02-15 devnull rrfreelist(reqmsg.qd);
258 27b457ae 2006-02-15 devnull rrfreelist(reqmsg.an);
259 27b457ae 2006-02-15 devnull rrfreelist(reqmsg.ns);
260 27b457ae 2006-02-15 devnull rrfreelist(reqmsg.ar);
261 27b457ae 2006-02-15 devnull }
262 27b457ae 2006-02-15 devnull }
263 27b457ae 2006-02-15 devnull
264 27b457ae 2006-02-15 devnull enum {
265 226d80b8 2006-04-01 devnull Maxactivetcp = 4
266 27b457ae 2006-02-15 devnull };
267 27b457ae 2006-02-15 devnull
268 27b457ae 2006-02-15 devnull static int
269 27b457ae 2006-02-15 devnull tcpannounce(char *mntpt)
270 27b457ae 2006-02-15 devnull {
271 27b457ae 2006-02-15 devnull int fd;
272 27b457ae 2006-02-15 devnull
273 27b457ae 2006-02-15 devnull USED(mntpt);
274 49a1496c 2006-02-20 devnull if((fd=announce(tcpaddr, adir)) < 0)
275 49a1496c 2006-02-20 devnull warning("announce %s: %r", tcpaddr);
276 27b457ae 2006-02-15 devnull return fd;
277 27b457ae 2006-02-15 devnull }
278 27b457ae 2006-02-15 devnull
279 27b457ae 2006-02-15 devnull void
280 27b457ae 2006-02-15 devnull dntcpserver(void *v)
281 27b457ae 2006-02-15 devnull {
282 27b457ae 2006-02-15 devnull int i, fd;
283 27b457ae 2006-02-15 devnull
284 19256e0d 2006-02-17 devnull while((fd = tcpannounce(v)) < 0)
285 27b457ae 2006-02-15 devnull sleep(5*1000);
286 27b457ae 2006-02-15 devnull
287 27b457ae 2006-02-15 devnull for(i=0; i<Maxactivetcp; i++)
288 19256e0d 2006-02-17 devnull proccreate(tcpproc, (void*)(uintptr)fd, STACK);
289 27b457ae 2006-02-15 devnull }