Blob


1 #include <u.h>
2 #include <libc.h>
3 #include <ip.h>
4 #include "dat.h"
5 #include "protos.h"
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,
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 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 };
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)
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;
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++ = '.';
142 if(to >= toend || p >= ep)
143 return nil;
144 *to = 0;
145 if(!pointer)
146 *pp = ++p;
147 return tostart;
150 static char*
151 tname(int type)
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";
207 snprint(buf, sizeof buf, "%d", type);
208 return buf;
211 static char*
212 cname(int class)
214 static char buf[40];
216 if(class == Cin)
217 return "";
219 snprint(buf, sizeof buf, "class=%d", class);
220 return buf;
223 #define PR(name, len) utfnlen(name, len), name
225 extern int sflag;
227 static int
228 p_seprint(Msg *m)
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();
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;
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--;
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));
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;
409 if(p != ep)
410 goto error;
412 return 0;
414 error:
415 m->p = seprint(m->p, m->e, " packet error!");
416 return 0;
419 Proto dns =
421 "dns",
422 nil,
423 nil,
424 p_seprint,
425 nil,
426 nil,
427 nil,
428 defaultframer
429 };