12 readmsg(int fd, uchar *buf, int max)
17 if(readn(fd, x, 2) != 2)
22 if(readn(fd, buf, n) != n)
28 connreadmsg(int tfd, int *fd, uchar *buf, int max)
34 lfd = listen(adir, ldir);
37 *fd = accept(lfd, ldir);
39 n = readmsg(*fd, buf, max);
47 reply(int fd, DNSmsg *rep, Request *req, NetConnInfo *caller)
55 syslog(0, logfile, "%d: reply (%s) %s %s %ux",
56 req->id, caller ? caller->raddr : "unk",
58 rrname(rep->qd->type, tname, sizeof tname),
60 for(rp = rep->an; rp; rp = rp->next)
61 syslog(0, logfile, "an %R", rp);
62 for(rp = rep->ns; rp; rp = rp->next)
63 syslog(0, logfile, "ns %R", rp);
64 for(rp = rep->ar; rp; rp = rp->next)
65 syslog(0, logfile, "ar %R", rp);
69 len = convDNS2M(rep, buf+2, sizeof(buf) - 2);
71 abort(); /* "dnserver: converting reply" */;
74 if(write(fd, buf, len+2) < 0){
75 syslog(0, logfile, "sending reply: %r");
82 * Hash table for domain names. The hash is based only on the
83 * first element of the domain name.
100 inzone(DN *dp, char *name, int namelen, int depth)
106 if(numelem(dp->name) != depth)
108 n = strlen(dp->name);
111 if(strcmp(name, dp->name + n - namelen) != 0)
113 if(n > namelen && dp->name[n - namelen - 1] != '.')
119 dnzone(DNSmsg *reqp, DNSmsg *repp, Request *req, int rfd, NetConnInfo *caller)
123 int h, depth, found, nlen, rv;
126 memset(repp, 0, sizeof(*repp));
128 repp->flags = Fauth | Fresp | Fcanrec | Oquery;
130 reqp->qd = reqp->qd->next;
132 dp = repp->qd->owner;
135 repp->an = rrlookup(dp, Tsoa, NOneg);
136 rv = reply(rfd, repp, req, caller);
137 if(repp->an == 0 || rv < 0)
139 rrfreelist(repp->an);
141 nlen = strlen(dp->name);
143 /* construct a breadth first search of the name space (hard with a hash) */
145 for(depth = numelem(dp->name); ; depth++){
147 for(h = 0; h < HTLEN; h++)
148 for(ndp = ht[h]; ndp; ndp = ndp->next)
149 if(inzone(ndp, dp->name, nlen, depth)){
150 for(rp = ndp->rr; rp; rp = rp->next){
151 /* there shouldn't be negatives, but just in case */
155 /* don't send an soa's, ns's are enough */
161 rv = reply(rfd, repp, req, caller);
172 repp->an = rrlookup(dp, Tsoa, NOneg);
173 rv = reply(rfd, repp, req, caller);
176 rrfreelist(repp->an);
186 DNSmsg reqmsg, repmsg;
196 /* loop on requests */
197 for(;; putactivity()){
202 memset(&repmsg, 0, sizeof(repmsg));
204 len = readmsg(fd, buf, sizeof buf);
207 len = connreadmsg(fd, &rfd, buf, sizeof buf);
211 freenetconninfo(caller);
212 caller = getnetconninfo(0, fd);
214 req.aborttime = now + 15*Min;
215 err = convM2DNS(buf, len, &reqmsg);
217 syslog(0, logfile, "server: input error: %s from %I", err, buf);
220 if(reqmsg.qdcount < 1){
221 syslog(0, logfile, "server: no questions from %I", buf);
224 if(reqmsg.flags & Fresp){
225 syslog(0, logfile, "server: reply not request from %I", buf);
228 if((reqmsg.flags & Omask) != Oquery){
229 syslog(0, logfile, "server: op %d from %I", reqmsg.flags & Omask, buf);
234 syslog(0, logfile, "%d: serve (%s) %d %s %s",
235 req.id, caller ? caller->raddr : 0,
237 reqmsg.qd->owner->name,
238 rrname(reqmsg.qd->type, tname, sizeof tname));
240 /* loop through each question */
242 if(reqmsg.qd->type == Taxfr){
243 if(dnzone(&reqmsg, &repmsg, &req, rfd, caller) < 0)
246 dnserver(&reqmsg, &repmsg, &req);
247 rv = reply(rfd, &repmsg, &req, caller);
248 rrfreelist(repmsg.qd);
249 rrfreelist(repmsg.an);
250 rrfreelist(repmsg.ns);
251 rrfreelist(repmsg.ar);
257 rrfreelist(reqmsg.qd);
258 rrfreelist(reqmsg.an);
259 rrfreelist(reqmsg.ns);
260 rrfreelist(reqmsg.ar);
269 tcpannounce(char *mntpt)
274 if((fd=announce(tcpaddr, adir)) < 0)
275 warning("announce %s: %r", tcpaddr);
284 while((fd = tcpannounce(v)) < 0)
287 for(i=0; i<Maxactivetcp; i++)
288 proccreate(tcpproc, (void*)(uintptr)fd, STACK);