2 #include <netinet/in.h>
3 #include <arpa/nameser.h>
12 static void nstrcpy(char*, char*, int);
13 static void mkptrname(char*, char*, int);
14 static Ndbtuple *doquery(char*, char*);
17 * Run a DNS lookup for val/type on net.
20 dnsquery(char *net, char *val, char *type)
30 fmtinstall('I', eipfmt);
32 /* give up early on stupid questions - vwhois */
33 if(strcmp(val, "::") == 0 || strcmp(val, "0.0.0.0") == 0)
36 /* zero out the error string */
39 /* if this is a reverse lookup, first look up the domain name */
40 if(strcmp(type, "ptr") == 0){
41 mkptrname(val, rip, sizeof rip);
42 t = doquery(rip, "ptr");
44 t = doquery(val, type);
50 * convert address into a reverse lookup address
53 mkptrname(char *ip, char *rip, int rlen)
59 if(strstr(ip, "in-addr.arpa") || strstr(ip, "IN-ADDR.ARPA")){
60 nstrcpy(rip, ip, rlen);
64 nstrcpy(buf, ip, sizeof buf);
74 memmove(np, p+1, len);
79 memmove(np, p+1, len);
81 strcpy(np, "in-addr.arpa");
85 nstrcpy(char *to, char *from, int len)
87 strncpy(to, from, len);
92 * Disgusting, ugly interface to libresolv,
93 * which everyone seems to have.
123 /* query types (all RR types are also queries) */
124 Tixfr= 251, /* incremental zone transfer */
125 Taxfr= 252, /* zone transfer */
126 Tmailb= 253, /* { Tmb, Tmg, Tmr } */
127 Tall= 255, /* all records */
130 Csym= 0, /* internal symbols */
131 Cin= 1, /* internet */
132 Ccs, /* CSNET (obsolete) */
134 Chs, /* Hesiod (?) */
136 /* class queries (all class types are also queries) */
137 Call= 255, /* all classes */
142 static int name2type(char*);
143 static uchar *skipquestion(uchar*, uchar*, uchar*, int);
144 static uchar *unpack(uchar*, uchar*, uchar*, Ndbtuple**, int);
145 static uchar *rrnext(uchar*, uchar*, uchar*, Ndbtuple**);
146 static Ndbtuple *rrunpack(uchar*, uchar*, uchar**, char*, ...);
149 doquery(char *name, char *type)
154 int qdcount, ancount;
156 if((nstype = name2type(type)) < 0){
157 werrstr("unknown dns type %s", type);
161 buf = malloc(MAXDNS);
165 if((n = res_search(name, Cin, nstype, buf, MAXDNS)) < 0){
171 werrstr("too much dns information");
175 qdcount = (buf[4]<<8)|buf[5];
176 ancount = (buf[6]<<8)|buf[7];
179 p = skipquestion(buf, buf+n, p, qdcount);
180 p = unpack(buf, buf+n, p, &t, ancount);
220 for(i=0; i<nelem(dnsnames); i++)
221 if(dnsnames[i].t == t)
222 return dnsnames[i].s;
227 name2type(char *name)
231 for(i=0; i<nelem(dnsnames); i++)
232 if(strcmp(name, dnsnames[i].s) == 0)
233 return dnsnames[i].t;
238 skipquestion(uchar *buf, uchar *ebuf, uchar *p, int n)
244 if((len = dn_expand(buf, ebuf, p, tmp, sizeof tmp)) <= 0)
252 unpack(uchar *buf, uchar *ebuf, uchar *p, Ndbtuple **tt, int n)
255 Ndbtuple *first, *last, *t;
261 if((p = rrnext(buf, ebuf, p, &t)) == nil){
266 if(t == nil) /* unimplemented rr type */
272 for(last=t; last->entry; last=last->entry)
273 last->line = last->entry;
280 #define G2(p) nhgets(p)
281 #define G4(p) nhgetl(p)
284 rrnext(uchar *buf, uchar *ebuf, uchar *p, Ndbtuple **tt)
300 if((len = dn_expand(buf, ebuf, p, b, sizeof b)) < 0){
302 werrstr("corrupt dns packet");
314 first = ndbnew("ptr", b);
316 first = ndbnew("dom", b);
322 t = rrunpack(buf, ebuf, &p, "YY", "cpu", "os");
325 t = rrunpack(buf, ebuf, &p, "NN", "mbox", "mbox");
328 t = rrunpack(buf, ebuf, &p, "SN", "pref", "mx");
339 t = rrunpack(buf, ebuf, &p, "N", type2name(rrtype));
342 if(rrlen != IPv4addrlen)
344 memmove(ip, v4prefix, IPaddrlen);
345 memmove(ip+IPv4off, p, IPv4addrlen);
346 snprint(tmp, sizeof tmp, "%I", ip);
347 t = ndbnew("ip", tmp);
351 if(rrlen != IPaddrlen)
353 snprint(tmp, sizeof tmp, "%I", ip);
354 t = ndbnew("ip", tmp);
358 snprint(tmp, sizeof tmp, "%.*H", rrlen, p);
359 t = ndbnew("null", tmp);
363 t = rrunpack(buf, ebuf, &p, "Y", "txt");
367 t = rrunpack(buf, ebuf, &p, "NNLLLLL", "ns", "mbox",
368 "serial", "refresh", "retry", "expire", "ttl");
372 t = rrunpack(buf, ebuf, &p, "SCCY", "flags", "proto", "alg", "key");
376 t = rrunpack(buf, ebuf, &p, "SCCLLLSNY", "type", "alg", "labels",
377 "ttl", "exp", "incep", "tag", "signer", "sig");
381 t = rrunpack(buf, ebuf, &p, "SSCY", "type", "tag", "alg", "cert");
394 rrunpack(uchar *buf, uchar *ebuf, uchar **pp, char *fmt, ...)
400 Ndbtuple *t, *first, *last;
408 name = va_arg(arg, char*);
413 snprint(tmp, sizeof tmp, "%d", *p++);
416 snprint(tmp, sizeof tmp, "%d", G2(p));
420 snprint(tmp, sizeof tmp, "%d", G4(p));
424 if((len = dn_expand(buf, ebuf, p, tmp, sizeof tmp)) < 0)
438 t = ndbnew(name, tmp);