19 static char *servername;
20 static RR *serveraddrs;
30 uchar ipaddr[IPaddrlen]; /* my ip address */
32 char *logfile = "dns";
35 char *zonerefreshprogram;
39 int prettyrrfmt(Fmt*);
40 void preloadserveraddrs(void);
41 void squirrelserveraddrs(void);
43 void doquery(char*, char*);
44 void docmd(int, char**);
49 fprint(2, "usage: dnsdebug [-fr] [query ...]\n");
50 threadexitsall("usage");
54 threadmain(int argc, char *argv[])
61 strcpy(mntpt, "/net");
68 dbfile = EARGF(usage());
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);
113 for(d = 0; t >= 24*60*60; t -= 24*60*60)
115 for(h = 0; t >= 60*60; t -= 60*60)
117 for(m = 0; t >= 60; t -= 60)
121 n += sprint(x, "%d day ", d);
123 n += sprint(x+n, "%d hr ", h);
125 n += sprint(x+n, "%d min ", m);
127 sprint(x+n, "%ld sec", t);
139 rp = va_arg(f->args, RR*);
141 strcpy(buf, "<null>");
146 e = buf + sizeof(buf);
147 p = seprint(p, e, "%-32.32s %-15.15s %-5.5s", rp->owner->name,
148 longtime(rp->db ? rp->ttl : (rp->ttl-now)),
149 rrname(rp->type, buf, sizeof buf));
152 seprint(p, e, "negative rcode %d\n", rp->negrcode);
158 seprint(p, e, "\t%s %s", rp->cpu->name, rp->os->name);
165 seprint(p, e, "\t%s", rp->host->name);
169 seprint(p, e, "\t%s", rp->mb->name);
172 seprint(p, e, "\t%s %s", rp->mb->name, rp->rmb->name);
175 seprint(p, e, "\t%lud %s", rp->pref, rp->host->name);
179 seprint(p, e, "\t%s", rp->ip->name);
182 seprint(p, e, "\t%s", rp->ptr->name);
185 seprint(p, e, "\t%s %s %lud %lud %lud %lud %lud", rp->host->name,
186 rp->rmb->name, rp->soa->serial, rp->soa->refresh, rp->soa->retry,
187 rp->soa->expire, rp->soa->minttl);
190 seprint(p, e, "\t%.*H", rp->null->dlen, rp->null->data);
193 p = seprint(p, e, "\t");
194 for(t = rp->txt; t != nil; t = t->next)
195 p = seprint(p, e, "%s", t->p);
198 seprint(p, e, "\t%s %s", rp->rmb->name, rp->rp->name);
201 seprint(p, e, "\t%d %d %d", rp->key->flags, rp->key->proto,
205 seprint(p, e, "\t%d %d %d %lud %lud %lud %d %s",
206 rp->sig->type, rp->sig->alg, rp->sig->labels, rp->sig->ttl,
207 rp->sig->exp, rp->sig->incep, rp->sig->tag, rp->sig->signer->name);
210 seprint(p, e, "\t%d %d %d",
211 rp->sig->type, rp->sig->tag, rp->sig->alg);
217 return fmtstrcpy(f, buf);
221 logsection(char *flag, RR *rp)
225 print("\t%s%R\n", flag, rp);
226 for(rp = rp->next; rp != nil; rp = rp->next)
227 print("\t %R\n", rp);
231 logreply(int id, uchar *addr, DNSmsg *mp)
237 switch(mp->flags & Rmask){
242 strcpy(resp, "Format error");
245 strcpy(resp, "Server failed");
248 strcpy(resp, "Nonexistent");
251 strcpy(resp, "Unimplemented");
254 strcpy(resp, "Refused");
257 sprint(resp, "%d", mp->flags & Rmask);
261 print("%d: rcvd %s from %I (%s%s%s%s%s)\n", id, resp, addr,
262 mp->flags & Fauth ? "authoritative" : "",
263 mp->flags & Ftrunc ? " truncated" : "",
264 mp->flags & Frecurse ? " recurse" : "",
265 mp->flags & Fcanrec ? " can_recurse" : "",
266 mp->flags & (Fauth|Rname) == (Fauth|Rname) ?
268 for(rp = mp->qd; rp != nil; rp = rp->next)
269 print("\tQ: %s %s\n", rp->owner->name, rrname(rp->type, buf, sizeof buf));
270 logsection("Ans: ", mp->an);
271 logsection("Auth: ", mp->ns);
272 logsection("Hint: ", mp->ar);
276 logsend(int id, int subid, uchar *addr, char *sname, char *rname, int type)
280 print("%d.%d: sending to %I/%s %s %s\n", id, subid,
281 addr, sname, rname, rrname(type, buf, sizeof buf));
285 getdnsservers(int class)
289 if(servername == nil)
290 return dnsservers(class);
293 rr->owner = dnlookup("local#dns#servers", class, 1);
294 rr->host = dnlookup(servername, class, 1);
300 squirrelserveraddrs(void)
305 /* look up the resolver address first */
309 rrfreelist(serveraddrs);
311 rr = getdnsservers(Cin);
313 for(rp = rr; rp != nil; rp = rp->next){
314 if(strcmp(ipattr(rp->host->name), "ip") == 0){
316 (*l)->owner = rp->host;
321 req.aborttime = now + 60; /* don't spend more than 60 seconds */
322 *l = dnresolve(rp->host->name, Cin, Ta, &req, 0, 0, Recurse, 0, 0);
331 preloadserveraddrs(void)
336 for(rp = serveraddrs; rp != nil; rp = rp->next){
343 setserver(char *server)
345 if(servername != nil){
350 if(server == nil || *server == 0)
352 servername = strdup(server);
353 squirrelserveraddrs();
354 if(serveraddrs == nil){
355 print("can't resolve %s\n", servername);
360 return resolver ? 0 : -1;
364 doquery(char *name, char *tstr)
374 preloadserveraddrs();
376 /* default to an "ip" request if alpha, "ptr" if numeric */
377 if(tstr == nil || *tstr == 0) {
378 if(strcmp(ipattr(name), "ip") == 0)
384 /* if name end in '.', remove it */
386 if(len > 0 && name[len-1] == '.'){
392 /* inverse queries may need to be permuted */
393 strncpy(buf, name, sizeof buf);
394 if(strcmp("ptr", tstr) == 0
395 && strstr(name, "IN-ADDR") == 0
396 && strstr(name, "in-addr") == 0){
397 for(p = name; *p; p++)
406 memmove(np, p+1, len);
411 memmove(np, p+1, len);
413 strcpy(np, "in-addr.arpa");
419 print("!unknown type %s\n", tstr);
424 req.aborttime = now + 60; /* don't spend more than 60 seconds */
425 rr = dnresolve(buf, Cin, type, &req, 0, 0, Recurse, rooted, 0);
427 print("----------------------------\n");
428 for(rp = rr; rp; rp = rp->next)
429 print("answer %R\n", rp);
430 print("----------------------------\n");
438 docmd(int n, char **f)
448 if(setserver(f[0]+1) < 0)