Blob
1 #include <u.h>2 #include <libc.h>3 #include <ip.h>4 #include "dat.h"5 #include "protos.h"7 enum8 {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,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 */38 /* classes */39 Csym= 0, /* internal symbols */40 Cin= 1, /* internet */41 Ccs, /* CSNET (obsolete) */42 Cch, /* Chaos net */43 Chs, /* Hesiod (?) */45 /* class queries (all class types are also queries) */46 Call= 255, /* all classes */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 */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) */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 };73 typedef struct Hdr Hdr;74 struct Hdr75 {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 };85 static char*86 getstr(uchar **pp, int *len, uchar *ep)87 {88 uchar *p;89 int n;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 }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;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 }150 static char*151 tname(int type)152 {153 static char buf[20];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 }211 static char*212 cname(int class)213 {214 static char buf[40];216 if(class == Cin)217 return "";219 snprint(buf, sizeof buf, "class=%d", class);220 return buf;221 }223 #define PR(name, len) utfnlen(name, len), name225 extern int sflag;227 static int228 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;240 if(first){241 first = 0;242 quotefmtinstall();243 }245 if(m->pe - m->ps < sizeof(Hdr))246 return -1;247 h = (Hdr*)m->ps;248 m->pr = nil;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 }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;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;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;414 error:415 m->p = seprint(m->p, m->e, " packet error!");416 return 0;417 }419 Proto dns =420 {421 "dns",422 nil,423 nil,424 p_seprint,425 nil,426 nil,427 nil,428 defaultframer429 };