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* 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 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 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 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 213 p_seprintqd(Msg *m) 214 { 215 fmtrr(m, &dm.qd, 1); 216 donext(m); 217 return 0; 218 } 219 220 static int 221 p_seprintan(Msg *m) 222 { 223 fmtrr(m, &dm.an, 0); 224 donext(m); 225 return 0; 226 } 227 228 static int 229 p_seprintns(Msg *m) 230 { 231 fmtrr(m, &dm.ns, 1); 232 donext(m); 233 return 0; 234 } 235 236 static int 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* 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* 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* 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 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 354 ulong now = 0; 355 356 void 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/dns.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* 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 389 rrfreelist(RR *rp) 390 { 391 RR *next; 392 393 for(; rp; rp = next){ 394 next = rp->next; 395 rrfree(rp); 396 } 397 } 398 void 399 freeserverlist(Server *s) 400 { 401 Server *next; 402 403 for(; s != nil; s = next){ 404 next = s->next; 405 free(s); 406 } 407 } 408 409 /* 410 * allocate a resource record of a given type 411 */ 412 RR* 413 rralloc(int type) 414 { 415 RR *rp; 416 417 rp = emalloc(sizeof(*rp)); 418 rp->magic = RRmagic; 419 rp->pc = getcallerpc(&type); 420 rp->type = type; 421 switch(type){ 422 case Tsoa: 423 rp->soa = emalloc(sizeof(*rp->soa)); 424 rp->soa->slaves = nil; 425 break; 426 case Tkey: 427 rp->key = emalloc(sizeof(*rp->key)); 428 break; 429 case Tcert: 430 rp->cert = emalloc(sizeof(*rp->cert)); 431 break; 432 case Tsig: 433 rp->sig = emalloc(sizeof(*rp->sig)); 434 break; 435 case Tnull: 436 rp->null = emalloc(sizeof(*rp->null)); 437 break; 438 } 439 rp->ttl = 0; 440 rp->expire = 0; 441 rp->next = 0; 442 return rp; 443 } 444 445 /* 446 * free a resource record and any related structs 447 */ 448 void 449 rrfree(RR *rp) 450 { 451 DN *dp; 452 RR *nrp; 453 Txt *t; 454 455 assert(rp->magic = RRmagic); 456 assert(!rp->cached); 457 458 dp = rp->owner; 459 if(dp){ 460 assert(dp->magic == DNmagic); 461 for(nrp = dp->rr; nrp; nrp = nrp->next) 462 assert(nrp != rp); /* "rrfree of live rr" */; 463 } 464 465 switch(rp->type){ 466 case Tsoa: 467 freeserverlist(rp->soa->slaves); 468 free(rp->soa); 469 break; 470 case Tkey: 471 free(rp->key->data); 472 free(rp->key); 473 break; 474 case Tcert: 475 free(rp->cert->data); 476 free(rp->cert); 477 break; 478 case Tsig: 479 free(rp->sig->data); 480 free(rp->sig); 481 break; 482 case Tnull: 483 free(rp->null->data); 484 free(rp->null); 485 break; 486 case Ttxt: 487 while(rp->txt != nil){ 488 t = rp->txt; 489 rp->txt = t->next; 490 free(t->p); 491 free(t); 492 } 493 break; 494 } 495 496 rp->magic = ~rp->magic; 497 free(rp); 498 } 499