17dd7cddfSDavid du Colombier #include <u.h>
27dd7cddfSDavid du Colombier #include <libc.h>
37dd7cddfSDavid du Colombier #include <bio.h>
47dd7cddfSDavid du Colombier #include <ctype.h>
57dd7cddfSDavid du Colombier #include <ip.h>
67dd7cddfSDavid du Colombier #include <ndb.h>
77dd7cddfSDavid du Colombier #include "dns.h"
87dd7cddfSDavid du Colombier
94f8f669cSDavid du Colombier enum {
109a747e4fSDavid du Colombier Maxrequest= 128,
117dd7cddfSDavid du Colombier };
127dd7cddfSDavid du Colombier
134f8f669cSDavid du Colombier Cfg cfg;
144f8f669cSDavid du Colombier
157dd7cddfSDavid du Colombier static char *servername;
167dd7cddfSDavid du Colombier static RR *serverrr;
177dd7cddfSDavid du Colombier static RR *serveraddrs;
187dd7cddfSDavid du Colombier
194f8f669cSDavid du Colombier char *dbfile;
205aa528faSDavid du Colombier int debug;
214f8f669cSDavid du Colombier uchar ipaddr[IPaddrlen]; /* my ip address */
224f8f669cSDavid du Colombier char *logfile = "dnsdebug";
234f8f669cSDavid du Colombier int maxage = 60*60;
244f8f669cSDavid du Colombier char mntpt[Maxpath];
254f8f669cSDavid du Colombier int needrefresh;
265aa528faSDavid du Colombier ulong now;
27a41547ffSDavid du Colombier vlong nowns;
285aa528faSDavid du Colombier int testing;
296b0d5c8bSDavid du Colombier char *trace;
304f8f669cSDavid du Colombier int traceactivity;
31dc5a79c1SDavid du Colombier char *zonerefreshprogram;
327dd7cddfSDavid du Colombier
336b0d5c8bSDavid du Colombier void docmd(int, char**);
344f8f669cSDavid du Colombier void doquery(char*, char*);
354f8f669cSDavid du Colombier void preloadserveraddrs(void);
364f8f669cSDavid du Colombier int prettyrrfmt(Fmt*);
374f8f669cSDavid du Colombier int setserver(char*);
384f8f669cSDavid du Colombier void squirrelserveraddrs(void);
394f8f669cSDavid du Colombier
404f8f669cSDavid du Colombier void
usage(void)414f8f669cSDavid du Colombier usage(void)
424f8f669cSDavid du Colombier {
43d9924332SDavid du Colombier fprint(2, "%s: [-rx] [-f db-file] [[@server] domain [type]]\n", argv0);
444f8f669cSDavid du Colombier exits("usage");
454f8f669cSDavid du Colombier }
467dd7cddfSDavid du Colombier
477dd7cddfSDavid du Colombier void
main(int argc,char * argv[])487dd7cddfSDavid du Colombier main(int argc, char *argv[])
497dd7cddfSDavid du Colombier {
507dd7cddfSDavid du Colombier int n;
517dd7cddfSDavid du Colombier Biobuf in;
5280ee5cbfSDavid du Colombier char *p;
537dd7cddfSDavid du Colombier char *f[4];
547dd7cddfSDavid du Colombier
557dd7cddfSDavid du Colombier strcpy(mntpt, "/net");
564f8f669cSDavid du Colombier cfg.inside = 1;
577dd7cddfSDavid du Colombier
587dd7cddfSDavid du Colombier ARGBEGIN{
594f8f669cSDavid du Colombier case 'f':
604f8f669cSDavid du Colombier dbfile = EARGF(usage());
614f8f669cSDavid du Colombier break;
627dd7cddfSDavid du Colombier case 'r':
634f8f669cSDavid du Colombier cfg.resolver = 1;
647dd7cddfSDavid du Colombier break;
657dd7cddfSDavid du Colombier case 'x':
667dd7cddfSDavid du Colombier dbfile = "/lib/ndb/external";
677dd7cddfSDavid du Colombier strcpy(mntpt, "/net.alt");
687dd7cddfSDavid du Colombier break;
694f8f669cSDavid du Colombier default:
704f8f669cSDavid du Colombier usage();
717dd7cddfSDavid du Colombier }ARGEND
727dd7cddfSDavid du Colombier
734f8f669cSDavid du Colombier now = time(nil);
74e02f7f02SDavid du Colombier nowns = nsec();
757dd7cddfSDavid du Colombier dninit();
769a747e4fSDavid du Colombier fmtinstall('R', prettyrrfmt);
779a747e4fSDavid du Colombier if(myipaddr(ipaddr, mntpt) < 0)
787dd7cddfSDavid du Colombier sysfatal("can't read my ip address");
797dd7cddfSDavid du Colombier opendatabase();
807dd7cddfSDavid du Colombier
814f8f669cSDavid du Colombier if(cfg.resolver)
827dd7cddfSDavid du Colombier squirrelserveraddrs();
837dd7cddfSDavid du Colombier
847dd7cddfSDavid du Colombier debug = 1;
857dd7cddfSDavid du Colombier
867dd7cddfSDavid du Colombier if(argc > 0){
877dd7cddfSDavid du Colombier docmd(argc, argv);
887dd7cddfSDavid du Colombier exits(0);
897dd7cddfSDavid du Colombier }
907dd7cddfSDavid du Colombier
917dd7cddfSDavid du Colombier Binit(&in, 0, OREAD);
927dd7cddfSDavid du Colombier for(print("> "); p = Brdline(&in, '\n'); print("> ")){
937dd7cddfSDavid du Colombier p[Blinelen(&in)-1] = 0;
947dd7cddfSDavid du Colombier n = tokenize(p, f, 3);
954f8f669cSDavid du Colombier if(n>=1) {
964f8f669cSDavid du Colombier dnpurge(); /* flush the cache */
977dd7cddfSDavid du Colombier docmd(n, f);
984f8f669cSDavid du Colombier }
997dd7cddfSDavid du Colombier }
1007dd7cddfSDavid du Colombier exits(0);
1017dd7cddfSDavid du Colombier }
1027dd7cddfSDavid du Colombier
1037dd7cddfSDavid du Colombier static char*
longtime(long t)1047dd7cddfSDavid du Colombier longtime(long t)
1057dd7cddfSDavid du Colombier {
1067dd7cddfSDavid du Colombier int d, h, m, n;
1077dd7cddfSDavid du Colombier static char x[128];
1087dd7cddfSDavid du Colombier
1097dd7cddfSDavid du Colombier for(d = 0; t >= 24*60*60; t -= 24*60*60)
1107dd7cddfSDavid du Colombier d++;
1117dd7cddfSDavid du Colombier for(h = 0; t >= 60*60; t -= 60*60)
1127dd7cddfSDavid du Colombier h++;
1137dd7cddfSDavid du Colombier for(m = 0; t >= 60; t -= 60)
1147dd7cddfSDavid du Colombier m++;
1157dd7cddfSDavid du Colombier n = 0;
1167dd7cddfSDavid du Colombier if(d)
1177dd7cddfSDavid du Colombier n += sprint(x, "%d day ", d);
1187dd7cddfSDavid du Colombier if(h)
1197dd7cddfSDavid du Colombier n += sprint(x+n, "%d hr ", h);
1207dd7cddfSDavid du Colombier if(m)
1217dd7cddfSDavid du Colombier n += sprint(x+n, "%d min ", m);
1227dd7cddfSDavid du Colombier if(t || n == 0)
1237dd7cddfSDavid du Colombier sprint(x+n, "%ld sec", t);
1247dd7cddfSDavid du Colombier return x;
1257dd7cddfSDavid du Colombier }
1267dd7cddfSDavid du Colombier
1277dd7cddfSDavid du Colombier int
prettyrrfmt(Fmt * f)1289a747e4fSDavid du Colombier prettyrrfmt(Fmt *f)
1297dd7cddfSDavid du Colombier {
1307dd7cddfSDavid du Colombier RR *rp;
1317dd7cddfSDavid du Colombier char buf[3*Domlen];
1327dd7cddfSDavid du Colombier char *p, *e;
1338754a1dfSDavid du Colombier Txt *t;
1347dd7cddfSDavid du Colombier
1359a747e4fSDavid du Colombier rp = va_arg(f->args, RR*);
1367dd7cddfSDavid du Colombier if(rp == 0){
1377dd7cddfSDavid du Colombier strcpy(buf, "<null>");
1387dd7cddfSDavid du Colombier goto out;
1397dd7cddfSDavid du Colombier }
1407dd7cddfSDavid du Colombier
1417dd7cddfSDavid du Colombier p = buf;
1427dd7cddfSDavid du Colombier e = buf + sizeof(buf);
1437dd7cddfSDavid du Colombier p = seprint(p, e, "%-32.32s %-15.15s %-5.5s", rp->owner->name,
1447dd7cddfSDavid du Colombier longtime(rp->db? rp->ttl: (rp->ttl - now)),
1459a747e4fSDavid du Colombier rrname(rp->type, buf, sizeof buf));
1467dd7cddfSDavid du Colombier
1477dd7cddfSDavid du Colombier if(rp->negative){
14872061b92SDavid du Colombier seprint(p, e, "negative rcode %d", rp->negrcode);
1497dd7cddfSDavid du Colombier goto out;
1507dd7cddfSDavid du Colombier }
1517dd7cddfSDavid du Colombier
1527dd7cddfSDavid du Colombier switch(rp->type){
1537dd7cddfSDavid du Colombier case Thinfo:
1547dd7cddfSDavid du Colombier seprint(p, e, "\t%s %s", rp->cpu->name, rp->os->name);
1557dd7cddfSDavid du Colombier break;
1567dd7cddfSDavid du Colombier case Tcname:
1577dd7cddfSDavid du Colombier case Tmb:
1587dd7cddfSDavid du Colombier case Tmd:
1597dd7cddfSDavid du Colombier case Tmf:
1607dd7cddfSDavid du Colombier case Tns:
1614f8f669cSDavid du Colombier seprint(p, e, "\t%s", (rp->host? rp->host->name: ""));
1627dd7cddfSDavid du Colombier break;
1637dd7cddfSDavid du Colombier case Tmg:
1647dd7cddfSDavid du Colombier case Tmr:
1654f8f669cSDavid du Colombier seprint(p, e, "\t%s", (rp->mb? rp->mb->name: ""));
1667dd7cddfSDavid du Colombier break;
1677dd7cddfSDavid du Colombier case Tminfo:
1684f8f669cSDavid du Colombier seprint(p, e, "\t%s %s", (rp->mb? rp->mb->name: ""),
1694f8f669cSDavid du Colombier (rp->rmb? rp->rmb->name: ""));
1707dd7cddfSDavid du Colombier break;
1717dd7cddfSDavid du Colombier case Tmx:
1724f8f669cSDavid du Colombier seprint(p, e, "\t%lud %s", rp->pref,
1734f8f669cSDavid du Colombier (rp->host? rp->host->name: ""));
1747dd7cddfSDavid du Colombier break;
1757dd7cddfSDavid du Colombier case Ta:
1765d459b5aSDavid du Colombier case Taaaa:
1774f8f669cSDavid du Colombier seprint(p, e, "\t%s", (rp->ip? rp->ip->name: ""));
1787dd7cddfSDavid du Colombier break;
1797dd7cddfSDavid du Colombier case Tptr:
1804f8f669cSDavid du Colombier seprint(p, e, "\t%s", (rp->ptr? rp->ptr->name: ""));
1817dd7cddfSDavid du Colombier break;
1827dd7cddfSDavid du Colombier case Tsoa:
1834f8f669cSDavid du Colombier seprint(p, e, "\t%s %s %lud %lud %lud %lud %lud",
1844f8f669cSDavid du Colombier rp->host->name, rp->rmb->name, rp->soa->serial,
1854f8f669cSDavid du Colombier rp->soa->refresh, rp->soa->retry,
1867dd7cddfSDavid du Colombier rp->soa->expire, rp->soa->minttl);
1877dd7cddfSDavid du Colombier break;
1884f8f669cSDavid du Colombier case Tsrv:
1894f8f669cSDavid du Colombier seprint(p, e, "\t%ud %ud %ud %s",
190225077b0SDavid du Colombier rp->srv->pri, rp->srv->weight, rp->port, rp->host->name);
1914f8f669cSDavid du Colombier break;
1929a747e4fSDavid du Colombier case Tnull:
1939a747e4fSDavid du Colombier seprint(p, e, "\t%.*H", rp->null->dlen, rp->null->data);
1949a747e4fSDavid du Colombier break;
1957dd7cddfSDavid du Colombier case Ttxt:
1968754a1dfSDavid du Colombier p = seprint(p, e, "\t");
1978754a1dfSDavid du Colombier for(t = rp->txt; t != nil; t = t->next)
1988754a1dfSDavid du Colombier p = seprint(p, e, "%s", t->p);
1997dd7cddfSDavid du Colombier break;
2007dd7cddfSDavid du Colombier case Trp:
2018754a1dfSDavid du Colombier seprint(p, e, "\t%s %s", rp->rmb->name, rp->rp->name);
2027dd7cddfSDavid du Colombier break;
2037dd7cddfSDavid du Colombier case Tkey:
2047dd7cddfSDavid du Colombier seprint(p, e, "\t%d %d %d", rp->key->flags, rp->key->proto,
2057dd7cddfSDavid du Colombier rp->key->alg);
2067dd7cddfSDavid du Colombier break;
2077dd7cddfSDavid du Colombier case Tsig:
2087dd7cddfSDavid du Colombier seprint(p, e, "\t%d %d %d %lud %lud %lud %d %s",
2094f8f669cSDavid du Colombier rp->sig->type, rp->sig->alg, rp->sig->labels,
2104f8f669cSDavid du Colombier rp->sig->ttl, rp->sig->exp, rp->sig->incep,
2114f8f669cSDavid du Colombier rp->sig->tag, rp->sig->signer->name);
2127dd7cddfSDavid du Colombier break;
2137dd7cddfSDavid du Colombier case Tcert:
2147dd7cddfSDavid du Colombier seprint(p, e, "\t%d %d %d",
2157dd7cddfSDavid du Colombier rp->sig->type, rp->sig->tag, rp->sig->alg);
2167dd7cddfSDavid du Colombier break;
2177dd7cddfSDavid du Colombier }
2187dd7cddfSDavid du Colombier out:
2199a747e4fSDavid du Colombier return fmtstrcpy(f, buf);
2207dd7cddfSDavid du Colombier }
2217dd7cddfSDavid du Colombier
2227dd7cddfSDavid du Colombier void
logsection(char * flag,RR * rp)2237dd7cddfSDavid du Colombier logsection(char *flag, RR *rp)
2247dd7cddfSDavid du Colombier {
2257dd7cddfSDavid du Colombier if(rp == nil)
2267dd7cddfSDavid du Colombier return;
2277dd7cddfSDavid du Colombier print("\t%s%R\n", flag, rp);
2287dd7cddfSDavid du Colombier for(rp = rp->next; rp != nil; rp = rp->next)
2297dd7cddfSDavid du Colombier print("\t %R\n", rp);
2307dd7cddfSDavid du Colombier }
2317dd7cddfSDavid du Colombier
2327dd7cddfSDavid du Colombier void
logreply(int id,uchar * addr,DNSmsg * mp)2337dd7cddfSDavid du Colombier logreply(int id, uchar *addr, DNSmsg *mp)
2347dd7cddfSDavid du Colombier {
2357dd7cddfSDavid du Colombier RR *rp;
2364f8f669cSDavid du Colombier char buf[12], resp[32];
2377dd7cddfSDavid du Colombier
2387dd7cddfSDavid du Colombier switch(mp->flags & Rmask){
2397dd7cddfSDavid du Colombier case Rok:
2407dd7cddfSDavid du Colombier strcpy(resp, "OK");
2417dd7cddfSDavid du Colombier break;
2427dd7cddfSDavid du Colombier case Rformat:
2437dd7cddfSDavid du Colombier strcpy(resp, "Format error");
2447dd7cddfSDavid du Colombier break;
2457dd7cddfSDavid du Colombier case Rserver:
2467dd7cddfSDavid du Colombier strcpy(resp, "Server failed");
2477dd7cddfSDavid du Colombier break;
2487dd7cddfSDavid du Colombier case Rname:
2497dd7cddfSDavid du Colombier strcpy(resp, "Nonexistent");
2507dd7cddfSDavid du Colombier break;
2517dd7cddfSDavid du Colombier case Runimplimented:
2527dd7cddfSDavid du Colombier strcpy(resp, "Unimplemented");
2537dd7cddfSDavid du Colombier break;
2547dd7cddfSDavid du Colombier case Rrefused:
2557dd7cddfSDavid du Colombier strcpy(resp, "Refused");
2567dd7cddfSDavid du Colombier break;
2577dd7cddfSDavid du Colombier default:
2587dd7cddfSDavid du Colombier sprint(resp, "%d", mp->flags & Rmask);
2597dd7cddfSDavid du Colombier break;
2607dd7cddfSDavid du Colombier }
2617dd7cddfSDavid du Colombier
2627dd7cddfSDavid du Colombier print("%d: rcvd %s from %I (%s%s%s%s%s)\n", id, resp, addr,
2637dd7cddfSDavid du Colombier mp->flags & Fauth? "authoritative": "",
2647dd7cddfSDavid du Colombier mp->flags & Ftrunc? " truncated": "",
2657dd7cddfSDavid du Colombier mp->flags & Frecurse? " recurse": "",
2667dd7cddfSDavid du Colombier mp->flags & Fcanrec? " can_recurse": "",
2674f8f669cSDavid du Colombier (mp->flags & (Fauth|Rmask)) == (Fauth|Rname)? " nx": "");
2687dd7cddfSDavid du Colombier for(rp = mp->qd; rp != nil; rp = rp->next)
2694f8f669cSDavid du Colombier print("\tQ: %s %s\n", rp->owner->name,
2704f8f669cSDavid du Colombier rrname(rp->type, buf, sizeof buf));
2717dd7cddfSDavid du Colombier logsection("Ans: ", mp->an);
2727dd7cddfSDavid du Colombier logsection("Auth: ", mp->ns);
2737dd7cddfSDavid du Colombier logsection("Hint: ", mp->ar);
2747dd7cddfSDavid du Colombier }
2757dd7cddfSDavid du Colombier
2767dd7cddfSDavid du Colombier void
logsend(int id,int subid,uchar * addr,char * sname,char * rname,int type)2777dd7cddfSDavid du Colombier logsend(int id, int subid, uchar *addr, char *sname, char *rname, int type)
2787dd7cddfSDavid du Colombier {
2797dd7cddfSDavid du Colombier char buf[12];
2807dd7cddfSDavid du Colombier
2817dd7cddfSDavid du Colombier print("%d.%d: sending to %I/%s %s %s\n", id, subid,
2829a747e4fSDavid du Colombier addr, sname, rname, rrname(type, buf, sizeof buf));
2837dd7cddfSDavid du Colombier }
2847dd7cddfSDavid du Colombier
2857dd7cddfSDavid du Colombier RR*
getdnsservers(int class)2867dd7cddfSDavid du Colombier getdnsservers(int class)
2877dd7cddfSDavid du Colombier {
2887dd7cddfSDavid du Colombier RR *rr;
2897dd7cddfSDavid du Colombier
2907dd7cddfSDavid du Colombier if(servername == nil)
2917dd7cddfSDavid du Colombier return dnsservers(class);
2927dd7cddfSDavid du Colombier
2937dd7cddfSDavid du Colombier rr = rralloc(Tns);
2947dd7cddfSDavid du Colombier rr->owner = dnlookup("local#dns#servers", class, 1);
2957dd7cddfSDavid du Colombier rr->host = dnlookup(servername, class, 1);
2967dd7cddfSDavid du Colombier
2977dd7cddfSDavid du Colombier return rr;
2987dd7cddfSDavid du Colombier }
2997dd7cddfSDavid du Colombier
3007dd7cddfSDavid du Colombier void
squirrelserveraddrs(void)3017dd7cddfSDavid du Colombier squirrelserveraddrs(void)
3027dd7cddfSDavid du Colombier {
303d9924332SDavid du Colombier int v4;
304d9924332SDavid du Colombier char *attr;
3057dd7cddfSDavid du Colombier RR *rr, *rp, **l;
3067dd7cddfSDavid du Colombier Request req;
3077dd7cddfSDavid du Colombier
3087dd7cddfSDavid du Colombier /* look up the resolver address first */
3094f8f669cSDavid du Colombier cfg.resolver = 0;
3107dd7cddfSDavid du Colombier debug = 0;
3117dd7cddfSDavid du Colombier if(serveraddrs)
3127dd7cddfSDavid du Colombier rrfreelist(serveraddrs);
3137dd7cddfSDavid du Colombier serveraddrs = nil;
3147dd7cddfSDavid du Colombier rr = getdnsservers(Cin);
3157dd7cddfSDavid du Colombier l = &serveraddrs;
3167dd7cddfSDavid du Colombier for(rp = rr; rp != nil; rp = rp->next){
317d9924332SDavid du Colombier attr = ipattr(rp->host->name);
318d9924332SDavid du Colombier v4 = strcmp(attr, "ip") == 0;
319d9924332SDavid du Colombier if(v4 || strcmp(attr, "ipv6") == 0){
320d9924332SDavid du Colombier *l = rralloc(v4? Ta: Taaaa);
3217dd7cddfSDavid du Colombier (*l)->owner = rp->host;
3227dd7cddfSDavid du Colombier (*l)->ip = rp->host;
3237dd7cddfSDavid du Colombier l = &(*l)->next;
3247dd7cddfSDavid du Colombier continue;
3257dd7cddfSDavid du Colombier }
326*b2ebcd4dSDavid du Colombier memset(&req, 0, sizeof req);
3277dd7cddfSDavid du Colombier req.isslave = 1;
328e02f7f02SDavid du Colombier req.aborttime = NS2MS(nowns) + Maxreqtm;
329271b8d73SDavid du Colombier *l = dnresolve(rp->host->name, Cin, Ta, &req, 0, 0, Recurse, 0, 0);
330d9924332SDavid du Colombier if(*l == nil)
331d9924332SDavid du Colombier *l = dnresolve(rp->host->name, Cin, Taaaa, &req,
332d9924332SDavid du Colombier 0, 0, Recurse, 0, 0);
3337dd7cddfSDavid du Colombier while(*l != nil)
3347dd7cddfSDavid du Colombier l = &(*l)->next;
3357dd7cddfSDavid du Colombier }
3364f8f669cSDavid du Colombier cfg.resolver = 1;
3377dd7cddfSDavid du Colombier debug = 1;
3387dd7cddfSDavid du Colombier }
3397dd7cddfSDavid du Colombier
3407dd7cddfSDavid du Colombier void
preloadserveraddrs(void)3417dd7cddfSDavid du Colombier preloadserveraddrs(void)
3427dd7cddfSDavid du Colombier {
3437dd7cddfSDavid du Colombier RR *rp, **l, *first;
3447dd7cddfSDavid du Colombier
3457dd7cddfSDavid du Colombier l = &first;
3467dd7cddfSDavid du Colombier for(rp = serveraddrs; rp != nil; rp = rp->next){
3474faf7596SDavid du Colombier lock(&dnlock);
3487dd7cddfSDavid du Colombier rrcopy(rp, l);
3494faf7596SDavid du Colombier unlock(&dnlock);
3506dc4800dSDavid du Colombier rrattach(first, Authoritative);
3517dd7cddfSDavid du Colombier }
3527dd7cddfSDavid du Colombier }
3537dd7cddfSDavid du Colombier
3547dd7cddfSDavid du Colombier int
setserver(char * server)3557dd7cddfSDavid du Colombier setserver(char *server)
3567dd7cddfSDavid du Colombier {
3577dd7cddfSDavid du Colombier if(servername != nil){
3587dd7cddfSDavid du Colombier free(servername);
3597dd7cddfSDavid du Colombier servername = nil;
3604f8f669cSDavid du Colombier cfg.resolver = 0;
3617dd7cddfSDavid du Colombier }
3627dd7cddfSDavid du Colombier if(server == nil || *server == 0)
3637dd7cddfSDavid du Colombier return 0;
3647dd7cddfSDavid du Colombier servername = strdup(server);
3657dd7cddfSDavid du Colombier squirrelserveraddrs();
3667dd7cddfSDavid du Colombier if(serveraddrs == nil){
3677dd7cddfSDavid du Colombier print("can't resolve %s\n", servername);
3684f8f669cSDavid du Colombier cfg.resolver = 0;
3694f8f669cSDavid du Colombier } else
3704f8f669cSDavid du Colombier cfg.resolver = 1;
3714f8f669cSDavid du Colombier return cfg.resolver? 0: -1;
3727dd7cddfSDavid du Colombier }
3737dd7cddfSDavid du Colombier
3747dd7cddfSDavid du Colombier void
doquery(char * name,char * tstr)3757dd7cddfSDavid du Colombier doquery(char *name, char *tstr)
3767dd7cddfSDavid du Colombier {
3774f8f669cSDavid du Colombier int len, type, rooted;
3786b0d5c8bSDavid du Colombier char *p, *np;
3796b0d5c8bSDavid du Colombier char buf[1024];
3804f8f669cSDavid du Colombier RR *rr, *rp;
3814f8f669cSDavid du Colombier Request req;
3827dd7cddfSDavid du Colombier
3834f8f669cSDavid du Colombier if(cfg.resolver)
3847dd7cddfSDavid du Colombier preloadserveraddrs();
3857dd7cddfSDavid du Colombier
3867dd7cddfSDavid du Colombier /* default to an "ip" request if alpha, "ptr" if numeric */
3874f8f669cSDavid du Colombier if(tstr == nil || *tstr == 0)
3887dd7cddfSDavid du Colombier if(strcmp(ipattr(name), "ip") == 0)
3897dd7cddfSDavid du Colombier tstr = "ptr";
3907dd7cddfSDavid du Colombier else
3917dd7cddfSDavid du Colombier tstr = "ip";
3927dd7cddfSDavid du Colombier
3937dd7cddfSDavid du Colombier /* if name end in '.', remove it */
3947dd7cddfSDavid du Colombier len = strlen(name);
395271b8d73SDavid du Colombier if(len > 0 && name[len-1] == '.'){
396271b8d73SDavid du Colombier rooted = 1;
3977dd7cddfSDavid du Colombier name[len-1] = 0;
398271b8d73SDavid du Colombier } else
399271b8d73SDavid du Colombier rooted = 0;
4007dd7cddfSDavid du Colombier
4017dd7cddfSDavid du Colombier /* inverse queries may need to be permuted */
4029a747e4fSDavid du Colombier strncpy(buf, name, sizeof buf);
40353874d13SDavid du Colombier if(strcmp("ptr", tstr) == 0 && cistrstr(name, ".arpa") == nil){
40453874d13SDavid du Colombier /* TODO: reversing v6 addrs is harder */
4057dd7cddfSDavid du Colombier for(p = name; *p; p++)
4067dd7cddfSDavid du Colombier ;
4077dd7cddfSDavid du Colombier *p = '.';
4087dd7cddfSDavid du Colombier np = buf;
4097dd7cddfSDavid du Colombier len = 0;
4107dd7cddfSDavid du Colombier while(p >= name){
4117dd7cddfSDavid du Colombier len++;
4127dd7cddfSDavid du Colombier p--;
4137dd7cddfSDavid du Colombier if(*p == '.'){
4147dd7cddfSDavid du Colombier memmove(np, p+1, len);
4157dd7cddfSDavid du Colombier np += len;
4167dd7cddfSDavid du Colombier len = 0;
4177dd7cddfSDavid du Colombier }
4187dd7cddfSDavid du Colombier }
4197dd7cddfSDavid du Colombier memmove(np, p+1, len);
4207dd7cddfSDavid du Colombier np += len;
42153874d13SDavid du Colombier strcpy(np, "in-addr.arpa"); /* TODO: ip6.arpa for v6 */
4227dd7cddfSDavid du Colombier }
4237dd7cddfSDavid du Colombier
4247dd7cddfSDavid du Colombier /* look it up */
4257dd7cddfSDavid du Colombier type = rrtype(tstr);
4267dd7cddfSDavid du Colombier if(type < 0){
4277dd7cddfSDavid du Colombier print("!unknown type %s\n", tstr);
4287dd7cddfSDavid du Colombier return;
4297dd7cddfSDavid du Colombier }
4307dd7cddfSDavid du Colombier
4314f8f669cSDavid du Colombier memset(&req, 0, sizeof req);
432b4b9fc2fSDavid du Colombier getactivity(&req, 0);
4337dd7cddfSDavid du Colombier req.isslave = 1;
434e02f7f02SDavid du Colombier req.aborttime = NS2MS(nowns) + Maxreqtm;
435271b8d73SDavid du Colombier rr = dnresolve(buf, Cin, type, &req, 0, 0, Recurse, rooted, 0);
4367dd7cddfSDavid du Colombier if(rr){
4377dd7cddfSDavid du Colombier print("----------------------------\n");
4387dd7cddfSDavid du Colombier for(rp = rr; rp; rp = rp->next)
4397dd7cddfSDavid du Colombier print("answer %R\n", rp);
4407dd7cddfSDavid du Colombier print("----------------------------\n");
4417dd7cddfSDavid du Colombier }
4427dd7cddfSDavid du Colombier rrfreelist(rr);
4437dd7cddfSDavid du Colombier
444b4b9fc2fSDavid du Colombier putactivity(0);
4457dd7cddfSDavid du Colombier }
4467dd7cddfSDavid du Colombier
4477dd7cddfSDavid du Colombier void
docmd(int n,char ** f)4487dd7cddfSDavid du Colombier docmd(int n, char **f)
4497dd7cddfSDavid du Colombier {
4507dd7cddfSDavid du Colombier int tmpsrv;
4517dd7cddfSDavid du Colombier char *name, *type;
4527dd7cddfSDavid du Colombier
4534f8f669cSDavid du Colombier name = type = nil;
4547dd7cddfSDavid du Colombier tmpsrv = 0;
4557dd7cddfSDavid du Colombier
4567dd7cddfSDavid du Colombier if(*f[0] == '@') {
4577dd7cddfSDavid du Colombier if(setserver(f[0]+1) < 0)
4587dd7cddfSDavid du Colombier return;
4597dd7cddfSDavid du Colombier
4607dd7cddfSDavid du Colombier switch(n){
4617dd7cddfSDavid du Colombier case 3:
4627dd7cddfSDavid du Colombier type = f[2];
4637dd7cddfSDavid du Colombier /* fall through */
4647dd7cddfSDavid du Colombier case 2:
4657dd7cddfSDavid du Colombier name = f[1];
4667dd7cddfSDavid du Colombier tmpsrv = 1;
4677dd7cddfSDavid du Colombier break;
4687dd7cddfSDavid du Colombier }
4694f8f669cSDavid du Colombier } else
4707dd7cddfSDavid du Colombier switch(n){
4717dd7cddfSDavid du Colombier case 2:
4727dd7cddfSDavid du Colombier type = f[1];
4737dd7cddfSDavid du Colombier /* fall through */
4747dd7cddfSDavid du Colombier case 1:
4757dd7cddfSDavid du Colombier name = f[0];
4767dd7cddfSDavid du Colombier break;
4777dd7cddfSDavid du Colombier }
4787dd7cddfSDavid du Colombier
4797dd7cddfSDavid du Colombier if(name == nil)
4807dd7cddfSDavid du Colombier return;
4817dd7cddfSDavid du Colombier
4827dd7cddfSDavid du Colombier doquery(name, type);
4837dd7cddfSDavid du Colombier
4847dd7cddfSDavid du Colombier if(tmpsrv)
4857dd7cddfSDavid du Colombier setserver("");
4867dd7cddfSDavid du Colombier }
487