15 static char *servername;
17 static RR *serveraddrs;
21 uchar ipaddr[IPaddrlen]; /* my ip address */
22 char *logfile = "dnsdebug";
31 char *zonerefreshprogram;
33 void docmd(int, char**);
34 void doquery(char*, char*);
35 void preloadserveraddrs(void);
36 int prettyrrfmt(Fmt*);
38 void squirrelserveraddrs(void);
43 fprint(2, "%s: [-rx] [-f db-file] [[@server] domain [type]]\n", argv0);
48 main(int argc, char *argv[])
55 strcpy(mntpt, "/net");
60 dbfile = EARGF(usage());
66 dbfile = "/lib/ndb/external";
67 strcpy(mntpt, "/net.alt");
76 fmtinstall('R', prettyrrfmt);
77 if(myipaddr(ipaddr, mntpt) < 0)
78 sysfatal("can't read my ip address");
82 squirrelserveraddrs();
92 for(print("> "); p = Brdline(&in, '\n'); print("> ")){
93 p[Blinelen(&in)-1] = 0;
94 n = tokenize(p, f, 3);
96 dnpurge(); /* flush the cache */
109 for(d = 0; t >= 24*60*60; t -= 24*60*60)
111 for(h = 0; t >= 60*60; t -= 60*60)
113 for(m = 0; t >= 60; t -= 60)
117 n += sprint(x, "%d day ", d);
119 n += sprint(x+n, "%d hr ", h);
121 n += sprint(x+n, "%d min ", m);
123 sprint(x+n, "%ld sec", t);
135 rp = va_arg(f->args, RR*);
137 strcpy(buf, "<null>");
142 e = buf + sizeof(buf);
143 p = seprint(p, e, "%-32.32s %-15.15s %-5.5s", rp->owner->name,
144 longtime(rp->db? rp->ttl: (rp->ttl - now)),
145 rrname(rp->type, buf, sizeof buf));
148 seprint(p, e, "negative rcode %d", rp->negrcode);
154 seprint(p, e, "\t%s %s", rp->cpu->name, rp->os->name);
161 seprint(p, e, "\t%s", (rp->host? rp->host->name: ""));
165 seprint(p, e, "\t%s", (rp->mb? rp->mb->name: ""));
168 seprint(p, e, "\t%s %s", (rp->mb? rp->mb->name: ""),
169 (rp->rmb? rp->rmb->name: ""));
172 seprint(p, e, "\t%lud %s", rp->pref,
173 (rp->host? rp->host->name: ""));
177 seprint(p, e, "\t%s", (rp->ip? rp->ip->name: ""));
180 seprint(p, e, "\t%s", (rp->ptr? rp->ptr->name: ""));
183 seprint(p, e, "\t%s %s %lud %lud %lud %lud %lud",
184 rp->host->name, rp->rmb->name, rp->soa->serial,
185 rp->soa->refresh, rp->soa->retry,
186 rp->soa->expire, rp->soa->minttl);
189 seprint(p, e, "\t%ud %ud %ud %s",
190 rp->srv->pri, rp->srv->weight, rp->port, rp->host->name);
193 seprint(p, e, "\t%.*H", rp->null->dlen, rp->null->data);
196 p = seprint(p, e, "\t");
197 for(t = rp->txt; t != nil; t = t->next)
198 p = seprint(p, e, "%s", t->p);
201 seprint(p, e, "\t%s %s", rp->rmb->name, rp->rp->name);
204 seprint(p, e, "\t%d %d %d", rp->key->flags, rp->key->proto,
208 seprint(p, e, "\t%d %d %d %lud %lud %lud %d %s",
209 rp->sig->type, rp->sig->alg, rp->sig->labels,
210 rp->sig->ttl, rp->sig->exp, rp->sig->incep,
211 rp->sig->tag, rp->sig->signer->name);
214 seprint(p, e, "\t%d %d %d",
215 rp->sig->type, rp->sig->tag, rp->sig->alg);
219 return fmtstrcpy(f, buf);
223 logsection(char *flag, RR *rp)
227 print("\t%s%R\n", flag, rp);
228 for(rp = rp->next; rp != nil; rp = rp->next)
229 print("\t %R\n", rp);
233 logreply(int id, uchar *addr, DNSmsg *mp)
236 char buf[12], resp[32];
238 switch(mp->flags & Rmask){
243 strcpy(resp, "Format error");
246 strcpy(resp, "Server failed");
249 strcpy(resp, "Nonexistent");
252 strcpy(resp, "Unimplemented");
255 strcpy(resp, "Refused");
258 sprint(resp, "%d", mp->flags & Rmask);
262 print("%d: rcvd %s from %I (%s%s%s%s%s)\n", id, resp, addr,
263 mp->flags & Fauth? "authoritative": "",
264 mp->flags & Ftrunc? " truncated": "",
265 mp->flags & Frecurse? " recurse": "",
266 mp->flags & Fcanrec? " can_recurse": "",
267 (mp->flags & (Fauth|Rmask)) == (Fauth|Rname)? " nx": "");
268 for(rp = mp->qd; rp != nil; rp = rp->next)
269 print("\tQ: %s %s\n", rp->owner->name,
270 rrname(rp->type, buf, sizeof buf));
271 logsection("Ans: ", mp->an);
272 logsection("Auth: ", mp->ns);
273 logsection("Hint: ", mp->ar);
277 logsend(int id, int subid, uchar *addr, char *sname, char *rname, int type)
281 print("%d.%d: sending to %I/%s %s %s\n", id, subid,
282 addr, sname, rname, rrname(type, buf, sizeof buf));
286 getdnsservers(int class)
290 if(servername == nil)
291 return dnsservers(class);
294 rr->owner = dnlookup("local#dns#servers", class, 1);
295 rr->host = dnlookup(servername, class, 1);
301 squirrelserveraddrs(void)
308 /* look up the resolver address first */
312 rrfreelist(serveraddrs);
314 rr = getdnsservers(Cin);
316 for(rp = rr; rp != nil; rp = rp->next){
317 attr = ipattr(rp->host->name);
318 v4 = strcmp(attr, "ip") == 0;
319 if(v4 || strcmp(attr, "ipv6") == 0){
320 *l = rralloc(v4? Ta: Taaaa);
321 (*l)->owner = rp->host;
327 req.aborttime = NS2MS(nowns) + Maxreqtm;
328 *l = dnresolve(rp->host->name, Cin, Ta, &req, 0, 0, Recurse, 0, 0);
330 *l = dnresolve(rp->host->name, Cin, Taaaa, &req,
331 0, 0, Recurse, 0, 0);
340 preloadserveraddrs(void)
345 for(rp = serveraddrs; rp != nil; rp = rp->next){
347 rrattach(first, Authoritative);
352 setserver(char *server)
354 if(servername != nil){
359 if(server == nil || *server == 0)
361 servername = strdup(server);
362 squirrelserveraddrs();
363 if(serveraddrs == nil){
364 print("can't resolve %s\n", servername);
368 return cfg.resolver? 0: -1;
372 doquery(char *name, char *tstr)
374 int len, type, rooted;
381 preloadserveraddrs();
383 /* default to an "ip" request if alpha, "ptr" if numeric */
384 if(tstr == nil || *tstr == 0)
385 if(strcmp(ipattr(name), "ip") == 0)
390 /* if name end in '.', remove it */
392 if(len > 0 && name[len-1] == '.'){
398 /* inverse queries may need to be permuted */
399 strncpy(buf, name, sizeof buf);
400 if(strcmp("ptr", tstr) == 0 && cistrstr(name, ".arpa") == nil){
401 /* TODO: reversing v6 addrs is harder */
402 for(p = name; *p; p++)
411 memmove(np, p+1, len);
416 memmove(np, p+1, len);
418 strcpy(np, "in-addr.arpa"); /* TODO: ip6.arpa for v6 */
424 print("!unknown type %s\n", tstr);
428 memset(&req, 0, sizeof req);
429 getactivity(&req, 0);
431 req.aborttime = NS2MS(nowns) + Maxreqtm;
432 rr = dnresolve(buf, Cin, type, &req, 0, 0, Recurse, rooted, 0);
434 print("----------------------------\n");
435 for(rp = rr; rp; rp = rp->next)
436 print("answer %R\n", rp);
437 print("----------------------------\n");
445 docmd(int n, char **f)
454 if(setserver(f[0]+1) < 0)