xref: /plan9/sys/src/cmd/ip/snoopy/dns.c (revision b1c161c21052bbfab8430c267211155c26021160)
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