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 */
141 static int name2type(char*);
142 static uchar *skipquestion(uchar*, uchar*, uchar*, int);
143 static uchar *unpack(uchar*, uchar*, uchar*, Ndbtuple**, int);
144 static uchar *rrnext(uchar*, uchar*, uchar*, Ndbtuple**);
145 static Ndbtuple *rrunpack(uchar*, uchar*, uchar**, char*, ...);
148 doquery(char *name, char *type)
153 int qdcount, ancount;
155 if((nstype = name2type(type)) < 0){
156 werrstr("unknown dns type %s", type);
160 buf = malloc(MAXDNS);
164 if((n = res_search(name, Cin, nstype, buf, MAXDNS)) < 0){
170 werrstr("too much dns information");
174 qdcount = (buf[4]<<8)|buf[5];
175 ancount = (buf[6]<<8)|buf[7];
178 p = skipquestion(buf, buf+n, p, qdcount);
179 p = unpack(buf, buf+n, p, &t, ancount);
219 for(i=0; i<nelem(dnsnames); i++)
220 if(dnsnames[i].t == t)
221 return dnsnames[i].s;
226 name2type(char *name)
230 for(i=0; i<nelem(dnsnames); i++)
231 if(strcmp(name, dnsnames[i].s) == 0)
232 return dnsnames[i].t;
237 skipquestion(uchar *buf, uchar *ebuf, uchar *p, int n)
243 if((len = dn_expand(buf, ebuf, p, tmp, sizeof tmp)) <= 0)
251 unpack(uchar *buf, uchar *ebuf, uchar *p, Ndbtuple **tt, int n)
254 Ndbtuple *first, *last, *t;
260 if((p = rrnext(buf, ebuf, p, &t)) == nil){
265 if(t == nil) /* unimplemented rr type */
271 for(last=t; last->entry; last=last->entry)
272 last->line = last->entry;
279 #define G2(p) nhgets(p)
280 #define G4(p) nhgetl(p)
283 rrnext(uchar *buf, uchar *ebuf, uchar *p, Ndbtuple **tt)
299 if((len = dn_expand(buf, ebuf, p, b, sizeof b)) < 0){
301 werrstr("corrupt dns packet");
313 first = ndbnew("ptr", b);
315 first = ndbnew("dom", b);
321 t = rrunpack(buf, ebuf, &p, "YY", "cpu", "os");
324 t = rrunpack(buf, ebuf, &p, "NN", "mbox", "mbox");
327 t = rrunpack(buf, ebuf, &p, "SN", "pref", "mx");
338 t = rrunpack(buf, ebuf, &p, "N", type2name(rrtype));
341 if(rrlen != IPv4addrlen)
343 memmove(ip, v4prefix, IPaddrlen);
344 memmove(ip+IPv4off, p, IPv4addrlen);
345 snprint(tmp, sizeof tmp, "%I", ip);
346 t = ndbnew("ip", tmp);
350 if(rrlen != IPaddrlen)
352 snprint(tmp, sizeof tmp, "%I", ip);
353 t = ndbnew("ip", tmp);
357 snprint(tmp, sizeof tmp, "%.*H", rrlen, p);
358 t = ndbnew("null", tmp);
362 t = rrunpack(buf, ebuf, &p, "Y", "txt");
366 t = rrunpack(buf, ebuf, &p, "NNLLLLL", "ns", "mbox",
367 "serial", "refresh", "retry", "expire", "ttl");
371 t = rrunpack(buf, ebuf, &p, "SCCY", "flags", "proto", "alg", "key");
375 t = rrunpack(buf, ebuf, &p, "SCCLLLSNY", "type", "alg", "labels",
376 "ttl", "exp", "incep", "tag", "signer", "sig");
380 t = rrunpack(buf, ebuf, &p, "SSCY", "type", "tag", "alg", "cert");
393 rrunpack(uchar *buf, uchar *ebuf, uchar **pp, char *fmt, ...)
399 Ndbtuple *t, *first, *last;
407 name = va_arg(arg, char*);
412 snprint(tmp, sizeof tmp, "%d", *p++);
415 snprint(tmp, sizeof tmp, "%d", G2(p));
419 snprint(tmp, sizeof tmp, "%d", G4(p));
423 if((len = dn_expand(buf, ebuf, p, tmp, sizeof tmp)) < 0)
437 t = ndbnew(name, tmp);