1 #include <u.h>
2 #include <libc.h>
3 #include <ip.h>
4 #include "dat.h"
5 #include "protos.h"
6 #include "../../ndb/dns.h"
7
8 /* names of RR types - /sys/src/cmd/ndb/dn.c:/rrtname */
9 char *rrtname[] =
10 {
11 [Ta] "ip",
12 [Tns] "ns",
13 [Tmd] "md",
14 [Tmf] "mf",
15 [Tcname] "cname",
16 [Tsoa] "soa",
17 [Tmb] "mb",
18 [Tmg] "mg",
19 [Tmr] "mr",
20 [Tnull] "null",
21 [Twks] "wks",
22 [Tptr] "ptr",
23 [Thinfo] "hinfo",
24 [Tminfo] "minfo",
25 [Tmx] "mx",
26 [Ttxt] "txt",
27 [Trp] "rp",
28 [Tafsdb] "afsdb",
29 [Tx25] "x.25",
30 [Tisdn] "isdn",
31 [Trt] "rt",
32 [Tnsap] "nsap",
33 [Tnsapptr] "nsap-ptr",
34 [Tsig] "sig",
35 [Tkey] "key",
36 [Tpx] "px",
37 [Tgpos] "gpos",
38 [Taaaa] "ipv6",
39 [Tloc] "loc",
40 [Tnxt] "nxt",
41 [Teid] "eid",
42 [Tnimloc] "nimrod",
43 [Tsrv] "srv",
44 [Tatma] "atma",
45 [Tnaptr] "naptr",
46 [Tkx] "kx",
47 [Tcert] "cert",
48 [Ta6] "a6",
49 [Tdname] "dname",
50 [Tsink] "sink",
51 [Topt] "opt",
52 [Tapl] "apl",
53 [Tds] "ds",
54 [Tsshfp] "sshfp",
55 [Tipseckey] "ipseckey",
56 [Trrsig] "rrsig",
57 [Tnsec] "nsec",
58 [Tdnskey] "dnskey",
59 [Tspf] "spf",
60 [Tuinfo] "uinfo",
61 [Tuid] "uid",
62 [Tgid] "gid",
63 [Tunspec] "unspec",
64 [Ttkey] "tkey",
65 [Ttsig] "tsig",
66 [Tixfr] "ixfr",
67 [Taxfr] "axfr",
68 [Tmailb] "mailb",
69 [Tmaila] "maila",
70 [Tall] "all",
71 0,
72 };
73 static char*
rrtypestr(int t)74 rrtypestr(int t)
75 {
76 char buf[20];
77
78 if(t >= 0 && t < nelem(rrtname) && rrtname[t])
79 return rrtname[t];
80 snprint(buf, sizeof buf, "type%d", t);
81 return buf;
82 }
83
84 static void
fmtrr(Msg * m,RR ** rrp,int quest)85 fmtrr(Msg *m, RR **rrp, int quest)
86 {
87 Txt *t;
88 RR *rr;
89
90 rr = *rrp;
91 if(rr == nil)
92 return;
93 *rrp = rr->next;
94
95 m->p = seprint(m->p, m->e, "%s name=%s ttl=%lud",
96 rrtypestr(rr->type),
97 rr->owner->name, rr->ttl);
98 if(!quest)
99 switch(rr->type){
100 default:
101 break;
102 case Thinfo:
103 m->p = seprint(m->p, m->e, " cpu=%s os=%s",
104 rr->cpu->name, rr->os->name);
105 break;
106 case Tcname:
107 case Tmb:
108 case Tmd:
109 case Tmf:
110 case Tns:
111 m->p = seprint(m->p, m->e, " host=%s", rr->host->name);
112 break;
113 case Tmg:
114 case Tmr:
115 m->p = seprint(m->p, m->e, " mb=%s", rr->mb->name);
116 break;
117 case Tminfo:
118 m->p = seprint(m->p, m->e, " rmb=%s", rr->rmb->name);
119 m->p = seprint(m->p, m->e, " mb=%s", rr->mb->name);
120 break;
121 case Tmx:
122 m->p = seprint(m->p, m->e, " pref=%lud", rr->pref);
123 m->p = seprint(m->p, m->e, " host=%s", rr->host->name);
124 break;
125 case Ta:
126 case Taaaa:
127 m->p = seprint(m->p, m->e, " ip=%s", rr->ip->name);
128 break;
129 case Tptr:
130 m->p = seprint(m->p, m->e, " ptr=%s", rr->ptr->name);
131 break;
132 case Tsoa:
133 m->p = seprint(m->p, m->e, " host=%s", rr->host->name);
134 m->p = seprint(m->p, m->e, " rmb=%s", rr->rmb->name);
135 m->p = seprint(m->p, m->e, " soa.serial=%lud", rr->soa->serial);
136 m->p = seprint(m->p, m->e, " soa.refresh=%lud", rr->soa->refresh);
137 m->p = seprint(m->p, m->e, " soa.retry=%lud", rr->soa->retry);
138 m->p = seprint(m->p, m->e, " soa.expire=%lud", rr->soa->expire);
139 m->p = seprint(m->p, m->e, " soa.minttl=%lud", rr->soa->minttl);
140 break;
141 case Ttxt:
142 for(t=rr->txt; t; t=t->next)
143 m->p = seprint(m->p, m->e, " txt=%q", t->p);
144 break;
145 case Tnull:
146 m->p = seprint(m->p, m->e, " null=%.*H",
147 rr->null->dlen, rr->null->data);
148 break;
149 case Trp:
150 m->p = seprint(m->p, m->e, " rmb=%s", rr->rmb->name);
151 m->p = seprint(m->p, m->e, " rp=%s", rr->rp->name);
152 break;
153 case Tkey:
154 m->p = seprint(m->p, m->e, " flags=%d proto=%d alg=%d data=%.*H",
155 rr->key->flags, rr->key->proto, rr->key->alg,
156 rr->key->dlen, rr->key->data);
157 break;
158 case Tsig:
159 m->p = seprint(m->p, m->e,
160 " type=%d alg=%d labels=%d ttl=%lud exp=%lud incep=%lud tag=%d signer=%s data=%.*H",
161 rr->sig->type, rr->sig->alg, rr->sig->labels,
162 rr->sig->ttl, rr->sig->exp, rr->sig->incep, rr->sig->tag,
163 rr->sig->signer->name, rr->sig->dlen, rr->sig->data);
164 break;
165 case Tcert:
166 m->p = seprint(m->p, m->e, " type=%d tag=%d alg=%d data=%.*H",
167 rr->cert->type, rr->cert->tag, rr->cert->alg,
168 rr->cert->dlen, rr->cert->data);
169 break;
170 }
171 rrfree(rr);
172 }
173
174 void freealldn(void);
175 static Proto dnsqd, dnsan, dnsns, dnsar;
176
177 static void donext(Msg*);
178 static DNSmsg dm;
179
180 static int
p_seprint(Msg * m)181 p_seprint(Msg *m)
182 {
183 char *e;
184
185 if((e = convM2DNS(m->ps, m->pe-m->ps, &dm, nil)) != nil){
186 m->p = seprint(m->p, m->e, "error: %s", e);
187 return 0;
188 }
189 m->p = seprint(m->p, m->e, "id=%d flags=%#ux", dm.id, dm.flags);
190 donext(m);
191 return 0;
192 }
193
194 static void
donext(Msg * m)195 donext(Msg *m)
196 {
197 if(dm.qd)
198 m->pr = &dnsqd;
199 else if(dm.an)
200 m->pr = &dnsan;
201 else if(dm.ns)
202 m->pr = &dnsns;
203 else if(dm.ar)
204 m->pr = &dnsar;
205 else{
206 freealldn();
207 memset(&dm, 0, sizeof dm);
208 m->pr = nil;
209 }
210 }
211
212 static int
p_seprintqd(Msg * m)213 p_seprintqd(Msg *m)
214 {
215 fmtrr(m, &dm.qd, 1);
216 donext(m);
217 return 0;
218 }
219
220 static int
p_seprintan(Msg * m)221 p_seprintan(Msg *m)
222 {
223 fmtrr(m, &dm.an, 0);
224 donext(m);
225 return 0;
226 }
227
228 static int
p_seprintns(Msg * m)229 p_seprintns(Msg *m)
230 {
231 fmtrr(m, &dm.ns, 1);
232 donext(m);
233 return 0;
234 }
235
236 static int
p_seprintar(Msg * m)237 p_seprintar(Msg *m)
238 {
239 fmtrr(m, &dm.ar, 1);
240 donext(m);
241 return 0;
242 }
243
244 Proto dns =
245 {
246 "dns",
247 nil,
248 nil,
249 p_seprint,
250 nil,
251 nil,
252 nil,
253 defaultframer,
254 };
255
256 static Proto dnsqd =
257 {
258 "dns.qd",
259 nil,
260 nil,
261 p_seprintqd,
262 nil,
263 nil,
264 nil,
265 defaultframer,
266 };
267
268 static Proto dnsan =
269 {
270 "dns.an",
271 nil,
272 nil,
273 p_seprintan,
274 nil,
275 nil,
276 nil,
277 defaultframer,
278 };
279
280 static Proto dnsns =
281 {
282 "dns.ns",
283 nil,
284 nil,
285 p_seprintns,
286 nil,
287 nil,
288 nil,
289 defaultframer,
290 };
291
292 static Proto dnsar =
293 {
294 "dns.ar",
295 nil,
296 nil,
297 p_seprintar,
298 nil,
299 nil,
300 nil,
301 defaultframer,
302 };
303
304
305 void*
emalloc(int n)306 emalloc(int n)
307 {
308 void *v;
309
310 v = mallocz(n, 1);
311 if(v == nil)
312 sysfatal("out of memory");
313 return v;
314 }
315
316 char*
estrdup(char * s)317 estrdup(char *s)
318 {
319 s = strdup(s);
320 if(s == nil)
321 sysfatal("out of memory");
322 return s;
323 }
324
325 DN *alldn;
326
327 DN*
dnlookup(char * name,int class,int)328 dnlookup(char *name, int class, int)
329 {
330 DN *dn;
331
332 dn = emalloc(sizeof *dn);
333 dn->name = estrdup(name);
334 dn->class = class;
335 dn->magic = DNmagic;
336 dn->next = alldn;
337 alldn = dn;
338 return dn;
339 }
340
341 void
freealldn(void)342 freealldn(void)
343 {
344 DN *dn;
345
346 while(dn = alldn){
347 alldn = dn->next;
348 free(dn->name);
349 free(dn);
350 }
351 }
352
353 int debug; /* for ndb/dns.h */
354 ulong now = 0;
355
356 void
dnslog(char * fmt,...)357 dnslog(char *fmt, ...) /* don't log */
358 {
359 USED(fmt);
360 }
361
362 /*************************************************
363 * Everything below here is copied from /sys/src/cmd/ndb/dn.c
364 * without modification and can be recopied to update.
365 */
366
367 /*
368 * convert an integer RR type to it's ascii name
369 */
370 char*
rrname(int type,char * buf,int len)371 rrname(int type, char *buf, int len)
372 {
373 char *t;
374
375 t = nil;
376 if(type >= 0 && type <= Tall)
377 t = rrtname[type];
378 if(t==nil){
379 snprint(buf, len, "%d", type);
380 t = buf;
381 }
382 return t;
383 }
384
385 /*
386 * free a list of resource records and any related structs
387 */
388 void
rrfreelist(RR * rp)389 rrfreelist(RR *rp)
390 {
391 RR *next;
392
393 for(; rp; rp = next){
394 next = rp->next;
395 rrfree(rp);
396 }
397 }
398
399 void
freeserverlist(Server * s)400 freeserverlist(Server *s)
401 {
402 Server *next;
403
404 for(; s != nil; s = next){
405 next = s->next;
406 free(s);
407 }
408 }
409
410 /*
411 * allocate a resource record of a given type
412 */
413 RR*
rralloc(int type)414 rralloc(int type)
415 {
416 RR *rp;
417
418 rp = emalloc(sizeof(*rp));
419 rp->magic = RRmagic;
420 rp->pc = getcallerpc(&type);
421 rp->type = type;
422 setmalloctag(rp, rp->pc);
423 switch(type){
424 case Tsoa:
425 rp->soa = emalloc(sizeof(*rp->soa));
426 rp->soa->slaves = nil;
427 setmalloctag(rp->soa, rp->pc);
428 break;
429 case Tsrv:
430 rp->srv = emalloc(sizeof(*rp->srv));
431 setmalloctag(rp->srv, rp->pc);
432 break;
433 case Tkey:
434 rp->key = emalloc(sizeof(*rp->key));
435 setmalloctag(rp->key, rp->pc);
436 break;
437 case Tcert:
438 rp->cert = emalloc(sizeof(*rp->cert));
439 setmalloctag(rp->cert, rp->pc);
440 break;
441 case Tsig:
442 rp->sig = emalloc(sizeof(*rp->sig));
443 setmalloctag(rp->sig, rp->pc);
444 break;
445 case Tnull:
446 rp->null = emalloc(sizeof(*rp->null));
447 setmalloctag(rp->null, rp->pc);
448 break;
449 }
450 rp->ttl = 0;
451 rp->expire = 0;
452 rp->next = 0;
453 return rp;
454 }
455
456 /*
457 * free a resource record and any related structs
458 */
459 void
rrfree(RR * rp)460 rrfree(RR *rp)
461 {
462 DN *dp;
463 RR *nrp;
464 Txt *t;
465
466 assert(rp->magic = RRmagic);
467 assert(!rp->cached);
468
469 dp = rp->owner;
470 if(dp){
471 assert(dp->magic == DNmagic);
472 for(nrp = dp->rr; nrp; nrp = nrp->next)
473 assert(nrp != rp); /* "rrfree of live rr" */
474 }
475
476 switch(rp->type){
477 case Tsoa:
478 freeserverlist(rp->soa->slaves);
479 memset(rp->soa, 0, sizeof *rp->soa); /* cause trouble */
480 free(rp->soa);
481 break;
482 case Tsrv:
483 memset(rp->srv, 0, sizeof *rp->srv); /* cause trouble */
484 free(rp->srv);
485 break;
486 case Tkey:
487 free(rp->key->data);
488 memset(rp->key, 0, sizeof *rp->key); /* cause trouble */
489 free(rp->key);
490 break;
491 case Tcert:
492 free(rp->cert->data);
493 memset(rp->cert, 0, sizeof *rp->cert); /* cause trouble */
494 free(rp->cert);
495 break;
496 case Tsig:
497 free(rp->sig->data);
498 memset(rp->sig, 0, sizeof *rp->sig); /* cause trouble */
499 free(rp->sig);
500 break;
501 case Tnull:
502 free(rp->null->data);
503 memset(rp->null, 0, sizeof *rp->null); /* cause trouble */
504 free(rp->null);
505 break;
506 case Ttxt:
507 while(rp->txt != nil){
508 t = rp->txt;
509 rp->txt = t->next;
510 free(t->p);
511 memset(t, 0, sizeof *t); /* cause trouble */
512 free(t);
513 }
514 break;
515 }
516
517 rp->magic = ~rp->magic;
518 memset(rp, 0, sizeof *rp); /* cause trouble */
519 free(rp);
520 }
521