dns.c (7924B)
1 #include <u.h> 2 #include <libc.h> 3 #include <ip.h> 4 #include "dat.h" 5 #include "protos.h" 6 7 enum 8 { 9 /* RR types */ 10 Ta= 1, 11 Tns= 2, 12 Tmd= 3, 13 Tmf= 4, 14 Tcname= 5, 15 Tsoa= 6, 16 Tmb= 7, 17 Tmg= 8, 18 Tmr= 9, 19 Tnull= 10, 20 Twks= 11, 21 Tptr= 12, 22 Thinfo= 13, 23 Tminfo= 14, 24 Tmx= 15, 25 Ttxt= 16, 26 Trp= 17, 27 Tsig= 24, 28 Tkey= 25, 29 Taaaa= 28, 30 Tcert= 37, 31 32 /* query types (all RR types are also queries) */ 33 Tixfr= 251, /* incremental zone transfer */ 34 Taxfr= 252, /* zone transfer */ 35 Tmailb= 253, /* { Tmb, Tmg, Tmr } */ 36 Tall= 255, /* all records */ 37 38 /* classes */ 39 Csym= 0, /* internal symbols */ 40 Cin= 1, /* internet */ 41 Ccs, /* CSNET (obsolete) */ 42 Cch, /* Chaos net */ 43 Chs, /* Hesiod (?) */ 44 45 /* class queries (all class types are also queries) */ 46 Call= 255, /* all classes */ 47 48 /* opcodes */ 49 Oquery= 0<<11, /* normal query */ 50 Oinverse= 1<<11, /* inverse query */ 51 Ostatus= 2<<11, /* status request */ 52 Onotify= 4<<11, /* notify slaves of updates */ 53 Omask= 0xf<<11, /* mask for opcode */ 54 55 /* response codes */ 56 Rok= 0, 57 Rformat= 1, /* format error */ 58 Rserver= 2, /* server failure (e.g. no answer from something) */ 59 Rname= 3, /* bad name */ 60 Runimplimented= 4, /* unimplemented */ 61 Rrefused= 5, /* we don't like you */ 62 Rmask= 0xf, /* mask for response */ 63 Rtimeout= 0x10, /* timeout sending (for internal use only) */ 64 65 /* bits in flag word (other than opcode and response) */ 66 Fresp= 1<<15, /* message is a response */ 67 Fauth= 1<<10, /* true if an authoritative response */ 68 Ftrunc= 1<<9, /* truncated message */ 69 Frecurse= 1<<8, /* request recursion */ 70 Fcanrec= 1<<7, /* server can recurse */ 71 }; 72 73 typedef struct Hdr Hdr; 74 struct Hdr 75 { 76 uchar id[2]; 77 uchar flags[2]; 78 uchar qdcount[2]; 79 uchar ancount[2]; 80 uchar nscount[2]; 81 uchar arcount[2]; 82 }; 83 84 85 static char* 86 getstr(uchar **pp, int *len, uchar *ep) 87 { 88 uchar *p; 89 int n; 90 91 p = *pp; 92 n = *p++; 93 if(p+n > ep) 94 return nil; 95 *len = n; 96 *pp = p+n; 97 return (char*)p; 98 } 99 100 static char* 101 getname(uchar **pp, uchar *bp, uchar *ep) 102 { 103 static char buf[2][512]; 104 static int toggle; 105 char *tostart, *to; 106 char *toend; 107 int len, off, pointer, n; 108 uchar *p; 109 110 to = buf[toggle^=1]; 111 toend = to+sizeof buf[0]; 112 tostart = to; 113 p = *pp; 114 len = 0; 115 pointer = 0; 116 while(p < ep && *p){ 117 if((*p & 0xc0) == 0xc0){ 118 /* pointer to another spot in message */ 119 if(pointer == 0) 120 *pp = p + 2; 121 if(pointer++ > 10) 122 return nil; 123 off = ((p[0]<<8) + p[1]) & 0x3ff; 124 p = bp + off; 125 if(p >= ep) 126 return nil; 127 n = 0; 128 continue; 129 } 130 n = *p++; 131 if(to+n >= toend || p+n > ep) 132 return nil; 133 memmove(to, p, n); 134 to += n; 135 p += n; 136 if(*p){ 137 if(to >= toend) 138 return nil; 139 *to++ = '.'; 140 } 141 } 142 if(to >= toend || p >= ep) 143 return nil; 144 *to = 0; 145 if(!pointer) 146 *pp = ++p; 147 return tostart; 148 } 149 150 static char* 151 tname(int type) 152 { 153 static char buf[20]; 154 155 switch(type){ 156 case Ta: 157 return "a"; 158 case Tns: 159 return "ns"; 160 case Tmd: 161 return "md"; 162 case Tmf: 163 return "mf"; 164 case Tcname: 165 return "cname"; 166 case Tsoa: 167 return "soa"; 168 case Tmb: 169 return "mb"; 170 case Tmg: 171 return "mg"; 172 case Tmr: 173 return "mr"; 174 case Tnull: 175 return "null"; 176 case Twks: 177 return "wks"; 178 case Tptr: 179 return "ptr"; 180 case Thinfo: 181 return "hinfo"; 182 case Tminfo: 183 return "minfo"; 184 case Tmx: 185 return "mx"; 186 case Ttxt: 187 return "txt"; 188 case Trp: 189 return "rp"; 190 case Tsig: 191 return "sig"; 192 case Tkey: 193 return "key"; 194 case Taaaa: 195 return "aaaa"; 196 case Tcert: 197 return "cert"; 198 case Tixfr: 199 return "ixfr"; 200 case Taxfr: 201 return "axfr"; 202 case Tmailb: 203 return "mailb"; 204 case Tall: 205 return "all"; 206 } 207 snprint(buf, sizeof buf, "%d", type); 208 return buf; 209 } 210 211 static char* 212 cname(int class) 213 { 214 static char buf[40]; 215 216 if(class == Cin) 217 return ""; 218 219 snprint(buf, sizeof buf, "class=%d", class); 220 return buf; 221 } 222 223 #define PR(name, len) utfnlen(name, len), name 224 225 extern int sflag; 226 227 static int 228 p_seprint(Msg *m) 229 { 230 int i, pref; 231 Hdr *h; 232 uchar *p, *ep; 233 int an, ns, ar, rlen; 234 char *name, *prefix; 235 int len1, len2; 236 char *sym1, *sym2, *sep; 237 int type; 238 static int first = 1; 239 240 if(first){ 241 first = 0; 242 quotefmtinstall(); 243 } 244 245 if(m->pe - m->ps < sizeof(Hdr)) 246 return -1; 247 h = (Hdr*)m->ps; 248 m->pr = nil; 249 250 m->p = seprint(m->p, m->e, "id=%d flags=%04ux %d/%d/%d/%d", 251 NetS(h->id), NetS(h->flags), 252 NetS(h->qdcount), NetS(h->ancount), 253 NetS(h->nscount), NetS(h->arcount)); 254 sep = ")\n\t"; 255 if(sflag) 256 sep = ") "; 257 p = m->ps + sizeof(Hdr); 258 for(i=0; i<NetS(h->qdcount); i++){ 259 name = getname(&p, m->ps, m->pe); 260 if(name == nil || p+4 > m->pe) 261 goto error; 262 m->p = seprint(m->p, m->e, "%sq=(%q %s%s", 263 sep, name, tname(NetS(p)), cname(NetS(p+2))); 264 p += 4; 265 } 266 267 an = NetS(h->ancount); 268 ns = NetS(h->nscount); 269 ar = NetS(h->arcount); 270 while(an+ns+ar > 0){ 271 if(an > 0){ 272 prefix = "an"; 273 an--; 274 }else if(ns > 0){ 275 prefix = "ns"; 276 ns--; 277 }else{ 278 prefix = "ar"; 279 ar--; 280 } 281 name = getname(&p, m->ps, m->pe); 282 if(name == nil || p+10 > m->pe) 283 goto error; 284 type = NetS(p); 285 rlen = NetS(p+8); 286 ep = p+10+rlen; 287 if(ep > m->pe) 288 goto error; 289 m->p = seprint(m->p, m->e, "%s%s=(%q %s%s | ttl=%lud", 290 sep, prefix, name, tname(type), cname(NetS(p+2)), NetL(p+4), rlen); 291 p += 10; 292 switch(type){ 293 default: 294 p = ep; 295 break; 296 case Thinfo: 297 sym1 = getstr(&p, &len1, ep); 298 if(sym1 == nil) 299 goto error; 300 sym2 = getstr(&p, &len2, ep); 301 if(sym2 == nil) 302 goto error; 303 m->p = seprint(m->p, m->e, " cpu=%.*s os=%.*s", 304 PR(sym1, len1), 305 PR(sym2, len2)); 306 break; 307 case Tcname: 308 case Tmb: 309 case Tmd: 310 case Tmf: 311 case Tns: 312 case Tmg: 313 case Tmr: 314 case Tptr: 315 sym1 = getname(&p, m->ps, m->pe); 316 if(sym1 == nil) 317 goto error; 318 m->p = seprint(m->p, m->e, " %q", sym1); 319 break; 320 case Tminfo: 321 sym1 = getname(&p, m->ps, m->pe); 322 if(sym1 == nil) 323 goto error; 324 sym2 = getname(&p, m->ps, m->pe); 325 if(sym2 == nil) 326 goto error; 327 m->p = seprint(m->p, m->e, " %q %q", sym1, sym2); 328 break; 329 case Tmx: 330 if(p+2 >= ep) 331 goto error; 332 pref = NetS(p); 333 p += 2; 334 sym1 = getname(&p, m->ps, m->pe); 335 if(sym1 == nil) 336 goto error; 337 break; 338 case Ta: 339 if(p+4 > ep) 340 goto error; 341 m->p = seprint(m->p, m->e, " %V", p); 342 p += 4; 343 break; 344 case Taaaa: 345 if(p+16 > ep) 346 goto error; 347 m->p = seprint(m->p, m->e, " %I", p); 348 p += 16; 349 break; 350 case Tsoa: 351 sym1 = getname(&p, m->ps, m->pe); 352 if(sym1 == nil) 353 goto error; 354 sym2 = getname(&p, m->ps, m->pe); 355 if(sym2 == nil) 356 goto error; 357 if(p+20 > ep) 358 goto error; 359 m->p = seprint(m->p, m->e, " host=%q rmb=%q serial=%lud refresh=%lud retry=%lud expire=%lud minttl=%lud", 360 sym1, sym2, NetL(p), NetL(p+4), 361 NetL(p+8), NetL(p+12), NetL(p+16)); 362 break; 363 case Ttxt: 364 while(p < ep){ 365 sym1 = getstr(&p, &len1, ep); 366 if(sym1 == nil) 367 goto error; 368 m->p = seprint(m->p, m->e, " %.*q", PR(sym1, len1)); 369 } 370 break; 371 case Tnull: 372 m->p = seprint(m->p, m->e, " %.*H", rlen, p); 373 p += rlen; 374 break; 375 case Trp: 376 sym1 = getname(&p, m->ps, m->pe); 377 if(sym1 == nil) 378 goto error; 379 sym2 = getname(&p, m->ps, m->pe); 380 if(sym2 == nil) 381 goto error; 382 m->p = seprint(m->p, m->e, " rmb=%q rp=%q", sym1, sym2); 383 break; 384 case Tkey: 385 if(rlen < 4) 386 goto error; 387 m->p = seprint(m->p, m->e, " flags=%04ux proto=%d alg=%d %.*H", 388 NetS(p), p[3], p[4], rlen-4, p+4); 389 p += rlen; 390 break; 391 392 case Tsig: 393 if(rlen < 18) 394 goto error; 395 m->p = seprint(m->p, m->e, " type=%d alg=%d labels=%d ttl=%lud exp=%lud incep=%lud tag=%d %.*H", 396 NetS(p), p[3], p[4], NetL(p+4), NetL(p+8), NetL(p+12), NetS(p+16), 397 rlen-18, p+18); 398 p += rlen; 399 break; 400 401 case Tcert: 402 if(rlen < 5) 403 goto error; 404 m->p = seprint(m->p, m->e, " type=%d tag=%d alg=%d %.*H", 405 NetS(p), NetS(p+2), p[4], rlen-5, p+5); 406 p += rlen; 407 break; 408 } 409 if(p != ep) 410 goto error; 411 } 412 return 0; 413 414 error: 415 m->p = seprint(m->p, m->e, " packet error!"); 416 return 0; 417 } 418 419 Proto dns = 420 { 421 "dns", 422 nil, 423 nil, 424 p_seprint, 425 nil, 426 nil, 427 nil, 428 defaultframer 429 };