ref: 9ced712a2ad70557a8ceb89ff3b969b92c85f68c
dir: /sys/src/cmd/ip/snoopy/dns.c/
#include <u.h> #include <libc.h> #include <ip.h> #include "dat.h" #include "protos.h" #include "../../ndb/dns.h" /* names of RR types - /sys/src/cmd/ndb/dn.c:/rrtname */ char *rrtname[] = { [Ta] "ip", [Tns] "ns", [Tmd] "md", [Tmf] "mf", [Tcname] "cname", [Tsoa] "soa", [Tmb] "mb", [Tmg] "mg", [Tmr] "mr", [Tnull] "null", [Twks] "wks", [Tptr] "ptr", [Thinfo] "hinfo", [Tminfo] "minfo", [Tmx] "mx", [Ttxt] "txt", [Trp] "rp", [Tafsdb] "afsdb", [Tx25] "x.25", [Tisdn] "isdn", [Trt] "rt", [Tnsap] "nsap", [Tnsapptr] "nsap-ptr", [Tsig] "sig", [Tkey] "key", [Tpx] "px", [Tgpos] "gpos", [Taaaa] "ipv6", [Tloc] "loc", [Tnxt] "nxt", [Teid] "eid", [Tnimloc] "nimrod", [Tsrv] "srv", [Tatma] "atma", [Tnaptr] "naptr", [Tkx] "kx", [Tcert] "cert", [Ta6] "a6", [Tdname] "dname", [Tsink] "sink", [Topt] "opt", [Tapl] "apl", [Tds] "ds", [Tsshfp] "sshfp", [Tipseckey] "ipseckey", [Trrsig] "rrsig", [Tnsec] "nsec", [Tdnskey] "dnskey", [Tspf] "spf", [Tuinfo] "uinfo", [Tuid] "uid", [Tgid] "gid", [Tunspec] "unspec", [Ttkey] "tkey", [Ttsig] "tsig", [Tixfr] "ixfr", [Taxfr] "axfr", [Tmailb] "mailb", [Tmaila] "maila", [Tall] "all", [Tcaa] "caa", 0, }; static char* rrtypestr(int t) { static char buf[20]; if(t >= 0 && t < nelem(rrtname) && rrtname[t]) return rrtname[t]; snprint(buf, sizeof buf, "type%d", t); return buf; } static void fmtrr(Msg *m, RR **rrp, int quest) { Txt *t; RR *rr; rr = *rrp; if(rr == nil) return; *rrp = rr->next; if(rr->type == Topt){ m->p = seprint(m->p, m->e, "opt eflags=%#lux udpsize=%d data=%.*H", rr->eflags, rr->udpsize, rr->opt->dlen, rr->opt->data); rrfree(rr); return; } m->p = seprint(m->p, m->e, "%s name=%s ttl=%lud", rrtypestr(rr->type), rr->owner->name, rr->ttl); if(!quest) switch(rr->type){ case Thinfo: m->p = seprint(m->p, m->e, " cpu=%s os=%s", rr->cpu->name, rr->os->name); break; case Tcname: case Tmb: case Tmd: case Tmf: case Tns: m->p = seprint(m->p, m->e, " host=%s", rr->host->name); break; case Tmg: case Tmr: m->p = seprint(m->p, m->e, " mb=%s", rr->mb->name); break; case Tminfo: m->p = seprint(m->p, m->e, " rmb=%s", rr->rmb->name); m->p = seprint(m->p, m->e, " mb=%s", rr->mb->name); break; case Tmx: m->p = seprint(m->p, m->e, " pref=%lud", rr->pref); m->p = seprint(m->p, m->e, " host=%s", rr->host->name); break; case Ta: case Taaaa: m->p = seprint(m->p, m->e, " ip=%s", rr->ip->name); break; case Tptr: m->p = seprint(m->p, m->e, " ptr=%s", rr->ptr->name); break; case Tsoa: m->p = seprint(m->p, m->e, " host=%s", rr->host->name); m->p = seprint(m->p, m->e, " rmb=%s", rr->rmb->name); m->p = seprint(m->p, m->e, " soa.serial=%lud", rr->soa->serial); m->p = seprint(m->p, m->e, " soa.refresh=%lud", rr->soa->refresh); m->p = seprint(m->p, m->e, " soa.retry=%lud", rr->soa->retry); m->p = seprint(m->p, m->e, " soa.expire=%lud", rr->soa->expire); m->p = seprint(m->p, m->e, " soa.minttl=%lud", rr->soa->minttl); break; case Ttxt: for(t=rr->txt; t; t=t->next) m->p = seprint(m->p, m->e, " txt=\"%.*s\"", t->dlen, (char*)t->data); break; case Tnull: m->p = seprint(m->p, m->e, " null=%.*H", rr->null->dlen, rr->null->data); break; case Trp: m->p = seprint(m->p, m->e, " rmb=%s", rr->rmb->name); m->p = seprint(m->p, m->e, " rp=%s", rr->rp->name); break; case Tkey: m->p = seprint(m->p, m->e, " flags=%d proto=%d alg=%d data=%.*H", rr->key->flags, rr->key->proto, rr->key->alg, rr->key->dlen, rr->key->data); break; case Tsig: m->p = seprint(m->p, m->e, " type=%d alg=%d labels=%d ttl=%lud exp=%lud incep=%lud tag=%d signer=%s data=%.*H", rr->sig->type, rr->sig->alg, rr->sig->labels, rr->sig->ttl, rr->sig->exp, rr->sig->incep, rr->sig->tag, rr->sig->signer->name, rr->sig->dlen, rr->sig->data); break; case Tcert: m->p = seprint(m->p, m->e, " type=%d tag=%d alg=%d data=%.*H", rr->cert->type, rr->cert->tag, rr->cert->alg, rr->cert->dlen, rr->cert->data); break; case Tcaa: m->p = seprint(m->p, m->e, " flags=%d tag=%s caa=\"%.*s\"", rr->caa->flags, rr->caa->tag->name, rr->caa->dlen, (char*)rr->caa->data); break; default: if(rrsupported(rr->type)) break; m->p = seprint(m->p, m->e, " unknown=%.*H", rr->unknown->dlen, rr->unknown->data); } rrfree(rr); } void freealldn(void); static Proto dnsqd, dnsan, dnsns, dnsar; static void donext(Msg*); static void dolast(Msg*); static DNSmsg dm; static int p_seprint(Msg *m) { char *e; if((e = convM2DNS(m->ps, m->pe-m->ps, &dm, nil)) != nil){ m->p = seprint(m->p, m->e, "error: %s", e); free(e); dolast(m); return 0; } m->p = seprint(m->p, m->e, "id=%d flags=%#ux", dm.id, dm.flags); donext(m); return 0; } static void donext(Msg *m) { if(dm.qd) m->pr = &dnsqd; else if(dm.an) m->pr = &dnsan; else if(dm.ns) m->pr = &dnsns; else if(dm.ar) m->pr = &dnsar; else dolast(m); } static void dolast(Msg *m) { freealldn(); memset(&dm, 0, sizeof dm); m->pr = nil; } static int p_seprintqd(Msg *m) { fmtrr(m, &dm.qd, 1); donext(m); return 0; } static int p_seprintan(Msg *m) { fmtrr(m, &dm.an, 0); donext(m); return 0; } static int p_seprintns(Msg *m) { fmtrr(m, &dm.ns, 1); donext(m); return 0; } static int p_seprintar(Msg *m) { fmtrr(m, &dm.ar, 1); donext(m); return 0; } Proto dns = { "dns", nil, nil, p_seprint, nil, nil, nil, defaultframer, }; static Proto dnsqd = { "dns.qd", nil, nil, p_seprintqd, nil, nil, nil, defaultframer, }; static Proto dnsan = { "dns.an", nil, nil, p_seprintan, nil, nil, nil, defaultframer, }; static Proto dnsns = { "dns.ns", nil, nil, p_seprintns, nil, nil, nil, defaultframer, }; static Proto dnsar = { "dns.ar", nil, nil, p_seprintar, nil, nil, nil, defaultframer, }; void* emalloc(int n) { void *v; v = mallocz(n, 1); if(v == nil) sysfatal("out of memory"); return v; } char* estrdup(char *s) { s = strdup(s); if(s == nil) sysfatal("out of memory"); return s; } DN *alldn; DN* dnlookup(char *name, int class, int) { DN *dn; int n; n = strlen(name) + 1; dn = emalloc(sizeof(*dn) + n); memmove(dn->name, name, n); dn->class = class; dn->next = alldn; alldn = dn; return dn; } void freealldn(void) { DN *dn; while(dn = alldn){ alldn = dn->next; free(dn); } } void dnslog(char *fmt, ...) /* don't log */ { USED(fmt); } /************************************************* * Everything below here is copied from /sys/src/cmd/ndb/dn.c * without modification and can be recopied to update. */ int rrsupported(int type) { return type >= 0 && type < nelem(rrtname) && rrtname[type] != nil; } /* * convert an integer RR type to it's ascii name */ char* rrname(int type, char *buf, int len) { char *t; t = nil; if(type >= 0 && type < nelem(rrtname)) t = rrtname[type]; if(t==nil){ snprint(buf, len, "%d", type); t = buf; } return t; } /* * free a list of resource records and any related structs */ void rrfreelist(RR *rp) { RR *next; for(; rp; rp = next){ next = rp->next; rrfree(rp); } } void freeserverlist(Server *s) { Server *next; for(; s != nil; s = next){ next = s->next; free(s); } } /* * allocate a resource record of a given type */ RR* rralloc(int type) { RR *rp; rp = emalloc(sizeof(*rp)); rp->pc = getcallerpc(&type); rp->type = type; setmalloctag(rp, rp->pc); switch(type){ case Tsoa: rp->soa = emalloc(sizeof(*rp->soa)); rp->soa->slaves = nil; setmalloctag(rp->soa, rp->pc); break; case Tsrv: rp->srv = emalloc(sizeof(*rp->srv)); setmalloctag(rp->srv, rp->pc); break; case Tdnskey: case Tkey: rp->key = emalloc(sizeof(*rp->key)); setmalloctag(rp->key, rp->pc); break; case Tcaa: rp->caa = emalloc(sizeof(*rp->caa)); setmalloctag(rp->caa, rp->pc); break; case Tcert: rp->cert = emalloc(sizeof(*rp->cert)); setmalloctag(rp->cert, rp->pc); break; case Tsig: rp->sig = emalloc(sizeof(*rp->sig)); setmalloctag(rp->sig, rp->pc); break; case Tnull: rp->null = emalloc(sizeof(*rp->null)); setmalloctag(rp->null, rp->pc); break; case Topt: rp->opt = emalloc(sizeof(*rp->opt)); setmalloctag(rp->opt, rp->pc); break; default: if(rrsupported(rp->type)) break; rp->unknown = emalloc(sizeof(*rp->unknown)); setmalloctag(rp->unknown, rp->pc); } rp->ttl = 0; rp->expire = 0; rp->next = 0; return rp; } /* * free a resource record and any related structs */ void rrfree(RR *rp) { DN *dp; RR *nrp; Txt *t; assert(!rp->cached); dp = rp->owner; if(dp){ for(nrp = dp->rr; nrp; nrp = nrp->next) assert(nrp != rp); /* "rrfree of live rr" */ } switch(rp->type){ case Tsoa: freeserverlist(rp->soa->slaves); memset(rp->soa, 0, sizeof *rp->soa); /* cause trouble */ free(rp->soa); break; case Tsrv: memset(rp->srv, 0, sizeof *rp->srv); /* cause trouble */ free(rp->srv); break; case Tdnskey: case Tkey: free(rp->key->data); memset(rp->key, 0, sizeof *rp->key); /* cause trouble */ free(rp->key); break; case Tcert: free(rp->cert->data); memset(rp->cert, 0, sizeof *rp->cert); /* cause trouble */ free(rp->cert); break; case Tsig: free(rp->sig->data); memset(rp->sig, 0, sizeof *rp->sig); /* cause trouble */ free(rp->sig); break; case Tnull: free(rp->null->data); memset(rp->null, 0, sizeof *rp->null); /* cause trouble */ free(rp->null); break; case Tcaa: free(rp->caa->data); memset(rp->caa, 0, sizeof *rp->caa); /* cause trouble */ free(rp->caa); break; case Ttxt: while(t = rp->txt){ rp->txt = t->next; free(t->data); memset(t, 0, sizeof *t); /* cause trouble */ free(t); } break; case Topt: free(rp->opt->data); memset(rp->opt, 0, sizeof *rp->opt); /* cause trouble */ free(rp->opt); break; default: if(rrsupported(rp->type)) break; free(rp->unknown->data); memset(rp->unknown, 0, sizeof *rp->unknown); /* cause trouble */ free(rp->unknown); break; } memset(rp, 0, sizeof *rp); /* cause trouble */ free(rp); }