11 char *logfile = "dns";
23 uchar ipaddr[IPaddrlen]; /* my ip address */
25 char *zonerefreshprogram;
27 static int readmsg(int, uchar*, int);
28 static void reply(int, DNSmsg*, Request*);
29 static void dnzone(DNSmsg*, DNSmsg*, Request*);
30 static void getcaller(char*);
31 static void refreshmain(char*);
34 main(int argc, char *argv[])
38 DNSmsg reqmsg, repmsg;
67 snprint(mntpt, sizeof(mntpt), "/net%s", ext);
68 if(myipaddr(ipaddr, mntpt) < 0)
69 sysfatal("can't read my ip address");
70 syslog(0, logfile, "dnstcp call from %s to %I", caller, ipaddr);
77 /* loop on requests */
78 for(;; putactivity()){
80 memset(&repmsg, 0, sizeof(repmsg));
82 len = readmsg(0, buf, sizeof(buf));
87 req.aborttime = now + 15*Min;
88 err = convM2DNS(buf, len, &reqmsg);
90 syslog(0, logfile, "server: input error: %s from %I", err, buf);
93 if(reqmsg.qdcount < 1){
94 syslog(0, logfile, "server: no questions from %I", buf);
97 if(reqmsg.flags & Fresp){
98 syslog(0, logfile, "server: reply not request from %I", buf);
101 if((reqmsg.flags & Omask) != Oquery){
102 syslog(0, logfile, "server: op %d from %I", reqmsg.flags & Omask, buf);
107 syslog(0, logfile, "%d: serve (%s) %d %s %s",
110 reqmsg.qd->owner->name,
111 rrname(reqmsg.qd->type, tname, sizeof tname));
113 /* loop through each question */
115 if(reqmsg.qd->type == Taxfr){
116 dnzone(&reqmsg, &repmsg, &req);
118 dnserver(&reqmsg, &repmsg, &req);
119 reply(1, &repmsg, &req);
120 rrfreelist(repmsg.qd);
121 rrfreelist(repmsg.an);
122 rrfreelist(repmsg.ns);
123 rrfreelist(repmsg.ar);
127 rrfreelist(reqmsg.qd);
128 rrfreelist(reqmsg.an);
129 rrfreelist(reqmsg.ns);
130 rrfreelist(reqmsg.ar);
141 readmsg(int fd, uchar *buf, int max)
146 if(readn(fd, x, 2) != 2)
148 n = (x[0]<<8) | x[1];
151 if(readn(fd, buf, n) != n)
157 reply(int fd, DNSmsg *rep, Request *req)
165 syslog(0, logfile, "%d: reply (%s) %s %s %ux",
167 rep->qd->owner->name,
168 rrname(rep->qd->type, tname, sizeof tname),
170 for(rp = rep->an; rp; rp = rp->next)
171 syslog(0, logfile, "an %R", rp);
172 for(rp = rep->ns; rp; rp = rp->next)
173 syslog(0, logfile, "ns %R", rp);
174 for(rp = rep->ar; rp; rp = rp->next)
175 syslog(0, logfile, "ar %R", rp);
179 len = convDNS2M(rep, buf+2, sizeof(buf) - 2);
181 abort(); /* "dnserver: converting reply" */;
184 rv = write(fd, buf, len+2);
186 syslog(0, logfile, "sending reply: %d instead of %d", rv, len+2);
192 * Hash table for domain names. The hash is based only on the
193 * first element of the domain name.
195 extern DN *ht[HTLEN];
210 inzone(DN *dp, char *name, int namelen, int depth)
216 if(numelem(dp->name) != depth)
218 n = strlen(dp->name);
221 if(strcmp(name, dp->name + n - namelen) != 0)
223 if(n > namelen && dp->name[n - namelen - 1] != '.')
229 dnzone(DNSmsg *reqp, DNSmsg *repp, Request *req)
233 int h, depth, found, nlen;
235 memset(repp, 0, sizeof(*repp));
237 repp->flags = Fauth | Fresp | Fcanrec | Oquery;
239 reqp->qd = reqp->qd->next;
241 dp = repp->qd->owner;
244 repp->an = rrlookup(dp, Tsoa, NOneg);
248 rrfreelist(repp->an);
250 nlen = strlen(dp->name);
252 /* construct a breadth first search of the name space (hard with a hash) */
254 for(depth = numelem(dp->name); ; depth++){
256 for(h = 0; h < HTLEN; h++)
257 for(ndp = ht[h]; ndp; ndp = ndp->next)
258 if(inzone(ndp, dp->name, nlen, depth)){
259 for(rp = ndp->rr; rp; rp = rp->next){
260 /* there shouldn't be negatives, but just in case */
264 /* don't send an soa's, ns's are enough */
279 repp->an = rrlookup(dp, Tsoa, NOneg);
281 rrfreelist(repp->an);
290 static char remote[128];
292 snprint(remote, sizeof(remote), "%s/remote", dir);
293 fd = open(remote, OREAD);
296 n = read(fd, remote, sizeof(remote)-1);
300 if(remote[n-1] == '\n')
307 refreshmain(char *net)
312 snprint(file, sizeof(file), "%s/dns", net);
314 syslog(0, logfile, "refreshing %s", file);
315 fd = open(file, ORDWR);
317 syslog(0, logfile, "can't refresh %s", file);
320 fprint(fd, "refresh");
325 * the following varies between dnsdebug and dns
328 logreply(int id, uchar *addr, DNSmsg *mp)
332 syslog(0, LOG, "%d: rcvd %I flags:%s%s%s%s%s", id, addr,
333 mp->flags & Fauth ? " auth" : "",
334 mp->flags & Ftrunc ? " trunc" : "",
335 mp->flags & Frecurse ? " rd" : "",
336 mp->flags & Fcanrec ? " ra" : "",
337 mp->flags & (Fauth|Rname) == (Fauth|Rname) ?
339 for(rp = mp->qd; rp != nil; rp = rp->next)
340 syslog(0, LOG, "%d: rcvd %I qd %s", id, addr, rp->owner->name);
341 for(rp = mp->an; rp != nil; rp = rp->next)
342 syslog(0, LOG, "%d: rcvd %I an %R", id, addr, rp);
343 for(rp = mp->ns; rp != nil; rp = rp->next)
344 syslog(0, LOG, "%d: rcvd %I ns %R", id, addr, rp);
345 for(rp = mp->ar; rp != nil; rp = rp->next)
346 syslog(0, LOG, "%d: rcvd %I ar %R", id, addr, rp);
350 logsend(int id, int subid, uchar *addr, char *sname, char *rname, int type)
354 syslog(0, LOG, "%d.%d: sending to %I/%s %s %s",
355 id, subid, addr, sname, rname, rrname(type, buf, sizeof buf));
359 getdnsservers(int class)
361 return dnsservers(class);