1 /*
2 * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997
3 * The Regents of the University of California. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that: (1) source code distributions
7 * retain the above copyright notice and this paragraph in its entirety, (2)
8 * distributions including binary code include the above copyright notice and
9 * this paragraph in its entirety in the documentation or other materials
10 * provided with the distribution, and (3) all advertising materials mentioning
11 * features or use of this software display the following acknowledgement:
12 * ``This product includes software developed by the University of California,
13 * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
14 * the University nor the names of its contributors may be used to endorse
15 * or promote products derived from this software without specific prior
16 * written permission.
17 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
18 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
19 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
20 */
21
22 #include <unistd.h>
23 #include <stdlib.h>
24
25 #include <argus_compat.h>
26
27 #include <rabins.h>
28 #include <argus_util.h>
29 #include <argus_client.h>
30 #include <argus_main.h>
31 #include <argus_filter.h>
32
33 #include <signal.h>
34 #include <ctype.h>
35 #include <argus/extract.h>
36
37 extern u_char *snapend;
38
39 #include "interface.h"
40 #include "nameser.h"
41
42 extern char ArgusBuf[];
43
44 static const char *ns_ops[] = {
45 "", " inv_q", " stat", " op3", " notify", " update", " op6", " op7",
46 " op8", " updataA", " updateD", " updateDA",
47 " updateM", " updateMA", " zoneInit", " zoneRef",
48 };
49
50 static const char *ns_resp[] = {
51 "", " FormErr", " ServFail", " NXDomain",
52 " NotImp", " Refused", " YXDomain", " YXRRSet",
53 " NXRRSet", " NotAuth", " NotZone", " Resp11",
54 " Resp12", " Resp13", " Resp14", " NoChange",
55 };
56
57 /* skip over a domain name */
58 static const u_char *
ns_nskip(register const u_char * cp)59 ns_nskip(register const u_char *cp)
60 {
61 register u_char i;
62
63 if (!TTEST2(*cp, 1))
64 return (NULL);
65 i = *cp++;
66 while (i) {
67 if ((i & INDIR_MASK) == INDIR_MASK)
68 return (cp + 1);
69 if ((i & INDIR_MASK) == EDNS0_MASK) {
70 int bitlen, bytelen;
71
72 if ((i & ~INDIR_MASK) != EDNS0_ELT_BITLABEL)
73 return(NULL); /* unknown ELT */
74 if (!TTEST2(*cp, 1))
75 return (NULL);
76 if ((bitlen = *cp++) == 0)
77 bitlen = 256;
78 bytelen = (bitlen + 7) / 8;
79 cp += bytelen;
80 } else
81 cp += i;
82 if (!TTEST2(*cp, 1))
83 return (NULL);
84 i = *cp++;
85 }
86 return (cp);
87 }
88
89 /* print a <domain-name> */
90 static const u_char *
blabel_print(const u_char * cp)91 blabel_print(const u_char *cp)
92 {
93 int bitlen, slen, b;
94 const u_char *bitp, *lim;
95 char tc;
96
97 if (!TTEST2(*cp, 1))
98 return(NULL);
99 if ((bitlen = *cp) == 0)
100 bitlen = 256;
101 slen = (bitlen + 3) / 4;
102 lim = cp + 1 + slen;
103
104 /* print the bit string as a hex string */
105 sprintf(&ArgusBuf[strlen(ArgusBuf)],"\\[x");
106 for (bitp = cp + 1, b = bitlen; bitp < lim && b > 7; b -= 8, bitp++) {
107 TCHECK(*bitp);
108 sprintf(&ArgusBuf[strlen(ArgusBuf)],"%02x", *bitp);
109 }
110 if (b > 4) {
111 TCHECK(*bitp);
112 tc = *bitp++;
113 sprintf(&ArgusBuf[strlen(ArgusBuf)],"%02x", tc & (0xff << (8 - b)));
114 } else if (b > 0) {
115 TCHECK(*bitp);
116 tc = *bitp++;
117 sprintf(&ArgusBuf[strlen(ArgusBuf)],"%1x", ((tc >> 4) & 0x0f) & (0x0f << (4 - b)));
118 }
119 sprintf(&ArgusBuf[strlen(ArgusBuf)],"/%d]", bitlen);
120 return lim;
121 trunc:
122 sprintf(&ArgusBuf[strlen(ArgusBuf)],".../%d]", bitlen);
123 return NULL;
124 }
125
126 static int
labellen(const u_char * cp)127 labellen(const u_char *cp)
128 {
129 register u_int i;
130
131 if (!TTEST2(*cp, 1))
132 return(-1);
133 i = *cp;
134 if ((i & INDIR_MASK) == EDNS0_MASK) {
135 int bitlen, elt;
136 if ((elt = (i & ~INDIR_MASK)) != EDNS0_ELT_BITLABEL) {
137 sprintf(&ArgusBuf[strlen(ArgusBuf)],"<ELT %d>", elt);
138 return(-1);
139 }
140 if (!TTEST2(*(cp + 1), 1))
141 return(-1);
142 if ((bitlen = *(cp + 1)) == 0)
143 bitlen = 256;
144 return(((bitlen + 7) / 8) + 1);
145 } else
146 return(i);
147 }
148
149 static const u_char *
ns_nprint(register const u_char * cp,register const u_char * bp)150 ns_nprint(register const u_char *cp, register const u_char *bp)
151 {
152 register u_int i, l;
153 register const u_char *rp = NULL;
154 register int compress = 0;
155 int chars_processed;
156 int elt;
157 int data_size = snapend - bp;
158
159 if ((l = labellen(cp)) == (u_int)-1)
160 return(NULL);
161 if (!TTEST2(*cp, 1))
162 return(NULL);
163 chars_processed = 1;
164 if (((i = *cp++) & INDIR_MASK) != INDIR_MASK) {
165 compress = 0;
166 rp = cp + l;
167 }
168
169 if (i != 0)
170 while (i && cp < snapend) {
171 if ((i & INDIR_MASK) == INDIR_MASK) {
172 if (!compress) {
173 rp = cp + 1;
174 compress = 1;
175 }
176 if (!TTEST2(*cp, 1))
177 return(NULL);
178 cp = bp + (((i << 8) | *cp) & 0x3fff);
179 if ((l = labellen(cp)) == (u_int)-1)
180 return(NULL);
181 if (!TTEST2(*cp, 1))
182 return(NULL);
183 i = *cp++;
184 chars_processed++;
185
186 /*
187 * If we've looked at every character in
188 * the message, this pointer will make
189 * us look at some character again,
190 * which means we're looping.
191 */
192 if (chars_processed >= data_size) {
193 sprintf(&ArgusBuf[strlen(ArgusBuf)],"<LOOP>");
194 return (NULL);
195 }
196 continue;
197 }
198 if ((i & INDIR_MASK) == EDNS0_MASK) {
199 elt = (i & ~INDIR_MASK);
200 switch(elt) {
201 case EDNS0_ELT_BITLABEL:
202 if (blabel_print(cp) == NULL)
203 return (NULL);
204 break;
205 default:
206 /* unknown ELT */
207 sprintf(&ArgusBuf[strlen(ArgusBuf)],"<ELT %d>", elt);
208 return(NULL);
209 }
210 } else {
211 if (fn_printn(cp, l, snapend, ArgusBuf))
212 return(NULL);
213 }
214
215 cp += l;
216 chars_processed += l;
217 sprintf(&ArgusBuf[strlen(ArgusBuf)], "%c", '.');
218 if ((l = labellen(cp)) == (u_int)-1)
219 return(NULL);
220 if (!TTEST2(*cp, 1))
221 return(NULL);
222 i = *cp++;
223 chars_processed++;
224 if (!compress)
225 rp += l + 1;
226 }
227 else
228 sprintf(&ArgusBuf[strlen(ArgusBuf)], "%c", '.');
229 return (rp);
230 }
231
232 /* print a <character-string> */
233 static const u_char *
ns_cprint(register const u_char * cp)234 ns_cprint(register const u_char *cp)
235 {
236 register u_int i;
237
238 if (!TTEST2(*cp, 1))
239 return (NULL);
240 i = *cp++;
241 if (fn_printn(cp, i, snapend, ArgusBuf))
242 return (NULL);
243 return (cp + i);
244 }
245
246 /* http://www.iana.org/assignments/dns-parameters */
247 struct tok ns_type2str[] = {
248 { T_A, "A" }, /* RFC 1035 */
249 { T_NS, "NS" }, /* RFC 1035 */
250 { T_MD, "MD" }, /* RFC 1035 */
251 { T_MF, "MF" }, /* RFC 1035 */
252 { T_CNAME, "CNAME" }, /* RFC 1035 */
253 { T_SOA, "SOA" }, /* RFC 1035 */
254 { T_MB, "MB" }, /* RFC 1035 */
255 { T_MG, "MG" }, /* RFC 1035 */
256 { T_MR, "MR" }, /* RFC 1035 */
257 { T_NULL, "NULL" }, /* RFC 1035 */
258 { T_WKS, "WKS" }, /* RFC 1035 */
259 { T_PTR, "PTR" }, /* RFC 1035 */
260 { T_HINFO, "HINFO" }, /* RFC 1035 */
261 { T_MINFO, "MINFO" }, /* RFC 1035 */
262 { T_MX, "MX" }, /* RFC 1035 */
263 { T_TXT, "TXT" }, /* RFC 1035 */
264 { T_RP, "RP" }, /* RFC 1183 */
265 { T_AFSDB, "AFSDB" }, /* RFC 1183 */
266 { T_X25, "X25" }, /* RFC 1183 */
267 { T_ISDN, "ISDN" }, /* RFC 1183 */
268 { T_RT, "RT" }, /* RFC 1183 */
269 { T_NSAP, "NSAP" }, /* RFC 1706 */
270 { T_NSAP_PTR, "NSAP_PTR" },
271 { T_SIG, "SIG" }, /* RFC 2535 */
272 { T_KEY, "KEY" }, /* RFC 2535 */
273 { T_PX, "PX" }, /* RFC 2163 */
274 { T_GPOS, "GPOS" }, /* RFC 1712 */
275 { T_AAAA, "AAAA" }, /* RFC 1886 */
276 { T_LOC, "LOC" }, /* RFC 1876 */
277 { T_NXT, "NXT" }, /* RFC 2535 */
278 { T_EID, "EID" }, /* Nimrod */
279 { T_NIMLOC, "NIMLOC" }, /* Nimrod */
280 { T_SRV, "SRV" }, /* RFC 2782 */
281 { T_ATMA, "ATMA" }, /* ATM Forum */
282 { T_NAPTR, "NAPTR" }, /* RFC 2168, RFC 2915 */
283 { T_A6, "A6" }, /* RFC 2874 */
284 { T_DNAME, "DNAME" }, /* RFC 2672 */
285 { T_OPT, "OPT" }, /* RFC 2671 */
286 { T_UINFO, "UINFO" },
287 { T_UID, "UID" },
288 { T_GID, "GID" },
289 { T_UNSPEC, "UNSPEC" },
290 { T_UNSPECA, "UNSPECA" },
291 { T_TKEY, "TKEY" }, /* RFC 2930 */
292 { T_TSIG, "TSIG" }, /* RFC 2845 */
293 { T_IXFR, "IXFR" }, /* RFC 1995 */
294 { T_AXFR, "AXFR" }, /* RFC 1035 */
295 { T_MAILB, "MAILB" }, /* RFC 1035 */
296 { T_MAILA, "MAILA" }, /* RFC 1035 */
297 { T_ANY, "ANY" },
298 { 0, NULL }
299 };
300
301 struct tok ns_class2str[] = {
302 { C_IN, "IN" }, /* Not used */
303 { C_CHAOS, "CHAOS" },
304 { C_HS, "HS" },
305 { C_ANY, "ANY" },
306 { 0, NULL }
307 };
308
309 /* print a query */
310 static const u_char *
ns_qprint(register const u_char * cp,register const u_char * bp,int is_mdns)311 ns_qprint(register const u_char *cp, register const u_char *bp, int is_mdns)
312 {
313 register const u_char *np = cp;
314 register u_int i;
315
316 cp = ns_nskip(cp);
317
318 if (cp == NULL || !TTEST2(*cp, 4))
319 return(NULL);
320
321 /* print the qtype and qclass (if it's not IN) */
322 i = EXTRACT_16BITS(cp);
323 cp += 2;
324 sprintf(&ArgusBuf[strlen(ArgusBuf)]," %s", tok2str(ns_type2str, "Type%d", i));
325 i = EXTRACT_16BITS(cp);
326 cp += 2;
327 if (is_mdns && i == (C_IN|C_CACHE_FLUSH))
328 sprintf(&ArgusBuf[strlen(ArgusBuf)]," (Cache flush)");
329 else if (i != C_IN)
330 sprintf(&ArgusBuf[strlen(ArgusBuf)]," %s", tok2str(ns_class2str, "(Class %d)", i));
331
332 sprintf(&ArgusBuf[strlen(ArgusBuf)],"? ");
333 cp = ns_nprint(np, bp);
334 return(cp ? cp + 4 : NULL);
335 }
336
337 /* print a reply */
338 static const u_char *
ns_rprint(register const u_char * cp,register const u_char * bp,int is_mdns)339 ns_rprint(register const u_char *cp, register const u_char *bp, int is_mdns)
340 {
341 register u_int class;
342 register u_short typ, len;
343 register const u_char *rp;
344
345 if (ArgusParser->vflag) {
346 sprintf(&ArgusBuf[strlen(ArgusBuf)], "%c", ' ');
347 if ((cp = ns_nprint(cp, bp)) == NULL)
348 return NULL;
349 } else
350 cp = ns_nskip(cp);
351
352 if (cp == NULL || !TTEST2(*cp, 10))
353 return (snapend);
354
355 /* print the type/qtype and class (if it's not IN) */
356 typ = EXTRACT_16BITS(cp);
357 cp += 2;
358 class = EXTRACT_16BITS(cp);
359 cp += 2;
360 if (is_mdns && class == (C_IN|C_CACHE_FLUSH))
361 sprintf(&ArgusBuf[strlen(ArgusBuf)]," (Cache flush)");
362 else if (class != C_IN && typ != T_OPT)
363 sprintf(&ArgusBuf[strlen(ArgusBuf)]," %s", tok2str(ns_class2str, "(Class %d)", class));
364
365 /* ignore ttl */
366 cp += 4;
367
368 len = EXTRACT_16BITS(cp);
369 cp += 2;
370
371 rp = cp + len;
372
373 sprintf(&ArgusBuf[strlen(ArgusBuf)]," %s", tok2str(ns_type2str, "Type%d", typ));
374 if (rp > snapend)
375 return(NULL);
376
377 switch (typ) {
378 case T_A: {
379 unsigned int addr = htonl(*(unsigned int *)cp);
380 if (!TTEST2(*cp, sizeof(struct in_addr)))
381 return(NULL);
382 sprintf(&ArgusBuf[strlen(ArgusBuf)]," %s", ipaddr_string(&addr));
383 break;
384 }
385
386 case T_NS:
387 case T_CNAME:
388 case T_PTR:
389 #ifdef T_DNAME
390 case T_DNAME:
391 #endif
392 sprintf(&ArgusBuf[strlen(ArgusBuf)], "%c", ' ');
393 if (ns_nprint(cp, bp) == NULL)
394 return(NULL);
395 break;
396
397 case T_SOA:
398 if (!ArgusParser->vflag)
399 break;
400 sprintf(&ArgusBuf[strlen(ArgusBuf)], "%c", ' ');
401 if ((cp = ns_nprint(cp, bp)) == NULL)
402 return(NULL);
403 sprintf(&ArgusBuf[strlen(ArgusBuf)], "%c", ' ');
404 if ((cp = ns_nprint(cp, bp)) == NULL)
405 return(NULL);
406 if (!TTEST2(*cp, 5 * 4))
407 return(NULL);
408 sprintf(&ArgusBuf[strlen(ArgusBuf)]," %u", EXTRACT_32BITS(cp));
409 cp += 4;
410 sprintf(&ArgusBuf[strlen(ArgusBuf)]," %u", EXTRACT_32BITS(cp));
411 cp += 4;
412 sprintf(&ArgusBuf[strlen(ArgusBuf)]," %u", EXTRACT_32BITS(cp));
413 cp += 4;
414 sprintf(&ArgusBuf[strlen(ArgusBuf)]," %u", EXTRACT_32BITS(cp));
415 cp += 4;
416 sprintf(&ArgusBuf[strlen(ArgusBuf)]," %u", EXTRACT_32BITS(cp));
417 cp += 4;
418 break;
419 case T_MX:
420 sprintf(&ArgusBuf[strlen(ArgusBuf)], "%c", ' ');
421 if (!TTEST2(*cp, 2))
422 return(NULL);
423 if (ns_nprint(cp + 2, bp) == NULL)
424 return(NULL);
425 sprintf(&ArgusBuf[strlen(ArgusBuf)]," %d", EXTRACT_16BITS(cp));
426 break;
427
428 case T_TXT:
429 while (cp < rp) {
430 sprintf(&ArgusBuf[strlen(ArgusBuf)]," \"");
431 cp = ns_cprint(cp);
432 if (cp == NULL)
433 return(NULL);
434 sprintf(&ArgusBuf[strlen(ArgusBuf)], "%c", '"');
435 }
436 break;
437
438 case T_SRV:
439 sprintf(&ArgusBuf[strlen(ArgusBuf)], "%c", ' ');
440 if (!TTEST2(*cp, 6))
441 return(NULL);
442 if (ns_nprint(cp + 6, bp) == NULL)
443 return(NULL);
444 sprintf(&ArgusBuf[strlen(ArgusBuf)],":%d %d %d", EXTRACT_16BITS(cp + 4),
445 EXTRACT_16BITS(cp), EXTRACT_16BITS(cp + 2));
446 break;
447
448 #ifdef INET6
449 case T_AAAA:
450 if (!TTEST2(*cp, sizeof(struct in6_addr)))
451 return(NULL);
452 sprintf(&ArgusBuf[strlen(ArgusBuf)]," %s", ip6addr_string(cp));
453 break;
454
455 case T_A6:
456 {
457 struct in6_addr a;
458 int pbit, pbyte;
459
460 if (!TTEST2(*cp, 1))
461 return(NULL);
462 pbit = *cp;
463 pbyte = (pbit & ~7) / 8;
464 if (pbit > 128) {
465 sprintf(&ArgusBuf[strlen(ArgusBuf)]," %u(bad plen)", pbit);
466 break;
467 } else if (pbit < 128) {
468 if (!TTEST2(*(cp + 1), sizeof(a) - pbyte))
469 return(NULL);
470 memset(&a, 0, sizeof(a));
471 memcpy(&a.s6_addr[pbyte], cp + 1, sizeof(a) - pbyte);
472 sprintf(&ArgusBuf[strlen(ArgusBuf)]," %u %s", pbit, ip6addr_string(&a));
473 }
474 if (pbit > 0) {
475 sprintf(&ArgusBuf[strlen(ArgusBuf)], "%c", ' ');
476 if (ns_nprint(cp + 1 + sizeof(a) - pbyte, bp) == NULL)
477 return(NULL);
478 }
479 break;
480 }
481 #endif /*INET6*/
482
483 case T_OPT:
484 sprintf(&ArgusBuf[strlen(ArgusBuf)]," UDPsize=%u", class);
485 break;
486
487 case T_UNSPECA: /* One long string */
488 if (!TTEST2(*cp, len))
489 return(NULL);
490 if (fn_printn(cp, len, snapend, ArgusBuf))
491 return(NULL);
492 break;
493
494 case T_TSIG:
495 {
496 if (cp + len > snapend)
497 return(NULL);
498 if (!ArgusParser->vflag)
499 break;
500 sprintf(&ArgusBuf[strlen(ArgusBuf)], "%c", ' ');
501 if ((cp = ns_nprint(cp, bp)) == NULL)
502 return(NULL);
503 cp += 6;
504 if (!TTEST2(*cp, 2))
505 return(NULL);
506 sprintf(&ArgusBuf[strlen(ArgusBuf)]," fudge=%u", EXTRACT_16BITS(cp));
507 cp += 2;
508 if (!TTEST2(*cp, 2))
509 return(NULL);
510 sprintf(&ArgusBuf[strlen(ArgusBuf)]," maclen=%u", EXTRACT_16BITS(cp));
511 cp += 2 + EXTRACT_16BITS(cp);
512 if (!TTEST2(*cp, 2))
513 return(NULL);
514 sprintf(&ArgusBuf[strlen(ArgusBuf)]," origid=%u", EXTRACT_16BITS(cp));
515 cp += 2;
516 if (!TTEST2(*cp, 2))
517 return(NULL);
518 sprintf(&ArgusBuf[strlen(ArgusBuf)]," error=%u", EXTRACT_16BITS(cp));
519 cp += 2;
520 if (!TTEST2(*cp, 2))
521 return(NULL);
522 sprintf(&ArgusBuf[strlen(ArgusBuf)]," otherlen=%u", EXTRACT_16BITS(cp));
523 cp += 2;
524 }
525 }
526 return (rp); /* XXX This isn't always right */
527 }
528
529 char *
ns_print(register const u_char * bp,u_int length,int is_mdns)530 ns_print(register const u_char *bp, u_int length, int is_mdns)
531 {
532 register const HEADER *np;
533 register int qdcount, ancount, nscount, arcount;
534 register const u_char *cp;
535 u_int16_t b2;
536
537 np = (const HEADER *)bp;
538 TCHECK(*np);
539 /* get the byte-order right */
540 qdcount = EXTRACT_16BITS(&np->qdcount);
541 ancount = EXTRACT_16BITS(&np->ancount);
542 nscount = EXTRACT_16BITS(&np->nscount);
543 arcount = EXTRACT_16BITS(&np->arcount);
544
545 if (DNS_QR(np)) {
546 /* this is a response */
547 sprintf(&ArgusBuf[strlen(ArgusBuf)],"%d%s%s%s%s%s%s",
548 EXTRACT_16BITS(&np->id),
549 ns_ops[DNS_OPCODE(np)],
550 ns_resp[DNS_RCODE(np)],
551 DNS_AA(np)? "*" : "",
552 DNS_RA(np)? "" : "-",
553 DNS_TC(np)? "|" : "",
554 DNS_AD(np)? "$" : "");
555
556 if (qdcount != 1)
557 sprintf(&ArgusBuf[strlen(ArgusBuf)]," [%dq]", qdcount);
558
559 /* Print QUESTION section on -vv */
560 cp = (const u_char *)(np + 1);
561 while (qdcount--) {
562 if (qdcount < EXTRACT_16BITS(&np->qdcount) - 1)
563 sprintf(&ArgusBuf[strlen(ArgusBuf)], "%c", ',');
564 if (ArgusParser->vflag > 1) {
565 sprintf(&ArgusBuf[strlen(ArgusBuf)]," q:");
566 if ((cp = ns_qprint(cp, bp, is_mdns)) == NULL)
567 goto trunc;
568 } else {
569 if ((cp = ns_nskip(cp)) == NULL)
570 goto trunc;
571 cp += 4; /* skip QTYPE and QCLASS */
572 }
573 }
574 sprintf(&ArgusBuf[strlen(ArgusBuf)]," %d/%d/%d", ancount, nscount, arcount);
575 if (ancount--) {
576 if ((cp = ns_rprint(cp, bp, is_mdns)) == NULL)
577 goto trunc;
578 while (cp < snapend && ancount--) {
579 sprintf(&ArgusBuf[strlen(ArgusBuf)], "%c", ',');
580 if ((cp = ns_rprint(cp, bp, is_mdns)) == NULL)
581 goto trunc;
582 }
583 }
584 if (ancount > 0)
585 goto trunc;
586 /* Print NS and AR sections on -vv */
587 if (ArgusParser->vflag > 1) {
588 if (cp < snapend && nscount--) {
589 sprintf(&ArgusBuf[strlen(ArgusBuf)]," ns:");
590 if ((cp = ns_rprint(cp, bp, is_mdns)) == NULL)
591 goto trunc;
592 while (cp < snapend && nscount--) {
593 sprintf(&ArgusBuf[strlen(ArgusBuf)], "%c", ',');
594 if ((cp = ns_rprint(cp, bp, is_mdns)) == NULL)
595 goto trunc;
596 }
597 }
598 if (nscount > 0)
599 goto trunc;
600 if (cp < snapend && arcount--) {
601 sprintf(&ArgusBuf[strlen(ArgusBuf)]," ar:");
602 if ((cp = ns_rprint(cp, bp, is_mdns)) == NULL)
603 goto trunc;
604 while (cp < snapend && arcount--) {
605 sprintf(&ArgusBuf[strlen(ArgusBuf)], "%c", ',');
606 if ((cp = ns_rprint(cp, bp, is_mdns)) == NULL)
607 goto trunc;
608 }
609 }
610 if (arcount > 0)
611 goto trunc;
612 }
613 }
614 else {
615 char tbuf[128];
616 bzero(tbuf, sizeof(tbuf));
617
618 /* this is a request */
619 sprintf(&ArgusBuf[strlen(ArgusBuf)],"%d%s%s%s", EXTRACT_16BITS(&np->id), ns_ops[DNS_OPCODE(np)],
620 DNS_RD(np) ? "+" : "",
621 DNS_CD(np) ? "%" : "");
622
623 /* any weirdness? */
624 b2 = EXTRACT_16BITS(((u_short *)np)+1);
625 if (b2 & 0x6cf)
626 sprintf(&tbuf[strlen(tbuf)]," [b2&3=0x%x]", b2);
627
628 if (DNS_OPCODE(np) == IQUERY) {
629 if (qdcount)
630 sprintf(&tbuf[strlen(tbuf)]," [%dq]", qdcount);
631 if (ancount != 1)
632 sprintf(&tbuf[strlen(tbuf)]," [%da]", ancount);
633 }
634 else {
635 if (ancount)
636 sprintf(&tbuf[strlen(tbuf)]," [%da]", ancount);
637 if (qdcount != 1)
638 sprintf(&tbuf[strlen(tbuf)]," [%dq]", qdcount);
639 }
640 if (nscount)
641 sprintf(&tbuf[strlen(tbuf)]," [%dn]", nscount);
642 if (arcount)
643 sprintf(&tbuf[strlen(tbuf)]," [%dau]", arcount);
644
645 if (strlen(tbuf) > 0) {
646 sprintf(&ArgusBuf[strlen(ArgusBuf)]," %s", tbuf);
647 } else {
648 sprintf(&ArgusBuf[strlen(ArgusBuf)]," [_]");
649 }
650
651 cp = (const u_char *)(np + 1);
652 if (qdcount--) {
653 cp = ns_qprint(cp, (const u_char *)np, is_mdns);
654 if (!cp)
655 goto trunc;
656 while (cp < snapend && qdcount--) {
657 cp = ns_qprint((const u_char *)cp,
658 (const u_char *)np,
659 is_mdns);
660 if (!cp)
661 goto trunc;
662 }
663 }
664 if (qdcount > 0)
665 goto trunc;
666
667 /* Print remaining sections on -vv */
668 if (ArgusParser->vflag > 1) {
669 if (ancount--) {
670 if ((cp = ns_rprint(cp, bp, is_mdns)) == NULL)
671 goto trunc;
672 while (cp < snapend && ancount--) {
673 sprintf(&ArgusBuf[strlen(ArgusBuf)], "%c", ',');
674 if ((cp = ns_rprint(cp, bp, is_mdns)) == NULL)
675 goto trunc;
676 }
677 }
678 if (ancount > 0)
679 goto trunc;
680 if (cp < snapend && nscount--) {
681 sprintf(&ArgusBuf[strlen(ArgusBuf)]," ns:");
682 if ((cp = ns_rprint(cp, bp, is_mdns)) == NULL)
683 goto trunc;
684 while (nscount-- && cp < snapend) {
685 sprintf(&ArgusBuf[strlen(ArgusBuf)], "%c", ',');
686 if ((cp = ns_rprint(cp, bp, is_mdns)) == NULL)
687 goto trunc;
688 }
689 }
690 if (nscount > 0)
691 goto trunc;
692 if (cp < snapend && arcount--) {
693 sprintf(&ArgusBuf[strlen(ArgusBuf)]," ar:");
694 if ((cp = ns_rprint(cp, bp, is_mdns)) == NULL)
695 goto trunc;
696 while (cp < snapend && arcount--) {
697 sprintf(&ArgusBuf[strlen(ArgusBuf)], "%c", ',');
698 if ((cp = ns_rprint(cp, bp, is_mdns)) == NULL)
699 goto trunc;
700 }
701 }
702 if (arcount > 0)
703 goto trunc;
704 }
705 }
706 sprintf(&ArgusBuf[strlen(ArgusBuf)]," (%d)", length);
707 return ArgusBuf;
708
709 trunc:
710 sprintf(&ArgusBuf[strlen(ArgusBuf)],"[|domain]");
711 return ArgusBuf;
712 }
713